koreth@ssyx.ucsc.edu.ucsc.edu (Steven Grimm) (12/27/88)
Submitted-by: madsen@sask.usask.ca (Jorgen Madsen)
Posting-number: Volume 1, Issue 81
Archive-name: mx2v230/part01
[The binaries have been posted to comp.binaries.atari.st. -sg]
#!/bin/sh
# shar: Shell Archiver (v1.22)
#
# This is part 1 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
# Run the following text with /bin/sh to create:
# ACC.MOD
# ATOMIC.DEF
# ATOMIC.MOD
# BITSTUFF.DEF
# BITSTUFF.MOD
# CLI.MOD
# COM.MOD
# KILLLP.MOD
# LOGIN.DEF
# LOGIN.MOD
# LP.MOD
# MX2.MOD
# MX2LIB.C
# MX2NET.MOD
# MX2NOTES.TXT
# NETAUX.MOD
# NETMIDI.MOD
# NETWORK.DEF
# NETWORK.MOD
# NEWSYS.DEF
# NEWSYS.MOD
# PASSWD.MOD
# PIPE.DEF
# PIPE.MOD
# PS.MOD
# REDIR.MOD
# RUN.MOD
# SCANNER.DEF
# SCANNER.MOD
# SPAWN.MOD
# SPOOLER.MOD
# SQ.MOD
# SUBMIT.MOD
# SUBMITA.MOD
# SUBMITM.MOD
# SYS.MOD
# SYSCALL.DEF
# SYSCALL.MOD
# XA.MOD
# XMODEM.DEF
# XMODEM.MOD
# XMODEMR.MOD
# XMODEMT.MOD
# XS.MOD
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
exit 1; fi
sed 's/^X//' << 'SHAR_EOF' > ACC.MOD &&
X
X(* Copyright 1987,1988 fred brooks LogicTek *)
X(* *)
X(* *)
X(* First Release 12/8/87-FGB *)
X(* Added code to tell the context switcher the value of the *)
X(* ACC Super Stack to help it with multitasking gem programs *)
X(* 3/9/88-FGB *)
X(* *)
X
XMODULE acc;
X(*$T-,$S-*)
XFROM ATOMIC IMPORT VERSION;
XFROM SYSTEM IMPORT ADDRESS,ADR;
XFROM GEMDOS IMPORT Super,ConOut;
XFROM AESApplications IMPORT ApplInitialise;
XFROM AESMenus IMPORT MenuRegister;
XFROM AESEvents IMPORT EventMultiple;
XFROM GEMAESbase IMPORT AccessoryOpen;
XFROM AESForms IMPORT FormAlert;
X
XVAR
X applID : INTEGER; (* desk application ID *)
X menuID,waittime : INTEGER; (* menu ID *)
X Msg : ARRAY [0..16] OF INTEGER;
X handle, events, x,emask,b : INTEGER;
X ssv,stacksave : ADDRESS;
X superstack [144H] : ADDRESS;
X mx2run : BOOLEAN;
X
X
XBEGIN
X (* initialise application & install desk accessory *)
X applID := ApplInitialise();
X menuID := MenuRegister(applID,VERSION);
X emask:=48; (* timer and message *)
X waittime:=10000; (* check every 10 seconds to see if mx2 is running *)
X mx2run:=FALSE;
X
X ssv:=0;
X Super(ssv); (* in super mode *)
X superstack:=ssv; (* save superstack value for context switcher *)
X stacksave:=ssv;
X Super(ssv); (* return to gem stack space *)
X LOOP
X events := EventMultiple(emask,0,0,0,
X 0,0,0,0,0,
X 0,0,0,0,0,
X ADR(Msg),
X waittime,0,
X x,x,x,x,
X x,x);
X IF NOT mx2run THEN
X ssv:=0;
X Super(ssv); (* in super mode *)
X IF superstack#stacksave THEN
X waittime:=0; (* set timer to zero *)
X mx2run:=TRUE;
X END;
X Super(ssv); (* return to gem stack space *)
X END;
X IF Msg[0]=AccessoryOpen THEN
X IF emask=48 THEN b:=1 ELSE b:=2 END;
X ConOut(7c);
X x:=FormAlert(b,"[2][Fred Brooks LogicTek| | Switch|MX2 Desk Accessory][ON|OFF]");
X Msg[0]:=0;
X IF x=1 THEN
X emask:=48; (* message and timer *)
X ELSE
X emask:=16; (* just message *)
X END;
X END;
X END;
XEND acc.
SHAR_EOF
chmod 0600 ACC.MOD || echo "restore of ACC.MOD fails"
sed 's/^X//' << 'SHAR_EOF' > ATOMIC.DEF &&
XDEFINITION MODULE ATOMIC;
X
X(* Copyright 1987,1988 fred brooks LogicTek *)
X(* *)
X(* *)
X(* First Release 12/8/87-FGB *)
X(* Added variable parm to StartProcess to pass info to process *)
X(* in currentprocess.gemsave[15] 1/1/88-FGB *)
X(* *)
X(* Remove monitor priority. Each routine the switches processes *)
X(* must be protected from all interrupts by the IntEnd and *)
X(* IntBegin calls. If this is not done correctly the system *)
X(* system will bomb. 4/4/88-FGB *)
X(* *)
X
XFROM SYSTEM IMPORT ADDRESS,BYTE;
XFROM NEWSYS IMPORT PROCESS;
XFROM Strings IMPORT String;
X
XCONST MAGIC = 22261; (* somebodys b-day *)
X buflength = 1024;
X OTOS = LONGCARD(602CH); (* Old rom TOS *)
X MTOS = LONGCARD(87CEH); (* New rom MEGA TOS *)
X OLDDATE = 11201985H;
X NEWDATE = 04221987H;
X VERSION = " MX2 V2.3.0"; (* mx2 version number *)
XTYPE
X Gvectype = POINTER TO ADDRESS;
X buffer = ARRAY [0..buflength] OF BYTE;
X PIPE = RECORD
X pipename: String;
X buf : buffer;
X bufsize : CARDINAL;
X bufhead : CARDINAL;
X buftail : CARDINAL;
X cnt : CARDINAL;
X END;
X pipeptr = POINTER TO PIPE;
X(* these devices are defined for use with the MX2 port command
X dev0 thru dev7 are user defineable device drivers. By loading
X the addresses of the correct procedures into the DeviceTable for
X in, out and status custom devices may be defined.
X DeviceTable[dev0].bconstat:=Mybconstat;
X DeviceTable[dev0].bcostat:=Mybcostat;
X DeviceTable[dev0].bconin:=Mybconin;
X DeviceTable[dev0].bconout:=Mybconout;
X Will setup dev0 for use with the port command.
X
X sys port 4 -0 -0
X will cause the process with the PID of 4 to use dev0
X*)
X devicetype = (printer,aux,con,midi,null,dev0,dev1,dev2,dev3,
X dev4,dev5,dev6,dev7);
X devstattype = PROCEDURE(): BOOLEAN;
X devintype = PROCEDURE(): LONGCARD;
X devouttype = PROCEDURE(CHAR);
X
X devblocktype = RECORD
X bconstat : devstattype;
X bcostat : devstattype;
X bconin : devintype;
X bconout : devouttype;
X END;
X devtabletype = ARRAY [ORD(dev0)..ORD(dev7)] OF devblocktype;
X
XTYPE SIGNAL = POINTER TO ProcessDescriptor;
X GEMTYPE = ARRAY [0..0FFH] OF ADDRESS;
X pipetype = ARRAY [0..31] OF pipeptr;
X (* pipe names starting with mx2 or MX2 are reserved by the
X system *)
X(* This is the control record for all system process. Variable
X "currentprocess" points to the currently running process. The ready
X queue is implemented as a linked list round robin. *)
X
X(* The gemsave array contains important system vectors that are switched
X with every process. This allows programs to intercept trap vectors
X such as the GEMDOS TRAP 1 and still to allow the other programs
X to run correctly. current vectors saved are
X gemsave[0] gem workspace pointer
X gemsave[1] LINEA VECTOR 28H
X gemsave[2] GEMDOS TRAP 1 84H
X gemsave[3] GSX,GEM TRAP 2 88H
X gemsave[4] BIOS TRAP 13 B4H
X gemsave[5] XBIOS TRAP 14 B8H
X gemsave[6] linef VECTOR 2CH
X gemsave[7] level2 VECTOR 68H
X gemsave[8] level4 VECTOR 70H
X gemsave[9] _shell_p 4F6H
X gemsave[11] wait value (* V2.2.0 *)
X gemsave[12] wait mask (* V2.2.0 *)
X gemsave[13] sleep timer variable
X gemsave[14] timer flag variable
X gemsave[15] init parameter for process
X
X misc[0] priority work variable
X*)
X
X ProcessDescriptor =
X RECORD
X name : String; (* process name *)
X pid : INTEGER; (* process id *)
X cor : PROCESS; (* process coroutine *)
X pc : ADDRESS; (* process PC *)
X sr : CARDINAL; (* process SR *)
X ssp : ADDRESS; (* process super SR *)
X biosval : ADDRESS; (* bios call save ptr *)
X retval : ADDRESS;
X biosave : ARRAY [0..225] OF CARDINAL;
X gemsave : ARRAY [0..15] OF ADDRESS;
X termvec : ADDRESS;
X wsp : ADDRESS; (* process work space *)
X wspsize : LONGCARD; (* size of work space *)
X next : SIGNAL; (* ptr to next process *)
X ppid : INTEGER; (* parent id *)
X tmpcor : PROCESS; (* cor save variable *)
X ready : BOOLEAN; (* process run flag *)
X active : BOOLEAN; (* process alive flag *)
X intflag : BOOLEAN; (* process switched *)
X date : CARDINAL; (* date started *)
X time : CARDINAL; (* time started *)
X tick : LONGCARD; (* total 200hz clocks *)
X slice : LONGCARD; (* restart time 200hz *)
X pri : INTEGER; (* set length of run *)
X flags : ARRAY [0..2] OF LONGCARD; (* var *)
X(* flags[0] is default drive of process that called the kernel
X flags[1] is address of process to be added to ready list of kernel
X flags[2] is size of process stack or workspace
X*)
X ipname : String; (* program name *)
X iptail : String; (* program command *)
X ipenvstr : String; (* program env string *)
X return : INTEGER; (* function return *)
X errno : INTEGER; (* error number *)
X bpsave : GEMTYPE; (* save for gemdos *)
X Iport : devicetype;
X Oport : devicetype;
X waitloc : POINTER TO LONGCARD; (* V2.2.0 *)
X misc : ARRAY [0..8] OF INTEGER;
X END;
X
X(* Vector 144H points to variable that contains this record *)
X(* look at SYS.MOD for an example of use of these variables *)
X
X sysrequesttype =
X RECORD
X req : BOOLEAN;
X pid : INTEGER;
X magic : LONGCARD;
X END;
X
X spinttype =
X RECORD
X proc : PROC;
X pid : INTEGER;
X data : ADDRESS;
X END;
X
X StartProcesstype = PROCEDURE(VAR PROC,VAR LONGCARD,
X VAR INTEGER,VAR String,
X VAR ADDRESS);
X SwapProcesstype = PROCEDURE;
X TermProcesstype = PROCEDURE(VAR INTEGER);
X NextPidtype = PROCEDURE(): INTEGER;
X SleepProcesstype = PROCEDURE(VAR INTEGER);
X WakeupProcesstype = PROCEDURE(VAR INTEGER);
X ChangeProcessPrioritytype = PROCEDURE(VAR INTEGER,VAR INTEGER);
X MultiBegintype = PROCEDURE;
X MultiEndtype = PROCEDURE;
X DozeProcesstype = PROCEDURE(VAR INTEGER,VAR LONGCARD);
X WaitProcesstype = PROCEDURE(VAR INTEGER,VAR ADDRESS,
X VAR LONGCARD, VAR LONGCARD,
X VAR LONGCARD);
X
X sysvariable =
X RECORD
X currentprocess : POINTER TO SIGNAL;
X MULTI : POINTER TO BOOLEAN;
X slicebegin : POINTER TO LONGCARD;
X contextswitch : POINTER TO LONGCARD;
X command : POINTER TO String;
X request : POINTER TO sysrequesttype;
X CRON : POINTER TO PROC;
X spintenable : POINTER TO BITSET;
X spintmask : POINTER TO BITSET;
X spint : POINTER TO ARRAY [0..15] OF spinttype;
X bpsave : POINTER TO GEMTYPE;
X pipes : POINTER TO pipetype;
X sysmemsize : POINTER TO LONGCARD;
X gemsaveGvec : POINTER TO Gvectype;
X StartProcess : StartProcesstype;
X SwapProcess : SwapProcesstype;
X TermProcess : TermProcesstype;
X NextPid : NextPidtype;
X SleepProcess : SleepProcesstype;
X WakeupProcess : WakeupProcesstype;
X ChangeProcessPriority : ChangeProcessPrioritytype;
X MultiBegin : MultiBegintype;
X MultiEnd : MultiEndtype;
X DozeProcess : DozeProcesstype;
X WaitProcess : WaitProcesstype;
X CronActive : POINTER TO BOOLEAN;
X DeviceTable : POINTER TO devtabletype;
X END;
X
XVAR currentprocess : SIGNAL;
X MULTI : BOOLEAN;
X slicebegin : LONGCARD;
X contextswitch : LONGCARD;
X command : String;
X request : sysrequesttype;
X CRON : PROC;
X spintenable : BITSET;
X spintmask : BITSET;
X spint : ARRAY [0..15] OF spinttype;
X bpsave : GEMTYPE;
X pipes : pipetype;
X sysmemsize : LONGCARD;
X ROMDATE [0fc0018H] : LONGCARD;
X gemsaveGvec : Gvectype;
X CronActive : BOOLEAN;
X DeviceTable : devtabletype;
X (* A spint is a software interrupt. It is called by
X setting it's bit in the spint enable mask. Spints
X 0-3 are reserved by the system *)
X (* The CRON procedure variable is here to put your
X own procedure into the init scheduler in MX2 this
X procedure will be run every 30 seconds. It is setup to
X the dummy procedure at first. to setup your own
X get sysvar then (sysvar.CRON:='your procedure') *)
X
X(* start the master context switch interrupt and setup system variables *)
XPROCEDURE Initsked;
X
X(* setup kernal to begin the system startup setup all buffers and
X procedures for MX2 *)
XPROCEDURE InitProcesses;
X
X(* shutdown kernal and restore to normal gem state *)
X(* this currently does not work *)
XPROCEDURE EndProcesses;
X
X(* create a process for the MX2 system, place in the scheduler ready
X list, start new process *)
XPROCEDURE StartProcess(VAR P: PROC;
X VAR n: LONGCARD;
X VAR priority: INTEGER;
X VAR pn: String;
X VAR parm: ADDRESS);
X (* parm is the init parameter to be placed in
X gemsave[15] *)
X
X(* store the currentprocess and switch to next process in ready list *)
XPROCEDURE SwapProcess;
X
X(* end process and remove it from the ready list, free memory used by
X process *)
XPROCEDURE TermProcess(VAR id: INTEGER);
X
X(* return the next pid the system will use for a new process *)
XPROCEDURE NextPid(): INTEGER;
X
X(* tell scheduler not to run this process but keep in memory *)
XPROCEDURE SleepProcess(VAR id: INTEGER);
X
X(* tell scheduler to sleep for msec 1000th of a second *)
XPROCEDURE DozeProcess(VAR id: INTEGER; VAR msec: LONGCARD);
X
X(* Sleep process until the contents of 'loc' equals 'value AND mask'.
Xmsec is the timeout value in milliseconds if set the 0 it waits forever *)
XPROCEDURE WaitProcess(VAR id: INTEGER; VAR loc: ADDRESS;
X VAR value,mask,msec: LONGCARD);
X
X(* tell scheduler to start running this process again if it was sleeping
X before *)
XPROCEDURE WakeupProcess(VAR id: INTEGER);
X
X(* V0.7 change process priority *)
XPROCEDURE ChangeProcessPriority(VAR id: INTEGER; VAR pri: INTEGER);
X
X(* turn on the scheduler interrupt, and start normal process switching *)
XPROCEDURE MultiBegin;
X
X(* turn off the scheduler interrupt, used to stop process switching in
X section of code that should not be swapped out *)
XPROCEDURE MultiEnd;
X
X(* check if flag is TRUE and lock out other process from changing it's
X state until procedure is over *)
XPROCEDURE CheckFlag(VAR flag: BOOLEAN): BOOLEAN;
X
X(* set flag to TRUE and lock out other process from changing it's
X state until procedure is over *)
XPROCEDURE SetFlag(VAR flag: BOOLEAN);
X
X(* set flag to FALSE and lock out other process from changing it's
X state until procedure is over *)
XPROCEDURE ResetFlag(VAR flag: BOOLEAN);
X
X(* check if flag is TRUE then set flag to FALSE while locking out other
X process from changing it's state until procedure is over *)
XPROCEDURE CheckResetFlag(VAR flag: BOOLEAN): BOOLEAN;
X
XEND ATOMIC.
X
SHAR_EOF
chmod 0600 ATOMIC.DEF || echo "restore of ATOMIC.DEF fails"
sed 's/^X//' << 'SHAR_EOF' > ATOMIC.MOD &&
X
X(* Copyright 1987,1988 fred brooks LogicTek *)
X(* *)
X(* *)
X(* First Release 12/8/87-FGB *)
X(* *)
X(* Modified TermProcess to also kill all the children processes *)
X(* of the parent. Changed FindProcess not to find zombies *)
X(* 12/11/87-FGB *)
X(* *)
X(* Added variable parm to StartProcess to pass info to process *)
X(* in currentprocess.gemsave[15] 1/1/88-FGB *)
X(* The PID of the new process will be returned in variable parm *)
X(* 2/24/88-FGB *)
X(* *)
X(* Added DozeProcess to allow timed a sleep of processes *)
X(* 2/21/88-FGB *)
X(* *)
X(* Remove monitor priority. Each routine the switches processes *)
X(* must be protected from all interrupts by the IntEnd and *)
X(* IntBegin calls. If this is not done correctly the system *)
X(* system will bomb. 4/4/88-FGB *)
X(* *)
X
X
X(*$T-,$S-,$A+ *)
XIMPLEMENTATION MODULE ATOMIC;
X
XFROM SYSTEM IMPORT ADR,TSIZE,
X CODE,SETREG,ADDRESS,REGISTER;
XFROM NEWSYS IMPORT NEWPROCESS,PROCESS,TRANSFER,IOTRANSFER;
XFROM XBIOS IMPORT SuperExec;
XFROM BitStuff IMPORT LAnd;
X
XFROM GEMDOS IMPORT GetTime,GetDate,Super;
X
XFROM Storage IMPORT ALLOCATE,DEALLOCATE;
X
XFROM Strings IMPORT String;
X
XTYPE workspace = ARRAY [0..254] OF CARDINAL;
X savetype = POINTER TO ARRAY [0..22] OF CARDINAL;
X sigs = (sleep,wakeup,terminate,trace,routine,
X program,wait,gem,tos);
X CPFlagtype = SET OF sigs;
X CPFlagptrtype = POINTER TO CPFlagtype;
X
XCONST trapvec = 110H; (* vector on IOTRANSFER *)
X offsetvec = 140H; (* offset IOTRANSFER vector *)
X intnum = 4; (* interrupt number on MFP *)
X
XVAR s0,s1,s2,schedproc,s,
X initproc,lastproc : SIGNAL;
X kin : ARRAY [0..32] OF INTEGER;
X wsp0,wsp1,wsp2,wsp3 : workspace;
X wsp,bios : ADDRESS;
X etimer [400H] : ADDRESS;
X biospointer [4a2H] : ADDRESS;
X ptermvec [408H] : ADDRESS;
X trap [trapvec] : ADDRESS;
X memtop [436H] : ADDRESS;
X flock [43eH] : CARDINAL;
X hz200 [4baH] : LONGCARD;
X temphz200,TICKS : LONGCARD;
X sysvector [144H] : POINTER TO sysvariable;
X accsuperstack : ADDRESS;
X sysvar : sysvariable;
X linea [28H] : ADDRESS;
X gemdos [84H] : ADDRESS;
X gsxgem [88H] : ADDRESS;
X tbios [0b4H] : ADDRESS;
X xbios [0b8H] : ADDRESS;
X linef [2cH] : ADDRESS;
X level2 [68H] : ADDRESS;
X level4 [70H] : ADDRESS;
X shellp [4F6H] : ADDRESS;
X oldtrap,oldtermvec : ADDRESS;
X OldEtimer,sspval : ADDRESS;
X p,cotick,x,t,temp : PROCESS;
X processesid,I : INTEGER;
X zombie : BOOLEAN;
X children,highpri : INTEGER;
X savefrom,saveto : savetype;
X CPFlagptr : CPFlagptrtype;
X
X (* -------------- BEGIN -------------- *)
X
XPROCEDURE StartProcess(VAR P : PROC;
X VAR n : LONGCARD;
X VAR priority : INTEGER;
X VAR pn : String;
X VAR parm : ADDRESS);
XBEGIN
X IntEnd;
X SuperExec(UpdatecurrentProc);
X ALLOCATE(wsp,n);
X IF wsp=NIL THEN
X currentprocess^.errno:=12;
X IntBegin;
X RETURN;
X END;
X DEC(sysmemsize,n);
X s1:=currentprocess;
X s0:=currentprocess;
X
X IF processesid>0 THEN (* search only after setup of SCHED *)
X s0:=schedproc; (* set to sched process *)
X LOOP (* find zombie process *)
X s0:=s0^.next;
X IF s0^.pid=1 THEN (* zombie not found in list *)
X EXIT;
X END;
X FindZombieProcess(zombie);
X IF zombie THEN EXIT END;
X END;
X END; (* if processesid>1 *)
X
X IF zombie THEN
X currentprocess:=s0;
X ELSE
X ALLOCATE(currentprocess,TSIZE(ProcessDescriptor));
X IF currentprocess=NIL THEN
X s1^.errno:=12;
X IntBegin;
X RETURN;
X END;
X DEC(sysmemsize,TSIZE(ProcessDescriptor));
X INC(processesid);
X currentprocess^.pid:=processesid;
X currentprocess^.next:=initproc; lastproc^.next:=currentprocess;
X lastproc:=currentprocess;
X END;
X
X WITH currentprocess^ DO
X name:=pn;
X ppid:=request.pid;
X ready:=TRUE; active:=TRUE;
X tick:=0;
X IF priority<1 THEN priority:=1 END;
X IF priority>10 THEN priority:=10 END;
X pri:=priority;
X misc[0]:=pri;
X IF pri>highpri THEN highpri:=pri END;
X GetTime(time);
X GetDate(date);
X gemsave[13]:=0; (* set timer to zero *)
X gemsave[14]:=0; (* set all flags to zero *)
X gemsave[15]:=parm;
X parm:=ADDRESS(currentprocess^.pid);
X Iport:=s1^.Iport;
X Oport:=s1^.Oport;
X END;
X IF currentprocess^.pid>1 THEN
X FindProcess(request.pid,s2);
X s2^.return:=currentprocess^.pid;
X ELSE
X currentprocess^.return:=0;
X END;
X SuperExec(SetSlice);
X currentprocess^.slice:=temphz200;
X currentprocess^.wsp:=wsp;
X currentprocess^.wspsize:=n;
X NEWPROCESS(P,wsp,n,currentprocess^.cor);
X SuperExec(intbiosptr);
X s1^.errno:=0;
X INC(contextswitch); (* update switch counter *)
X TRANSFER(s1^.cor,currentprocess^.cor);
X IntBegin;
XEND StartProcess;
X
XPROCEDURE TermProcess(VAR id: INTEGER);
XBEGIN
X IF id<2 THEN RETURN END;
X IntEnd;
X
X FindProcess(id,s2);
X IF s2=NIL THEN
X currentprocess^.errno:=3;
X IntBegin;
X RETURN;
X END;
X currentprocess^.errno:=0;
X
X s2^.active:=FALSE; (* set flag *)
X IF s2^.wsp#NIL THEN
X DEALLOCATE(s2^.wsp,s2^.wspsize);
X INC(sysmemsize,s2^.wspsize);
X END;
X s2^.wsp:=NIL; (* set TO NIL to make zombie process *)
X s0:=currentprocess; (* set to the parent process *)
X
X kin[0]:=id;
X REPEAT (* loop thru process list and find all related processes *)
X FindChildProcess(kin[0],s1);
X WHILE s1#NIL DO
X INC(children);
X kin[children]:=s1^.pid;
X s1^.active:=FALSE; (* set flag *)
X s1^.gemsave[14]:=0; (* reset all flags *)
X IF s1^.wsp#NIL THEN
X DEALLOCATE(s1^.wsp,s1^.wspsize);
X INC(sysmemsize,s1^.wspsize);
X END;
X s1^.wsp:=NIL; (* set TO NIL to make zombie process *)
X currentprocess:=s1; (* set currentprocess to terminated *)
X SuperExec(IncSlice); (* update cpu time for terminated *)
X FindChildProcess(kin[0],s1);
X END;
X kin[0]:=kin[children];
X DEC(children);
X UNTIL children<0;
X currentprocess:=s0;
X
X currentprocess^.errno:=0;
X s1:=currentprocess; (* save currentprocess *)
X currentprocess:=s2; (* set currentprocess to terminated *)
X SuperExec(UpdatecurrentProc); (* update cpu time for terminated *)
X
X
X currentprocess:=schedproc; (* set to transfer to the sched *)
X
X IF s1^.pid#id THEN
X temp:=s1^.cor; (* currentprocess different than terminated *)
X ELSE
X temp:=t; (* process the same so set up dummy process *)
X END;
X
X IF s1^.pid#1 THEN
X SuperExec(UpdateProc);
X TRANSFER(temp,currentprocess^.cor); (* do context switch *)
X END;
X IntBegin;
XEND TermProcess;
X
XPROCEDURE NextPid(): INTEGER;
XBEGIN
X s1:=currentprocess;
X s0:=currentprocess;
X
X IF processesid>0 THEN (* search only after setup of SCHED *)
X s0:=schedproc; (* set to sched process *)
X LOOP (* find zombie process *)
X s0:=s0^.next;
X IF s0^.pid=1 THEN (* zombie not found in list *)
X EXIT;
X END;
X FindZombieProcess(zombie);
X IF zombie THEN EXIT END;
X END;
X END; (* if processesid>1 *)
X
X IF zombie THEN
X RETURN s0^.pid;
X ELSE
X RETURN processesid+1;
X END;
XEND NextPid;
X
XPROCEDURE SleepProcess(VAR id: INTEGER);
XBEGIN
X IF id<2 THEN RETURN END;
X
X IntEnd;
X FindProcess(id,s2);
X IF s2=NIL THEN
X currentprocess^.errno:=3;
X IntBegin;
X RETURN;
X END;
X currentprocess^.errno:=0;
X
X IF (s2^.wsp#NIL) AND (NOT s2^.active) THEN IntBegin; RETURN END;
X IF s2^.wsp#NIL THEN
X s2^.active:=FALSE; (* set flag *)
X CPFlagptr:=ADR(s2^.gemsave[14]);
X INCL(CPFlagptr^,sleep);
X s2^.gemsave[13]:=0;
X END;
X
X s1:=currentprocess; (* save currentprocess *)
X SuperExec(UpdatecurrentProc); (* update cpu time for sleeper *)
X
X currentprocess:=schedproc; (* set to transfer to the sched *)
X
X IF s1^.pid#1 THEN
X s1^.ready:=FALSE; currentprocess^.ready:=TRUE;
X SuperExec(UpdateProc);
X TRANSFER(s1^.cor,currentprocess^.cor); (* do context switch *)
X END;
X IntBegin;
XEND SleepProcess;
X
XPROCEDURE DozeProcess(VAR id: INTEGER; VAR msec : LONGCARD);
XBEGIN
X IF id<2 THEN RETURN END;
X
X IntEnd;
X FindProcess(id,s2);
X IF s2=NIL THEN
X currentprocess^.errno:=3;
X IntBegin;
X RETURN;
X END;
X currentprocess^.errno:=0;
X
X IF (s2^.wsp#NIL) AND (NOT s2^.active) THEN
X IntBegin;
X RETURN;
X END;
X IF s2^.wsp#NIL THEN
X s2^.active:=FALSE; (* set flag *)
X CPFlagptr:=ADR(s2^.gemsave[14]);
X INCL(CPFlagptr^,sleep);
X IF msec#0 THEN
X SuperExec(SetSlice);
X s2^.gemsave[13]:=ADDRESS(temphz200+(msec DIV 5));
X ELSE
X s2^.gemsave[13]:=0;
X END;
X END;
X
X s1:=currentprocess; (* save currentprocess *)
X SuperExec(getbiosptr);
X SuperExec(UpdatecurrentProc); (* update cpu time for sleeper *)
X
X currentprocess:=schedproc; (* set to transfer to the sched *)
X
X IF s1^.pid#1 THEN
X s1^.ready:=FALSE; currentprocess^.ready:=TRUE;
X SuperExec(UpdateProc);
X TRANSFER(s1^.cor,currentprocess^.cor); (* do context switch *)
X END;
X IntBegin;
XEND DozeProcess;
X
XPROCEDURE WaitProcess(VAR id: INTEGER; VAR loc: ADDRESS;
X VAR value,mask,msec : LONGCARD);
XBEGIN
X IF id<2 THEN RETURN END;
X
X IntEnd;
X FindProcess(id,s2);
X IF s2=NIL THEN
X currentprocess^.errno:=3;
X IntBegin;
X RETURN;
X END;
X currentprocess^.errno:=0;
X
X IF (s2^.wsp#NIL) AND (NOT s2^.active) THEN
X IntBegin;
X RETURN;
X END;
X IF s2^.wsp#NIL THEN
X s2^.active:=FALSE; (* set flag *)
X CPFlagptr:=ADR(s2^.gemsave[14]);
X INCL(CPFlagptr^,sleep);
X INCL(CPFlagptr^,wait);
X s2^.waitloc:=loc;
X s2^.gemsave[11]:=ADDRESS(value);
X s2^.gemsave[12]:=ADDRESS(mask);
X IF msec#0 THEN
X SuperExec(SetSlice);
X s2^.gemsave[13]:=ADDRESS(temphz200+(msec DIV 5));
X ELSE
X s2^.gemsave[13]:=0;
X END;
X END;
X
X s1:=currentprocess; (* save currentprocess *)
X SuperExec(UpdatecurrentProc); (* update cpu time for sleeper *)
X
X currentprocess:=schedproc; (* set to transfer to the sched *)
X
X IF s1^.pid#1 THEN
X s1^.ready:=FALSE; currentprocess^.ready:=TRUE;
X SuperExec(UpdateProc);
X TRANSFER(s1^.cor,currentprocess^.cor); (* do context switch *)
X END;
X IntBegin;
XEND WaitProcess;
X
XPROCEDURE WakeupProcess(VAR id: INTEGER);
XBEGIN
X IF id<2 THEN RETURN END;
X
X IntEnd;
X FindProcess(id,s2);
X IF s2=NIL THEN
X currentprocess^.errno:=3;
X IntBegin;
X RETURN;
X END;
X
X IF (s2^.wsp#NIL) AND s2^.active THEN
X currentprocess^.errno:=0;
X IntBegin;
X RETURN; (* already awake *)
X END;
X
X IF s2^.wsp#NIL THEN
X s2^.active:=TRUE; (* set flag *)
X CPFlagptr:=ADR(s2^.gemsave[14]);
X EXCL(CPFlagptr^,sleep);
X currentprocess^.errno:=0;
X ELSE
X currentprocess^.errno:=3;
X END;
X IntBegin;
XEND WakeupProcess;
X
X(* V0.7 *)
XPROCEDURE ChangeProcessPriority(VAR id: INTEGER; VAR pri: INTEGER);
XBEGIN
X IF id<2 THEN RETURN END;
X
X IntEnd;
X FindProcess(id,s2);
X IF s2=NIL THEN
X currentprocess^.errno:=3;
X IntBegin;
X RETURN;
X END;
X
X IF pri<1 THEN pri:=1 END;
X IF pri>10 THEN pri:=10 END;
X s2^.pri:=pri;
X IntBegin;
XEND ChangeProcessPriority;
X
XPROCEDURE InitProcesses;
XBEGIN
X CRON:=dummy;
X ALLOCATE(currentprocess,TSIZE(ProcessDescriptor));
X DEC(sysmemsize,TSIZE(ProcessDescriptor));
X processesid:=0;
X initproc:=currentprocess;
X lastproc:=initproc;
X WITH currentprocess^ DO
X next:=currentprocess;
X ready:=FALSE;
X active:=FALSE;
X name:="INIT";
X GetTime(time);
X GetDate(date);
SHAR_EOF
echo "End of part 1, continue with part 2"
echo "2" > s2_seq_.tmp
exit 0