Segment allocation was explained briefly in the system overview
(chapter 2) and will be described in more detail
here. At cold reset time, EXOS builds up a list of all available RAM
segments, testing each one. The system will not function unless at least
32K (two segments) is available, and this must include segment
0FFh
which will be the system segment.
The lowest numbered RAM segment is taken out of the list and used as the page zero segment. This segment is never used in any form of allocation, it remains in Z80 page 0 for evermore.
Each RAM segment in the list can be in one of five different states which are:
The number of segments in each of these catagories can be determined by making a return system status EXOS call (code 20), which is explained in section 11.18.
The system segment (segment 0FFh) is always either allocated to the system or shared, it can never be free. All other segments are initially free except for the page zero segment which is outside this allocation scheme.
When the user makes an allocate segment EXOS call (code 24), if there are any free segments then one of them will be marked as allocated to the user and its segment number will be returned. The user can obtain as many segments as he likes in this way, limited only by the number of segments available. He can also free any segments which he has been allocated by making a free segment EXOS call (code 25).
Segments can become allocated to devices/extensions in several ways. A device driver can make an allocate segment call in the same way as the user, and if a segment is available it will be marked as allocated to a device/extension. Also a device can free segments in the same way as the user. Device/extension segments can also become allocated when a system extension is loaded (see section 10.5), or at startup time when an extension ROM is linked in (if the ROM requests any page1 RAM - see section 9.2.7).
Any segments allocated to devices/extensions or to the user will remain allocated after a warm reset. Also device/extension segments (but not user segments) will remain allocated when a new applications program is started up. Great care must be taken with any device that does allocate RAM segments to itself, to ensure that they are freed when the device has finished with them. Particular care must be taken with device initialisation since a device can be reinitialised and will still have the segments allocated, so it must remember this and not try to allocate itself new segments.
Whenever a user or a device/extension segment is requested, the lowest numbered available segment will be allocated. This ensures that the video segments, which have high numbers are kept as much as possible for the system so that they will be available for video channels.
Segments which are allocated to the system are basically used for channel RAM areas. The system uses RAM starting at the top of the system segment, down as far as necessary, possibly continuing into other segments. The top of the system segment is used for system variables, system stack, device RAM areas (see explanation of devices and device descriptors) and RAM areas for extension ROMs. All of these must be contained in the system segment. Below these there is a chain of channel descriptors, each with an associated RAM area, which can occupy as many segments as necessary. This will be described in more detail later.
Any segments which are used for channel RAM are marked as allocated to
the system. Each segment is used from the top down until it becomes full,
at which time another segment is allocated. Thus all system segments will
be fully used, except for the last one which may have some space left in
the bottom. There is a system variable, the EXOS boundary
which indicates the lowest address in the last system segment being used.
This value can be read by doing a read EXOS
boundary call (code 22) which returns a value in the range
0000h
to
New system segments can be allocated when a channel is opened or when a user device or system extension is linked in. When a channel is closed and the associated channel RAM is freed, this may result in the channel RAM usage moving out of a segment, in which case the segment will be freed and the EXOS boundary set up for the previous segment.
EXOS always allocates the highest numbered segment available when it needs a new segment for the system. This ensures that as much contiguous video RAM as possible is available for video channels, since video segments are the highest numbered. If a video segment becomes free while the system is using a nonvideo segment then the two will be swapped, although this will only be done next time a channel is opened.
There can be at most one RAM segment which is shared between the user and the system. If it exists, this will always be the last of the segments used by the system and will therefore contain the EXOS boundary as described above.
The user will be allocated a shared segment if he makes an
allocate segment call when there are
no free segments available. This fact is indicated by a specific status
code (.SHARE
) being returned by the
allocate segment call and the user will also be
told the current position of the EXOS boundary within this segment (see
section 11.22). A device or a system
extension can never be allocated a shared segment.
When the shared segment is allocated, a second boundary, called the user boundary, is created within the segment. This is in addition to the EXOS boundary and will initially have the same value. The user can at any time set a new position for the user boundary by making a set user boundary call (code 23). The user boundary can be set to any value from zero, up to and including the current setting of the EXOS boundary.
The user can use the segment from the start up to (but not including) the user boundary. EXOS is always using the segment from the top, down to (and including) the EXOS boundary. The area in between the two boundaries (which may be zero bytes) is no man's land and must not be used either by EXOS or by the user. However EXOS may, when it requires more RAM, move the EXOS boundary down as far as the user boundary. Similarly the user may move the user boundary up as far as the EXOS boundary when it needs more RAM. In this way the sharing of the segment between EXOS and the user is flexible and can change.
The segment can become unshared when a channel is closed, if EXOS no longer needs the segment. Also the user can free the shared segment in which case it will be flagged as allocated to the system. Having freed it, the user can always allocate it again of course.
When a channel is opened, if there is a shared segment then the EXOS boundary will usually have to be moved down. The user boundary should therefore be moved down as far as possible before opening a channel, to make space. Also, if a segment becomes free while there is a shared segment (it could have been freed by the user or by a device or extension), then EXOS is unable to allocate this to the system, although it can be allocated to the user. This means that it is advisable for the user to free the shared segment as soon as possible, maybe copying the contents into a new segment, in order to make the best use of RAM.
The System segment has been mentioned several times before. This section gives details of how it is used, and certain addresses. Further details of the various sections of RAM which can be allocated in it will be explained in the relevant sections.
The very top of the system segment contains a few variables which are at defined absolute addresses and can be used either by the user or by devices. Some of these have already been explained and others will be mentioned later. This list just gives the address and name of each one, along with a very brief description.
0BFFFh - USR_P3 | These are the contents of the four 0BFFEh - USR_P2 | paging registers when EXOS was last 0BFFDh - USR_P1 | called. Needed by devices when given 0BFFCh - USR_P0 | user addresses. 0BFFA/Bh - STACK_LIMIT Used for stack checking by devices which need more than the default amount of stack. 0BFF8/9h - RST_ADDR User's warm reset address. 0BFF6/7h - ST_POINTER The Z80 address of the statusline memory. The 42 bytes from this address onwards are the status line (see video driver specification). 0BFF4/5h - LP_POINTER The Z80 address of the start of the line parameter table (see video driver specification). 0BFF3h - PORTB5 Current value of general output port 0B5h. Used by various devices which access this port. See device driver specifications for a description. 0BFF2h - FLAG_SOFT_IRQ Triggers software interrupts. 0BFF0/1h - SECOND_COUNTER 16bit seconds counter. 0BFEFh - CRDISP_FLAG Flag for suppressing signon message 0BFED/Eh - USER_ISR Address of user's interrupt service routine, must be in page 0 and can be 0000h for no routine.
Below these fixed variables are all the internal system variables for the EXOS kernel,and also RAM areas for all the built in devices. These RAM areas include space for the line parameter table, character font, function key strings, sound queues, etc, as well as variables for each device. This area also includes space for the EXOS system stack which is used by all devices and system extensions. The size of this area is fixed for any one version of EXOS.
Below this fixed area is the list of RAM segments, and below that the list of extension ROMs, both of which vary in size depending on the number of extension RAM and ROM units connected. Below these lists is any system segment RAM allocated to extension ROMs when they are initialised (see later for explanation). These areas are all set up at cold reset time and then remain fixed.
Below this are the device descriptors for all built in device drivers and also any device drivers contained in extension ROMs. This includes any device RAM areas required by extension ROM devices. Built in devices have their device RAM allocated permanently in the fixed RAM area and so do not require any RAM here. This area is newly set up whenever a reset EXOS call is made, with the reset flags set to relink devices (see section 11.2), which is generally when a new applications program takes control.
When a user device is linked in, this area will be extended downwards to include any device RAM which the new device requests. This will result in everything below this area being moved down. Once allocated this device RAM will remain until devices are relinked, which will detroy the user device driver.
All of the above areas must lie wholly within the system segment. Any attempt to allocate RAM which would push them out of this segment will fail.
Immediately below the user device RAM area is the start of the channel RAM area. This must start in the system segment, but can run down into as many other segments as required. The channel RAM area includes a channel descriptor, and a RAM area for each channel which is currently open. These RAM areas can be moved around by EXOS when other channels are opened or closed, or user devices linked in. They are explained in detail in the section on channel RAM allocation.
It is clear from the above description that the sizes and addresses of most of these areas vary depending on the hardware and software configuration. However as an example the diagram below shows the addresses for a standard 64K machine with a single ROM cartridge, such as the ISBASIC cartridge, fitted. This should only be used as a guide since the exact sizes and addresses may vary in future versions. The addresses are given in Z80page 2, since this is where the system segment is normally accessed by EXOS and devices, although it can of course be paged in to any of the Z80pages.
Address Size BFFFh: +--------------------------------------------+ ... | Defined address variables ( list above ) | 17 BFEFh | | BFEEh: +--------------------------------------------+ | Internal EXOS system variables | 267 BEE3h: +--------------------------------------------+ | Device RAM areas for built in devices | 3212 B257h: +--------------------------------------------+ | Space for EXOS RAM resident code | 60 B21Bh: +--------------------------------------------+ | System stack | 1604 ABD5h: +--------------------------------------------+ | RAM segment list, 1 byte per segment | 4 ABD1h: +--------------------------------------------+ | Extension ROM list, 4 extra bytes per ROM | 12 ABC5h: +--------------------------------------------+ | RAM areas for extension ROMs | 0 +--------------------------------------------+ | Device descriptors for built in devices | 132 AB41h: +--------------------------------------------+ · | Start of channel descriptor chain | · · ·