EPOC16 Processes and Their Properties
EPOC16 is a preemptive multitasking operating system; at any time it can be running any number of processes (up to some limit). Much useful information about processes can be displayed with the SPY program.
Each process has a name, a task number, and a process ID. The task number runs from 1 upwards (the Series 3 is limited to 24), and a task number can be reused whenever a process terminates. The process ID consists of the address of the control block for the process in kernel memory in the bottom 12 bits, and a simple counter in the top 4 bits; this starts at 0 for the first process to use this control block, and is incremented whenever the block is reused.
The name of a process is normally the name of the program (1 to 8 characters), followed by .$
(or .@
for subtasks), and the task number as 2 decimal digits. The code for a process is placed in a segment called by the name of the program followed by .SC
. Thus it is not possible to run two programs with the same name at the same time.
Each process has a priority. Non-operating system processes are limited to priority 192; the normal priorities are 128 for foreground and 112 for background. Only the highest priority process(es) able to run will do so; all lower priority ones will wait.
System processes
There are two kinds of system processes: fixed ones and optional ones. The fixed processes are:
Process Name | Description |
SYS$NULL.$01 |
handles power off |
SYS$MANG.$02 |
the process and resource manager |
SYS$FSRV.$03 |
the file server |
SYS$WSRC.$04 |
the window server |
SYS$SHLL.$05 |
the process launcher and system screen |
TIME.$06 |
the time and alarm server |
The optional processes are:
Process Name | Description |
SYS$NCP.$?? |
the remote link manager |
Registers
Processes may use the data registers (AX
, BX
, CX
, DX
, SI
, and DI
) without restriction. The kernel may move memory segments about in memory at any time without warning; when it does so, those of the segment registers (CS
, DS
, ES
, and SS
) that appear to the kernel to be valid will be adjusted automatically. If it is desired to change these registers at any other time, it should therefore be done with interrupts disabled.
OPL uses CS
, DS
, and SS
, and these should not be altered by assembler code invoked from with OPL. ES
is not used by the OPL interpreter, and is normally left the same as DS
and SS
(which are always the same). Many system calls use data registers to hold pointers; a segment register is also used with each such pointer. The Psionics files SYSCALLS.n indicate when an address is using ES
; they do not distinguish DS
and SS
. Any assembler code called from OPL should exit with ES
equal to DS
.
The only other values that can usefully be placed in ES
are the kernel data segment (using system call GenDataSegment), and segments created with the system call SegCreate
. To do the former, just invoke INT $8F; ES
will then point to the kernel data segment, and accesses via ES
will behave just as if done with the system call GenGetOsData
(it is not possible to write in this way). The latter is done as follows:
; Assume the segment handle is in BX.
INT $8F
MOV ES,ES:[BX]
; ES now points to the start of the segment.
; If the segment moves, ES will change automatically.
; Before returning to OPL:
CLI ; with interrupts disabled
PUSH DS ; copy DS to ES
POP ES
STI ; and allow interrupts again
Memory
Each process has a single segment of memory. From zero upwards, this contains:
- reserved statics
- stack (grows downwards)
- normal statics
- heap (grows upwards)
The heap is divided into allocated and free cells. The SPY program shows the number and total byte count of each kind of cell. The kernel will remove free cells from the end of the heap when it needs space.
The stack is initialized to all 0xFF
; it must always hold at least 256 bytes to allow interrupts to be processed (otherwise panic 69 will occur). A typical stack size is 0xA00
. The SPY program allows the unused portion of the stack to be refilled with 0xFF
(to allow the high water mark to be reset).
The heap consists of consecutive cells:
Offset | Length | Description |
0 | 2 | length of data portion (L) |
2 | L+1 |
data portion (whose address is returned by allocators) @Is that right, or is it 2 to L-1 ?@ |
Cells are always aligned to even addresses, and for this and other reasons may be larger than requested.
Specific memory locations
The following table lists some specific use of memory locations.
Offset | Length | Description |
0 | 2 | Initialized to 0xDEAD ; should never change
|
2 | 4 | Used by the kernel |
6 | 2 | handle of the segment holding the fold tables @@ |
8 | 8 | used by the object oriented programming system |
16 | 2 | used by the kernel |
18 | 2 | address of block <P18> |
20 | 2 | handle of the application manager object |
22 | 4 | used by the window server |
26 | 4 | used by the OPL runtime system |
30 | 2 | used by the debugger |
32 | 1 | zero when address trapping is turned off (do not alter) |
33 | 1 | non-zero when the kernel is modifying the heap |
34 | 2 |
address of @if this word is zero, the process will not be sent X messages) |
36 | 2 |
address of a heap cell containing a cstr holding the full path name of the program being executed, followed by a |
38 | 2 |
not used by the kernel or OPL; used by the debugger |
40 | 14 |
not used by the kernel or OPL |
54 | 2 |
address of current dialog structure |
56 | 2 |
@@ |
58 | 2 |
non-zero if locked (by OPL "LOCK ON" or equivalent) |
60 | 2 |
address of |
62 | 2 |
address of cstr holding current file being processed |
64 |
maximum limit of stack (if floating point emulation is in use, the emulator uses offsets 64 to 767) |
Certain of these memory locations have names in the system documentation:
Process Name | Description |
34 | DatProcessNamePtr |
36 |
DatCommandPtr |
40 | DatApp1 |
42 |
DatApp2 |
44 | DatApp3 |
46 |
DatApp4 |
48 | DatApp5 |
50 |
DatApp6 |
52 | DatApp7 |
58 | DatLocked |
60 | DatStatusNamePtr |
62 | DatUsedPathNamePtr |
@Location winHandle
is the channel number of the console device.
Block <P18> has the following contents:
@this is a "wserv
" object@
Offset 32 (word): address of block <P18P32>
Block <P18P32> has the following contents:
Offset 12 (word): address of block <P18P32P12>
Block <P18P32P12> is created by the MINIT
keyword and destroyed by the MENU
keyword. Outside this range, the block is invalid, and the pointer in the <P18P32> block is invalid. Each MCARD
keyword can move this block, thus altering that pointer. The block has the following contents:
Offset | Length | Description |
0 | 1 | number of MCARD calls so far
|
1 | menu information blocks, in order of menu creation |
Offset | Length | Description |
0 | 2 | address of secondary menu information block |
2 | cstr |
Menu title |
Offset | Length | Description |
0 | 4 | [Only ever seen 0x7392A1DF ]
|
4 | 2 | number of items in the menu |
6 | 4 | [Only ever seen 1 so far] |
10 | 2 | address of item table |
Each item table has the following contents:
Offset | Length | Description |
0 | 1 | number of items in the menu |
1 | item information blocks, in order of item |
Each item information block has the following contents:
Offset | Length | Description |
0 | 1 | number of bytes in the block, excluding this one |
1 | 1 | Psion+ accelerator code (lowercased) |
2 | cstr |
item text |
Time process
The pending alarms can be located in the memory of the Time process. At some location between offset $0A00 and $0AFF is a block with the form:
Offset | Length | Description |
0 | 4 | 0x08040201 |
4 | 4 | 0x00402010 |
8 | 4 | Unknown (missing from Psionics files) |
12 | 4 | first alarm control block |
It is reported that on the Series 3c this has moved to somewhere between 0x0C00
and 0x0CFF
. It is also reported that on some versions the control block is at offset 10 or 15.
The alarm control blocks are in a circular list, with the last pointing to offset 12 (or 10 or 15) of the above block (which is not an alarm control block); if that location points to itself, there are no alarms. Each block has the form:
Offset | Length | Description |
0 | 2 | next alarm control block |
2 | 2 | reported that this is the second next alarm control block |
4 | 2 | Unknown (was missing from original Psionics File) |
6 | 2 | process ID of process owning alarm |
8 | 1 |
0 = clock alarm 1 = has time and date 2 = has date |
10 | 4 |
abstime alarm expires |
14 | 4 |
abstime displayed in alarm message |
18 | 10 qstr
|
name of alarm sound |
28 | 66 cstr
|
text displayed in alarm message |
93 | 163 |
[unknown; alleged to be part of the block] |
The built-in alarm sounds have names consisting of a single byte (thus offset 18 is 1 and offset 19 holds the name):
1=rings, 2=chimes, and 16=silence.
@System screen or Window Server (which?) places info about 14 application
buttons at DatApp1
.@
No Comments