(* ------------------- VERSION 19 03.06.86 ------------------- *) PACKET supervisor : (* Autor: J.Liedtke *) LET ack = 0 , nak = 1 , error nak = 2 , system catalogue code = 3 , begin code = 4 , end code = 5 , break code = 6 , rename code = 7 , halt code = 8 , password code = 9 , family password code = 40 , set autonom code = 41 , reset autonom code = 42 , define canal code = 43 , go back to old canal code = 44 , task of channel code = 45 , canal of channel code = 46 , set automatic startup code = 47 , reset automatic startup code = 48 , continue code low = 100 , continue code high = 132 , system start code = 100 , define station code = 32000 , max station no = 127 , nil = 0 , number of tasks = 125 , number of channels = 32 , highest terminal channel = 16 , highest user channel = 24 , highest system channel = 32 , configurator channel = 32 , shutup and save code = 12 , channel field = 4 , fromid field = 11 , nilchannel = 0 ; TASK VAR order task ; INT VAR order code , channel nr , channel index ; DATASPACE VAR ds ; BOUND STRUCT (TEXT tname, tpass, TASK task, PROCA start proc) VAR msg ; BOUND TEXT VAR error msg ; REAL VAR last rename time := 0.0 ; TEXT VAR actual password, supply password ; ROW highest terminal channel TASK VAR canal ; ROW number of channels TASK VAR connected task ; FOR channel index FROM 1 UPTO highest terminal channel REP canal (channel index) := niltask ; PER ; FOR channel index FROM 1 UPTO number of channels REP connected task (channel index) := niltask PER ; ROW number of tasks BOOL VAR autonom flag ; ROW number of tasks BOOL VAR automatic startup flag ; ROW number of tasks TEXT VAR task password ; task password (1) := "-" ; task password (2) := "-" ; set clock (date ("09.06.86")) ; TASK VAR dummy task ; command dialogue (TRUE) ; ke ; (* maintenance ke *) create son (myself, "SYSUR", dummy task, proca (PROC sysur)) ; PROC sysur : disable stop ; begin ("ARCHIVE", PROC archive manager, dummy task) ; begin ("OPERATOR", PROC monitor, dummy task) ; begin ("conf", PROC configurator, dummy task) ; system manager ENDPROC sysur ; PROC configurator : page ; REP UNTIL yes("Archiv 'dev' eingelegt") PER; archive ("dev") ; fetch all (archive) ; release (archive) ; REP UNTIL yes ("save system") PER ; command dialogue (FALSE) ; save system ; command dialogue (TRUE) ; rename myself ("configurator") ; disable stop ; REP configuration manager ; clear error PER ENDPROC configurator ; erase last bootstrap source dataspace ; channel (myself, 1) ; command dialogue (TRUE) ; IF yes("Leere Floppy eingelegt") THEN channel (myself, nilchannel) ; command dialogue (FALSE) ; sys op (shutup and save code) ELSE channel (myself, nilchannel) ; command dialogue (FALSE) FI ; supervisor ; PROC supervisor : disable stop ; INT VAR old session := session ; REP wait (ds, order code, order task) ; IF is niltask (order task) THEN interrupt ELIF station (order task) = station (myself) THEN order from task FI PER . interrupt : IF order code = 0 THEN IF old session <> session THEN disconnect all terminal tasks ; old session := session FI ; system start interrupt ELSE supervisor interrupt (canal (order code), order code, connected task (order code)) FI . disconnect all terminal tasks : INT VAR i ; FOR i FROM 1 UPTO highest terminal channel REP TASK VAR id := connected task (i) ; IF NOT (is niltask (id) COR automatic startup flag (index (id)) COR is niltask (canal (i))) THEN break task FI PER . break task : IF task direct connected to channel THEN channel (id, nilchannel) ; connected task (i) := niltask ELSE disconnect if at terminal but overloaded by canal FI . task direct connected to channel : pcb (id, channel field) <> nilchannel . disconnect if at terminal but overloaded by canal : connected task (i) := niltask . order from task : channel index := channel (order task) ; IF is command analyzer task THEN order from command analyzer (connected task (channel index)) ELSE order from user task FI ; IF is error THEN send back error message FI . is command analyzer task : channel index <> nilchannel CAND channel index <= highest terminal channel CAND order task = canal (channel index) . send back error message : forget (ds) ; ds := nilspace ; error msg := ds ; CONCR (error msg) := error message ; clear error ; send (order task, error nak, ds) . ENDPROC supervisor ; PROC supervisor interrupt (TASK VAR command analyzer, INT CONST channel nr, TASK VAR terminal task) : IF NOT is niltask (terminal task) THEN channel (terminal task, nilchannel) FI ; create command analyzer if necessary ; IF already at terminal THEN halt process (command analyzer) ELSE send acknowledge FI ; channel (command analyzer, channel nr) ; activate (command analyzer) . create command analyzer if necessary : IF is niltask (command analyzer) THEN create son (myself, "-", command analyzer, proca (PROC analyze supervisor command)) FI . send acknowledge : forget (ds) ; ds := nilspace ; send (command analyzer, ack, ds) . already at terminal : channel (command analyzer) = channel nr . ENDPROC supervisor interrupt ; PROC order from command analyzer (TASK VAR terminal task) : enable stop ; IF is continue THEN sv cmd continue ELIF order code = system catalogue code THEN task info cmd ELIF order code = task of channel code THEN sv cmd task of channel ELSE SELECT order code OF CASE ack : CASE end code : sv cmd end CASE break code : sv cmd break CASE halt code : sv cmd halt OTHERWISE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") END SELECT ; channel (command analyzer, nilchannel) FI ; forget (ds) ; IF NOT is niltask (terminal task) AND order code <> system catalogue code THEN channel (order task, nilchannel) ; channel (terminal task, channel index) ; activate (terminal task) FI . sv cmd task of channel : msg := ds ; msg.task := terminal task ; send (order task,ack, ds) ; LEAVE order from command analyzer . sv cmd end : IF NOT is niltask (terminal task) THEN delete task (terminal task) ; terminal task := niltask FI . sv cmd break : terminal task := niltask . sv cmd continue : sv cmd break ; continue cmd by canal . sv cmd halt : IF is niltask (terminal task) THEN errorstop ("keine Task angekoppelt") ELSE halt process (terminal task) FI . is continue : order code > continue code low AND order code <= continue code high . command analyzer : canal (channel index) . ENDPROC order from command analyzer ; PROC order from user task : enable stop ; SELECT order code OF CASE nak, error nak : CASE system catalogue code : task info cmd CASE begin code : user begin cmd CASE end code : user end cmd CASE break code : user break cmd CASE rename code : user rename cmd CASE password code : password cmd CASE family password code : family password cmd CASE set autonom code : set autonom cmd CASE reset autonom code : reset autonom cmd CASE define canal code : define new canal CASE go back to old canal code : go back to old canal CASE task of channel code : task of channel CASE canal of channel code : canal of channel CASE set automatic startup code : set automatic startup cmd CASE reset automatic startup code : reset automatic startup cmd OTHERWISE IF is continue THEN user continue cmd ELIF is define station THEN define new station ELSE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") FI ENDSELECT . user begin cmd : msg := ds ; create son (order task, new task name, new task, new start proc) ; send (order task, ack, ds) . user end cmd : msg := ds ; TASK VAR to be erased := CONCR (msg).task ; IF task end permitted THEN delete task (to be erased) ELSE errorstop ("'end' unzulaessig") FI ; IF exists (order task) THEN send (order task, ack, ds) ELSE forget (ds) FI . task end permitted : ( (task is dead AND system catalogue contains entry) OR exists (to be erased)) CAND ( to be erased = order task COR to be erased < order task COR (order task < myself AND NOT (order task < to be erased)) ) . task is dead : status (to be erased) > 6 . system catalogue contains entry : task in catalogue (to be erased, index (to be erased)) . user rename cmd : IF last rename was long ago THEN msg := ds ; name (order task, CONCR (msg).tname) ; update entry in connected task array ; send (order task, ack, ds) ; remember rename time ELSE send (order task, nak, ds) FI . update entry in connected task array : IF channel (order task) <> nilchannel THEN connected task (channel (order task)) := order task FI . remember rename time : last rename time := clock (1) . last rename was long ago : abs (clock (1) - last rename time) > 20.0 . user break cmd : break order task ; send (order task, ack, ds) . break order task : IF task direct connected to channel THEN channel (order task, nilchannel) ; terminal task := niltask ELSE disconnect if at terminal but overloaded by canal FI . task direct connected to channel : channel index <> nilchannel . terminal task : connected task (channel index) . disconnect if at terminal but overloaded by canal : INT VAR i ; FOR i FROM 1 UPTO highest terminal channel REP IF connected task (i) = order task THEN connected task (i) := niltask ; LEAVE disconnect if at terminal but overloaded by canal FI PER . user continue cmd : INT CONST dest channel := order code - continue code low ; IF dest channel <= highest user channel OR order task < myself THEN IF NOT channel really existing THEN errorstop ("kein Kanal") ELIF dest channel is free OR task is already at dest channel THEN break order task ; continue (order task, dest channel) ; autonom flag (index (order task)) := FALSE ; send (order task, ack, ds) ELSE errorstop ("Kanal belegt") FI ELSE errorstop ("ungueltiger Kanal") FI . channel really existing : channel type (dest channel) <> 0 OR dest channel = configurator channel . dest channel is free : (is niltask (connected task (dest channel)) OR channel (connected task (dest channel)) = nilchannel) AND no canal active . no canal active : dest channel > highest terminal channel COR is niltask (canal (dest channel)) COR channel (canal (dest channel)) = nilchannel . task is already at dest channel : channel index = dest channel . password cmd : msg := ds ; task password (index (order task)) := new task password ; forget (ds) ; ds := nilspace ; send (order task, ack, ds) . family password cmd : msg := ds ; actual password := new task password ; supply password := task password (index (order task)) ; change pw of all sons where necessary (son (order task)) ; task password (index (order task)) := actual password ; forget (ds) ; ds := nilspace ; send (order task, ack, ds) . set autonom cmd : autonom flag (index (order task)) := TRUE ; send (order task, ack, ds) . reset autonom cmd : autonom flag (index (order task)) := FALSE ; send (order task, ack, ds) . define new canal : IF order task < myself AND channel index > 0 AND channel index <= highest terminal channel CAND is niltask (canal (channel index)) THEN canal (channel index) := order task ; connected task (channel index) := niltask ; send (order task, ack, ds) ELSE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") FI . go back to old canal : IF order task < myself AND channel index > 0 AND channel index <= highest terminal channel THEN IF NOT is niltask (canal (channel index)) THEN delete task (canal (channel index)) FI ; send (order task, ack, ds) ELSE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") FI . task of channel : msg := ds ; channel nr := int (msg.tname) ; msg.task := channel task ; send (order task, ack, ds). channel task : IF channel nr <= highest terminal channel THEN IF no command analyzer active THEN connected task (channel nr) ELSE canal (channel nr) FI ELSE connected task (channel nr) FI . no command analyzer active : channel (canal (channel nr)) = nilchannel . canal of channel : msg := ds ; channel nr := int (msg.tname) ; msg.task := canal (channel nr) ; send (order task, ack, ds). set automatic startup cmd : automatic startup flag (index (order task)) := TRUE ; send (order task, ack, ds) . reset automatic startup cmd : automatic startup flag (index (order task)) := FALSE ; send (order task, ack, ds) . is continue : order code > continue code low AND order code <= continue code high . new task name : CONCR (msg).tname . new task : CONCR (msg).task . new task password : subtext (CONCR (msg).tpass, 1, 100) . new start proc : CONCR (msg).start proc . is define station : order code >= define station code AND order task < myself AND order code <= define station code + max station no . ENDPROC order from user task ; PROC continue cmd by canal : access task name and password ; check password if necessary ; continue or send continue request ; channel (order task, nilchannel) . access task name and password : msg := ds ; TASK CONST user task := task (CONCR (msg).tname) ; INT CONST task index := index (user task) ; actual password := task password (task index) ; supply password := CONCR (msg).tpass . check password if necessary : IF actual password <> "" THEN IF supply password = "" THEN ask for password ; LEAVE continue cmd by canal ELIF actual password <> supply password OR actual password = "-" THEN errorstop ("Passwort falsch") FI FI . ask for password : send (order task, password code, ds) . continue or send continue request : IF autonom flag (task index) THEN send continue request to user task ELSE continue (user task, order code - continue code low) FI . send continue request to user task : INT VAR request count , quit ; FOR request count FROM 1 UPTO 10 REP send (user task, order code, ds, quit) ; IF quit = ack THEN LEAVE send continue request to user task FI ; pause (3) PER ; errorstop ("Task antwortet nicht") . ENDPROC continue cmd by canal ; PROC continue (TASK CONST id, INT CONST channel nr) : IF NOT is niltask (id) CAND channel (id) <> channel nr THEN check whether not linked to another channel ; channel (id, channel nr) ; connected task (channel nr) := id ; prio (id, 0) ; activate (id) FI . check whether not linked to another channel : INT VAR i ; FOR i FROM 1 UPTO number of channels REP IF connected task (i) = id THEN errorstop ("bereits an Kanal " + text (i) ) ; LEAVE continue FI PER . ENDPROC continue ; PROC task info cmd : forget (ds) ; ds := sys cat ; send (order task, ack, ds) . ENDPROC task info cmd ; PROC delete task (TASK CONST superfluous) : delete all sons of superfluous ; delete superfluous itself . delete superfluous itself : update cpu time of father ; erase process (superfluous) ; delete (superfluous) ; erase terminal connection remark . update cpu time of father : TASK CONST father task := father (superfluous) ; IF NOT is niltask (father task) THEN disable stop ; REAL CONST father time := clock (father task) + clock (superfluous); IF is error THEN clear error ELSE set clock (father task, father time) FI ; enable stop FI . erase terminal connection remark : INT VAR i ; FOR i FROM 1 UPTO number of channels REP IF connected task (i) = superfluous THEN connected task (i) := niltask ; LEAVE erase terminal connection remark FI PER ; FOR i FROM 1 UPTO highest terminal channel REP IF canal (i) = superfluous THEN canal (i) := niltask ; LEAVE erase terminal connection remark FI PER . delete all sons of superfluous : TASK VAR son task ; REP son task := son (superfluous) ; IF is niltask (son task) THEN LEAVE delete all sons of superfluous FI ; delete task (son task) PER . ENDPROC delete task ; PROC create son (TASK CONST father, TEXT CONST task name, TASK VAR new task, PROCA CONST start) : entry (father, task name, new task) ; autonom flag (index (new task)) := FALSE ; automatic startup flag (index (new task)) := TRUE ; task password (index (new task)) := "" ; create (father, new task, privilege, start) . privilege : IF new task < myself THEN 1 ELSE 0 FI . ENDPROC create son ; PROC system start interrupt : IF exists task ("configurator") THEN send system start message FI . send system start message : ds := nilspace ; INT VAR request count, quit ; FOR request count FROM 1 UPTO 10 REP send (task ("configurator"), system start code, ds, quit) ; IF quit = ack THEN LEAVE send system start message FI ; pause (3) PER ; forget (ds) . ENDPROC system start interrupt ; PROC define new station : INT CONST station := order code - define station code ; INT VAR i ; FOR i FROM 1 UPTO highest terminal channel REP IF NOT is niltask (canal (i)) THEN delete task (canal (i)) FI PER ; define station (station) ; FOR i FROM 1 UPTO number of channels REP update (connected task (i)) PER ; forget (ds) . ENDPROC define new station ; PROC change pw of all sons where necessary (TASK CONST first son) : TASK VAR actual task := first son ; WHILE NOT is niltask (actual task) REP change pw ; change pw of all sons where necessary (son (actual task)); actual task := brother (actual task) PER. change pw : IF task password (index (actual task)) = supply password OR task password (index (actual task)) = "" THEN task password (index (actual task)) := actual password FI. END PROC change pw of all sons where necessary ; (******************* basic supervisor operations **********************) PROC channel (TASK CONST id, INT CONST channel nr) : pcb (id, channel field, channel nr) ENDPROC channel ; INT PROC channel type (INT CONST channel nr) : disable stop ; channel (myself, channel nr) ; INT VAR type ; control (1, 0, 0, type) ; channel (myself, nilchannel) ; type ENDPROC channel type ; PROC erase last bootstrap source dataspace : disable stop ; errorstop ("") ; clear error ENDPROC erase last bootstrap source dataspace ; PROC set clock (TASK CONST id, REAL CONST clock value) : EXTERNAL 82 ENDPROC set clock ; PROC sys op (INT CONST code) : EXTERNAL 90 END PROC sys op ; PROC create (TASK CONST father, son, INT CONST priv, PROCA CONST start) : EXTERNAL 95 ENDPROC create ; PROC pcb (TASK CONST id, INT CONST field, value) : EXTERNAL 105 ENDPROC pcb ; PROC activate (TASK CONST id) : EXTERNAL 108 ENDPROC activate ; PROC deactivate (TASK CONST id) : EXTERNAL 109 ENDPROC deactivate ; PROC halt process (TASK CONST id) : EXTERNAL 110 ENDPROC halt process ; PROC erase process (TASK CONST id) : EXTERNAL 112 ENDPROC erase process ; ENDPACKET supervisor ;