<?xml version="1.0"?>
<!DOCTYPE riscos-prm PUBLIC "-//Gerph//DTD PRM documentation 1.02//EN"
                            "http://gerph.org/dtd/103/prm.dtd">

<riscos-prm>
<chapter title="Application Memory">
<section title="Introduction">
<p>
RISC OS memory is managed by Dynamic Areas. All areas of memory are assigned to a Dynamic Area
which controls the sizing of the area, what is mapped into the area, and what access control is applied
to it. These areas can themselves have certain properties which are managed by the Kernel - being sparse,
and being able to be shrunk on demand would be examples of these properties.
</p>

<p>
    Some modules using dynamic areas can provide operations to manage the content of those areas. A typical
    example of such management would be the Sprite Area which will be resized as operations are performed
    on it. One area that is considered special is the application space. This dynamic area is managed within
    the Operating System, and is treated a little differently by some parts of the system.
</p>

<p>
    The application space is managed as a special dynamic area whose contents can be switched in and out
    on demand. The contents of these areas are known as 'Application Memory Blocks'. There is
    a dedicated SWI, <reference type="swi" name="OS_AMBControl"/>, which mananges the contents of the
    application space and these 'AMBs'.
</p>

<p>
    This specialised management of the application space is largely historical, although there are
    certain performance improvements that are gained by the management being given preferential treatment.
</p>

</section>

<section title="Overview">
<p>
    Dynamic Area -1, known as the Application Space, usually contains the user mode code being executed
    by the system. This is the main place where code and data is stored for execution by the user. The
    application space lives at &hex;8000, and contains a single continous block of paged memory. This
    area of memory, and the dynamic area which describes it, is able to controlled by the
    <reference type="swi" name="OS_AMBControl"/> SWIs.
</p>

<p>
    Initially, only a single AMB exists, and is mapped into the application space. However, the WindowManager
    will manipulate the Dynamic Area to allow tasks to be switched in and out of the application space.
    The WindowManager concept of a 'Task' is its view on to the AMBs that it manages. The WindowManager
    hides the switching of application space from the user mode application tasks through the use of
    <reference type="swi" name="Wimp_Poll"/>.
</p>

<p>
    Historically, the WindowManager usurped the management of the application space from the Kernel to
    perform the task switches. With the introduction of RISC OS 3.7, OS_AMBControl returned the control of
    the application space to the Kernel. This allows other managers to also perform application space
    management in a similar manner to that of the WindowManager.
</p>
</section>


<section title="Technical details">
<p>
    The application space is managed through OS_AMBControl through an 'AMB handle'. This is an opaque
    identifier which identifies a specific mapping of memory - the AMB. AMBs must be created, destroyed
    and managed through the <reference type="swi" name="OS_AMBControl"/> SWI. However, other SWIs may
    also have an effect on the region.
</p>

<subsection title="Application Memory Blocks">
<p>
    Application Memory Blocks ('AMBs') have a number of properties which are managed by the OS_AMBControl
    system:
</p>
<p>
    <list>
        <item>They define the contents of a region of memory.</item>
        <item>The memory to which they refer can be visible to the system ('mapped in') or inaccessible ('mapped out').</item>
        <item>The memory may be mapped within the application space (at &hex;8000), or to an arbitary location in memory. This is used under special circumstances by the WindowManager for performance reasons.</item>
        <item>The number of pages which are used by the AMB.</item>
    </list>
</p>

<p>
    The system keeps track of the Current AMB. This is the AMB which is mapped at the base of the application
    space. AMBs mapped into other areas of memory are a concession to the historic operation of the WindowManager.
    The Current AMB is reflected in the sizes returned from OS_ChangeDynamicArea and OS_DynamicArea.
</p>

<p>
    The operating system interfaces which interact with the Current AMB are:
</p>
<p>
    <list>
        <item><p><reference type="swi" name="OS_ReadDynamicArea"/></p>
              <p>
              Calls to read the application space size will return the size of the current AMB.
              </p>
      </item>

        <item><p><reference type="swi" name="OS_ChangeDynamicArea"/></p>
              <p>
                On RISC OS Classic: Calls to change the application space size will fail.
                The size of the free pool must be changed to affect the AMB size.
                Removing pages from the Free Pool will add them to the AMB.
                Adding pages to the Free Pool will remove them from the AMB.
              </p>
              <p>
                On RISC OS Pyromaniac: Calls to change the application space will change the AMB.
                The Free Pool does not exist.
              </p>
              </item>

        <item><p><reference type="swi" name="OS_DynamicArea"/></p>
              <p>
                The Application Space is never enumerated by OS_DynamicArea.
              </p>
              </item>

        <item><p><reference type="swi" name="OS_ChangeEnvironment" reason="0"/></p>
              <p>Environment Handler 0 contains the memory limit.
                 This is the maximum address occupied by the Current AMB.
                 This value is updated by when the Current AMB is changed, or the size of the Current AMB is updated.</p>
              </item>

        <item><p><reference type="swi" name="OS_ChangeEnvironment" reason="14"/></p>
              <p>Environment Handler 14 contains the application space size.
                 This value is updated by when the Current AMB is changed, or the size of the Current AMB is updated.</p>
              <p>On RISC OS Classic: Writing to this environment handler will directly manipulate the logical size of
                 the dynamic area, and may have undesireable effects on the system.</p>
              </item>

        <item><p><reference type="swi" name="Wimp_SlotSize"/></p>
              <p>Changes the size of the WindowManager's understanding of the current AMB, and the
                 'next' slot.</p>
              </item>
    </list>
</p>
</subsection>

<subsection title="Caveats">
<p>
    Although the AMBs have been discussed in terms of their relationship to the Application Space dynamic
    area, there are special cases to be aware of.</p>

<subsubsection title="AMB existence">
<p>
    On RISC OS Classic: The application space dynamic area may exist without a corresponding AMB to manage
    it. Only on starting the WindowManager do AMBs begin to be used.
    Until that time (or after the WindowManager has relinquished control), the application space is managed
    only through the standard DynamicArea operations. This is because the application space
    dynamic area and memory is controlled by the Kernel, with OS_AMBControl manipulating the state when it
    is used. Until OS_AMBControl is used, the application space essentially just another region of memory.
</p>
<p>
    On RISC OS Pyromaniac: There is always an AMB handle present, and changes to it or dynamic areas will
    have the same effect. This is because the application space is owned by the OS_AMBControl system,
    and there is always a view on to application space which reflects OS_AMBControl's state.
</p>
</subsubsection>

<subsubsection title="Allocation of AMBs">
<p>
    On RISC OS Classic: On allocation of an AMB it will overlay the current mapping. If an AMB is already
    mapped into the application space, it may result in memory being present where the state of the
    dynamic areas (and OS_ValidateAddress) indicates there should not be any present. Always map out the
    AMB before use.
</p>
<p>
    On RISC OS Pyromaniac: On allocation of an AMB, the Current AMB is always mapped out first.
</p>
</subsubsection>


<subsubsection title="Partial mapping of AMBs">
<p>
    On RISC OS Classic: AMBs may be mapped anywhere in memory. This is to allow the WindowManager to perform
    fast copies between applications.
</p>
<p>
    On RISC OS Pyromaniac: AMBs may only be mapped into application space.
</p>
</subsubsection>

</subsection>

<subsection title="Lazy mapping">
<p>
    From RISC OS 4 onward, it is possible for the OS_AMBControl system to map regions of memory from the
    AMB only when required. The mapping still honours the maximum memory limits, and the pages are still
    allocated upfront, but page table updates may be deferred until an access requires the page. This
    was a performance improvement by avoiding large numbers of page table updates, and TLB or cache flushes
    on some systems. This behaviour was termed 'Lazy mapping'.
</p>
<p>
    This behaviour is optional, and should be transparent to the user application. It may have an impact
    on applications relying on DMA, or which manipulate page tables directly. The behaviour can be controlled
    through <reference type="swi" name="OS_AMBControl" reason="5"/>.
</p>

<p>
    RISC OS Pyromaniac does not support this behaviour - it does not have page tables for this to have an
    effect.
</p>
</subsection>

</section>


<section title="SWI calls">

<swi-definition name="OS_AMBControl"
                number="70"
                description="Application Memory Block management"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">
            <value-table>
                <value number="0"><reference type="swi" name="OS_AMBControl" reason="0" use-description="yes"/></value>
                <value number="1"><reference type="swi" name="OS_AMBControl" reason="1" use-description="yes"/></value>
                <value number="2"><reference type="swi" name="OS_AMBControl" reason="2" use-description="yes"/></value>
                <value number="3"><reference type="swi" name="OS_AMBControl" reason="3" use-description="yes"/></value>
                <value number="4"><reference type="swi" name="OS_AMBControl" reason="4" use-description="yes"/></value>
                <value number="5"><reference type="swi" name="OS_AMBControl" reason="5" use-description="yes"/></value>
                <value number="6">Reserved</value>
                <value number="7">Reserved</value>
                <value number="8"><reference type="swi" name="OS_AMBControl" reason="8" use-description="yes"/></value>
                <value number="9"><reference type="swi" name="OS_AMBControl" reason="9" use-description="yes"/></value>
            </value-table>
        </bit>
        <bit number="8-31">Flags dependant on reason code</bit>
    </bitfield-table>
 </register-use>
</entry>
<exit>
 <register-use number="0-3">Dependant on reason code</register-use>
</exit>

<use>
<p>This SWI is used to control and read information about the Application Memory Blocks which manage the Application Space. Consult the individual reason codes for more information.</p>
</use>

<compatibility>
    <version supplier="Acorn" riscos-lt="3.50" state="unsupported"/>
    <version supplier="Acorn" riscos-ge="3.50" state="supported"/>
    <version supplier="RISC OS Ltd" state="supported"/>
    <version supplier="RISC OS Open Ltd" state="supported"/>
    <version supplier="RISC OS Pyromaniac" riscos-ge="7.12" state="supported"/>
</compatibility>

<related>
<!-- <reference type="vector" name="BingleV" /> -->
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="0"
                reasonname="AllocateAMB"
                description="Allocate a new Application Memory Block"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">0</bit>
        <bit number="8-31">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
 <register-use number="1">Number of pages requested</register-use>
</entry>
<exit>
 <register-use number="1">Number of pages actually allocated</register-use>
 <register-use number="2">New AMB handle</register-use>
</exit>

<use>
<p> This SWI is used to allocate a new AMB.
    The AMB will be given the size specified by the number of pages requested, if they are available.
    If the requested size is not available, the number of pages which were able to be allocated will be returned.
</p>

<p>
    The newly allocated AMB becomes the Current AMB and will replace any AMB which is currently mapped in.
</p>

<p>
    Note: It is not guaranteed that the pages allocated will have been cleared; they may contain data from earlier system use.
</p>

</use>

<related>
    <reference type="swi" name="OS_AMBControl" />
    <reference type="swi" name="OS_AMBControl" reason="1"/>
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="1"
                reasonname="DeallocateAMB"
                description="Deallocate an Application Memory Block"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">1</bit>
        <bit number="8-31" name="Flags">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
 <register-use number="2">AMB handle</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="2" state="preserved"/>
</exit>

<use>
<p>This SWI is used to deallocate a given AMB. The memory associated with the AMB will be discarded.
    If the AMB handle refers to the Current AMB, it will be mapped out.</p>

<p>
    Note: It is not guaranteed that the pages released will have been cleared; they may be available when mapped to other locations.
</p>

</use>

<related>
    <reference type="swi" name="OS_AMBControl" />
    <reference type="swi" name="OS_AMBControl" reason="0"/>
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="2"
                reasonname="ResizeAMB"
                description="Change number of pages allocated to Application Memory Block"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">2</bit>
        <bit number="8-31" name="Flags">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
 <register-use number="1">Number of pages requested</register-use>
 <register-use number="2">AMB handle</register-use>
</entry>
<exit>
 <register-use number="1">Number of pages actually allocated</register-use>
 <register-use number="3">Previous number of pages allocated</register-use>
</exit>

<use>
<p>This SWI is used to change the number of pages which are allocated to the AMB, resizing it.
    If the AMB handle refers to the Current AMB, the pages will be mapped into memory.
    Otherwise, the AMB pages will be added or removed logically, but not physically in memory.
</p>

<p>
    Note: The pages added or removed may not be cleared.
</p>
</use>

<related>
    <reference type="swi" name="OS_AMBControl" />
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="3"
                reasonname="MapSlot"
                description="Map in or out an Application Memory Block"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">3</bit>
        <bit number="8" name="MapSome" state="clear">Map entire address space</bit>
        <bit number="8" state="set">Map partial address space</bit>
        <bit number="9-31" name="Flags">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
 <register-use number="1">Logical start address to map, or -1 to map out</register-use>
 <register-use number="2">AMB handle</register-use>
 <register-use number="3">Offset of start of mapping, in pages, if bit 8 of the flags is set</register-use>
 <register-use number="4">Number of pages to map, if bit 8 of the flags is set</register-use>
</entry>

<use>
<p>This SWI is used to control whether the AMB is mapped into the application space or not, or whether it is mapped into another area of memory (if bit 8 is set).</p>

<p>Partial address space mapping is only intended for specialised use for the WindowManager.
    It is not supported under RISC OS Pyromaniac.</p>
</use>

<related>
    <reference type="swi" name="OS_AMBControl" />
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="4"
                reasonname="AMBInfo"
                description="Read information on an Application Memory Block"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">4</bit>
        <bit number="8-31" name="Flags">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
 <register-use number="2">AMB handle</register-use>
</entry>
<exit>
 <register-use number="1">Current mapping start address, or -1 if mapped out (on RISC OS Classic, mapped out AMBs will return the address 'nowhere' - consult OS_ReadSysInfo for this location)</register-use>
 <register-use number="3">Current number of pages</register-use>
</exit>

<use>
<p>This SWI is used to read information about a specific AMB.</p>
</use>

<related>
    <reference type="swi" name="OS_AMBControl" />
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="5"
                reasonname="ControlLaziness"
                description="Control on demand mapping of Application Memory Blocks"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">5</bit>
        <bit number="8-31" name="Flags">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
 <register-use number="1">0 to disable laziness, 1 to enable laziness, -1 to read laziness</register-use>
 <register-use number="2">AMB handle</register-use>
</entry>
<exit>
 <register-use number="1">New laziness value</register-use>
</exit>

<use>
<p>This SWI is used to control whether lazy mapping of AMBs is performed. Lazy mapping is not supported on RISC OS Pyromaniac and will always return 0, to indicate it is not supported.</p>
</use>

<related>
    <reference type="swi" name="OS_AMBControl" />
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="8"
                reasonname="SystemInfo"
                description="System information"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">2</bit>
        <bit number="8-31" name="Flags">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
 <register-use number="1">Pointer to buffer for AMB information</register-use>
</entry>
<exit>
 <register-use number="0-1" state="preserved"/>
</exit>

<use>
<p>This SWI is used for diagnostic purposes to return the information about all currently allocated AMBs.
Call <reference type="swi" name="OS_AMBControl" reason="9"/> to read the number of AMBs currently in use,
to size the buffer.</p>

<p>
<offset-table>
    <offset number="0">Number of AMBs present in the table</offset>
    <offset number="4">Current AMB handle</offset>
    <offset number="8">List of AMB descriptors:
        <offset-table>
            <offset number="0">AMB handle</offset>
            <offset number="4">Number of pages</offset>
            <offset number="8">Logical address mapped to</offset>
            <offset number="12">Page protection flags<!-- Pyromaniac returns 0; check this --></offset>
        </offset-table>
    </offset>
</offset-table>
</p>

</use>

<related>
    <reference type="swi" name="OS_AMBControl" />
    <reference type="swi" name="OS_AMBControl" reason="9"/>
</related>

</swi-definition>


<swi-definition name="OS_AMBControl"
                number="70"
                reason="9"
                reasonname="CurrentInfo"
                description="Read the current Application Memory Block system state"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">

<entry>
 <register-use number="0">Reason code and flag bits:
    <bitfield-table>
        <bit number="0-7" name="Reason code">9</bit>
        <bit number="8-31" name="Flags">Reserved, must be 0</bit>
    </bitfield-table>
 </register-use>
</entry>
<exit>
 <register-use number="2">Current AMB handle</register-use>
 <register-use number="3">Number of AMBs present</register-use>
</exit>

<use>
<p>This SWI is used to read information about the number of AMBs and the Current AMB handle.</p>
</use>

<compatibility>
    <version supplier="RISC OS Pyromaniac" riscos-ge="7.12" state="supported"/>
</compatibility>

<related>
    <reference type="swi" name="OS_AMBControl" />
    <reference type="swi" name="OS_AMBControl" reason="8"/>
</related>

</swi-definition>

</section>



<section title="Error messages">

<error-definition name="AMBNoHandles"
                  number="1F7"
                  description="No AMB handles available"
                  >

<use>
<p>The error AMBNoHandles is returned if too many AMB handles have been created and a new one cannot be allocated.</p>
</use>

<related>
<reference type="swi" name="OS_AMBControl" reason="0" />
</related>

</error-definition>


<error-definition name="AMBBadHandle"
                  number="1F8"
                  description="Bad AMB handle"
                  >

<use>
<p>The error AMBBadReason is returned when the AMB handle supplied to an OS_AMBControl SWI is not valid.</p>
</use>

<related>
<reference type="swi" name="OS_AMBControl" />
</related>

</error-definition>


<error-definition name="AMBBadReason"
                  number="1F9"
                  description="Bad reason code supplied to OS_AMBControl"
                  >

<use>
<p>The error AMBBadReason is returned when reason code supplied to an OS_AMBControl SWI is not recognised.</p>
</use>

<related>
<reference type="swi" name="OS_AMBControl" />
</related>

</error-definition>


<error-definition name="AMBInvalidFlags"
                  number="1FA"
                  description="Invalid flags supplied to OS_AMBControl"
                  >

<use>
<p>The error AMBInvalidFlags is returned when flags supplied to an OS_AMBControl SWI were not recognised.</p>
</use>

<related>
<reference type="swi" name="OS_AMBControl" />
</related>

</error-definition>


<error-definition name="AMBBadMapSlot"
                  number="1FB"
                  description="Invalid mapping request to OS_AMBControl"
                  >

<use>
<p>The error AMBBadMapSlot is returned when an attempt has been made to map a slot to an invalid location in memory.</p>
</use>

<related>
<reference type="swi" name="OS_AMBControl" reason="3"/>
</related>

</error-definition>

</section>



</chapter>

<!-- MetaData -->
<meta>
 <maintainer>
  <email name="Gerph" address="gerph@gerph.org" />
 </maintainer>
 <disclaimer>
    <p>
        &copy; Gerph, 2020-23.
    </p>
 </disclaimer>

 <history>
  <revision number="1" author="Gerph" date="10 Nov 2020" title="Initial version">
    <change>Created</change>
  </revision>

  <revision number="2" author="Gerph" date="17 Sep 2023" title="Cleaned up version information">
    <change>Version information is now in compatibility sections for the new calls.</change>
  </revision>
 </history>

</meta>
</riscos-prm>
