[comp.sources.atari.st] v01i081: mx2v230 -- Multitasking kernel with utilities part01/08

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