DEFINITION MODULE ATOMIC; (* Copyright 1987 fred brooks LogicTek *) (* V1.0 *) FROM SYSTEM IMPORT PROCESS,ADDRESS; FROM Strings IMPORT String; CONST MAGIC = 92957; (* my b-day *) TYPE SIGNAL = POINTER TO ProcessDescriptor; GEMTYPE = ARRAY [0..0ffH] OF ADDRESS; (* This is the control record for all system process. Variable "currentprocess" points to the currently running process. The ready queue is implemented as a linked list round robin. *) (* The gemsave array contains important system vectors that are switched with every process. This allows programs to intercept trap vectors such as the GEMDOS TRAP 1 and still to allow the other programs to run correctly. current vectors saved are gemsave[0] gem workspace pointer gemsave[1] LINEA VECTOR 28H gemsave[2] GEMDOS TRAP 1 84H gemsave[3] GSX,GEM TRAP 2 88H gemsave[4] BIOS TRAP 13 B4H gemsave[5] XBIOS TRAP 14 B8H gemsave[6] linef VECTOR 2CH gemsave[7] level2 VECTOR 68H gemsave[8] level4 VECTOR 70H *) ProcessDescriptor = RECORD name : String; (* process name *) pid : INTEGER; (* process id *) cor : PROCESS; (* process coroutine *) pc : ADDRESS; (* process PC *) sr : CARDINAL; (* process SR *) ssp : ADDRESS; (* process super SR *) biosval : ADDRESS; (* bios call save ptr *) retval : ADDRESS; biosave : ARRAY [0..199] OF CARDINAL; gemsave : ARRAY [0..15] OF ADDRESS; termvec : ADDRESS; wsp : ADDRESS; (* process work space *) wspsize : LONGCARD; (* size of work space *) next : SIGNAL; (* ptr to next process *) ppid : INTEGER; (* parent id *) tmpcor : PROCESS; (* cor save variable *) ready : BOOLEAN; (* process run flag *) active : BOOLEAN; (* process alive flag *) intflag : BOOLEAN; (* process switched *) date : CARDINAL; (* date started *) time : CARDINAL; (* time started *) tick : LONGCARD; (* total 200hz clocks *) slice : LONGCARD; (* restart time 200hz *) pri : INTEGER; (* set length of run *) flags : ARRAY [0..2] OF LONGCARD; (* var *) ipname : String; (* program name *) iptail : String; (* program command *) ipenvstr : String; (* program env string *) return : INTEGER; (* function return *) errno : INTEGER; (* error number *) bpsave : GEMTYPE; (* save for gemdos *) END; (* Vector 144H points to variable that contains this record *) (* look at SYS.MOD for an example of use of these variables *) sysrequesttype = RECORD req : BOOLEAN; pid : INTEGER; magic : LONGCARD; END; spinttype = RECORD proc : PROC; pid : INTEGER; data : ADDRESS; END; sysvariable = RECORD currentprocess : POINTER TO SIGNAL; MULTI : POINTER TO BOOLEAN; slicebegin : POINTER TO LONGCARD; contextswitch : POINTER TO LONGCARD; command : POINTER TO String; request : POINTER TO sysrequesttype; CRON : POINTER TO PROC; spintenable : POINTER TO BITSET; spintmask : POINTER TO BITSET; spint : POINTER TO ARRAY [0..15] OF spinttype; bpsave : POINTER TO GEMTYPE; END; VAR currentprocess : SIGNAL; MULTI : BOOLEAN; slicebegin : LONGCARD; contextswitch : LONGCARD; command : String; request : sysrequesttype; CRON : PROC; spintenable : BITSET; spintmask : BITSET; spint : ARRAY [0..15] OF spinttype; bpsave : GEMTYPE; (* A spint is a software interrupt. It is called by setting it's bit in the spint enable mask. *) (* The CRON procedure variable is here to put your own procedure into the init scheduler in AMULTI this procedure will be run every 60 seconds. It is setup to the dummy procedure at first. to setup your own get sysvar then (sysvar.CRON:='your procedure') *) (* start the master context switch interrupt and setup system variables *) PROCEDURE Initsked; (* setup kernal to begin the system startup setup all buffers and procedures for AMULTI *) PROCEDURE InitProcesses; (* shutdown kernal and restore to normal gem state *) PROCEDURE EndProcesses; (* create a process for the AMULTI system, place in the scheduler ready list, start new process *) PROCEDURE StartProcess(VAR P: PROC; VAR n: LONGCARD; VAR priority: INTEGER; VAR pn: String); (* store the currentprocess and switch to next process in ready list *) PROCEDURE SwapProcess; (* end process and remove it from the ready list, free memory used by process *) PROCEDURE TermProcess(VAR id: INTEGER); (* tell scheduler not to run this process but keep in memory *) PROCEDURE SleepProcess(VAR id: INTEGER); (* tell scheduler to start running this process again if it was sleeping before *) PROCEDURE WakeupProcess(VAR id: INTEGER); (* V0.7 change process priority *) PROCEDURE ChangeProcessPriority(VAR id: INTEGER; VAR pri: INTEGER); (* turn on the scheduler interrupt, and start normal process switching *) PROCEDURE MultiBegin; (* turn off the scheduler interrupt, used to stop process switching in section of code that should not be swapped out *) PROCEDURE MultiEnd; (* check if flag is TRUE and lock out other process from changing it's state until procedure is over *) PROCEDURE CheckFlag(VAR flag: BOOLEAN): BOOLEAN; (* set flag to TRUE and lock out other process from changing it's state until procedure is over *) PROCEDURE SetFlag(VAR flag: BOOLEAN); (* set flag to FALSE and lock out other process from changing it's state until procedure is over *) PROCEDURE ResetFlag(VAR flag: BOOLEAN); (* check if flag is TRUE then set flag to FALSE while locking out other process from changing it's state until procedure is over *) PROCEDURE CheckResetFlag(VAR flag: BOOLEAN): BOOLEAN; END ATOMIC.