PACKET std schedule strategy DEFINES (* Autor: J.Liedtke *) (* Stand: 15.10.82 *) strategic decision : PROC strategic decision (INT CONST foreground workers, background workers, REAL CONST fore cpu load, back cpu load, paging load, INT VAR lowest activation prio, max background tasks) : IF no background permitted THEN lowest activation prio := 0 ; max background tasks := 0 ELSE lowest activation prio := 10 ; select max background tasks FI . no background permitted : foreground workers > 0 AND fore cpu load > 0.03 . select max background tasks : IF fore cpu load > 0.01 THEN max background tasks := 1 ELIF paging load < 0.07 THEN max background tasks := 3 ELIF paging load < 0.15 THEN max background tasks := 2 ELSE max background tasks := 1 FI . ENDPROC strategic decision ; ENDPACKET std schedule strategy ; (* Autor: J.Liedtke*) PACKET eumelmeter DEFINES (* Stand: 11.10.83 *) init log , log : LET snapshot interval = 590.0 ; REAL VAR next snapshot time , time , timex , paging wait , paging wait x , paging busy , paging busy x , fore cpu , fore cpu x , back cpu , back cpu x , system cpu , system cpu x , delta t ; INT VAR storage max, used ; TEXT VAR record ; PROC init log : time := clock (1) ; paging wait := clock (2) ; paging busy := clock (3) ; fore cpu := clock (4) ; back cpu := clock (5) ; system cpu := clock (6) ; next snapshot time := time + snapshot interval ENDPROC init log ; PROC log (INT CONST active terminals, active background) : new snapshot time if was clock reset ; IF clock (1) >= next snapshot time THEN save values ; get new values ; create stat record ; put log (record) ; define next snapshot time FI . new snapshot time if was clock reset : IF clock (1) < next snapshot time - snapshot interval THEN next snapshot time := clock (1) FI . save values : time x := time ; paging wait x := paging wait ; paging busy x := paging busy ; fore cpu x := fore cpu ; back cpu x := back cpu ; system cpu x := system cpu . get new values : time := clock (1) ; paging wait := clock (2) ; paging busy := clock (3) ; fore cpu := clock (4) ; back cpu := clock (5) ; system cpu := clock (6) ; storage (storage max, used) . create stat record : record := text (used, 5) ; record CAT text (active terminals,3) ; record CAT text (active background,3) ; delta t := (time - time x) ; percent (paging wait, paging wait x) ; percent (paging busy, paging busy x) ; percent (fore cpu, fore cpu x) ; percent (back cpu, back cpu x) ; percent (system cpu, system cpu x) ; percent (last, 0.0) ; percent (nutz, 0.0) . last : paging wait + paging busy + fore cpu + back cpu + system cpu - paging waitx - paging busyx - fore cpux - back cpux - system cpux . nutz : time - paging wait - system cpu - timex + paging waitx + system cpux . define next snapshot time : next snapshot time := time + snapshot interval . ENDPROC log ; PROC percent (REAL CONST neu, alt ) : record CAT text ( (neu-alt) / delta t * 100.0, 6,1) + "%" ENDPROC percent ; ENDPACKET eumelmeter ; PACKET background que manager DEFINES (* Autor: J.Liedtke *) (* Stand: 15.10.82 *) into background que , delete from background que , get first from background que , get next from background que : LET que size = 100 , ENTRY = STRUCT (TASK task, INT class) ; INT VAR end of que := 0 , actual entry pos ; ROW que size ENTRY VAR que ; PROC into background que (TASK CONST task) : INT VAR class := prio (task) ; IF end of que = que size THEN delete all not existing tasks FI ; check whether already in que ; IF already in que THEN IF in same class THEN LEAVE into background que ELSE delete from background que (task) ; into background que (task) FI ELSE insert new entry FI . check whether already in que : INT VAR entry pos := 1 ; WHILE entry pos <= end of que REP IF que (entry pos).task = task THEN LEAVE check whether already in que FI ; entry pos INCR 1 PER . already in que : entry pos <= end of que . in same class : que (entry pos).class = class . insert new entry : end of que INCR 1 ; que (end of que) := ENTRY:( task, class ) . delete all not existing tasks : INT VAR j ; FOR j FROM 1 UPTO end of que REP TASK VAR examined := que (j).task ; IF NOT exists (examined) THEN delete from background que (examined) FI PER . ENDPROC into background que ; PROC delete from background que (TASK CONST task) : search for entry ; IF entry found THEN delete entry ; update actual entry pos FI . search for entry : INT VAR entry pos := 1 ; WHILE entry pos <= end of que REP IF que (entry pos).task = task THEN LEAVE search for entry FI ; entry pos INCR 1 PER . entry found : entry pos <= end of que . delete entry : INT VAR i ; FOR i FROM entry pos UPTO end of que - 1 REP que (i) := que (i+1) PER ; end of que DECR 1 . update actual entry pos : IF actual entry or following one deleted THEN actual entry pos DECR 1 FI . actual entry or following one deleted : entry pos >= actual entry pos . ENDPROC delete from background que ; PROC get first from background que (TASK VAR task, INT CONST lowest class) : actual entry pos := 0 ; get next from background que (task, lowest class) ENDPROC get first from background que ; PROC get next from background que (TASK VAR task, INT CONST lowest class) : search next entry of permitted class ; IF actual entry pos <= end of que THEN task := que (actual entry pos).task ELSE task := niltask FI . search next entry of permitted class : REP actual entry pos INCR 1 UNTIL actual entry pos > end of que COR que (actual entry pos).class <= lowest class PER. ENDPROC get next from background que ; ENDPACKET background que manager ; PACKET scheduler DEFINES (* Autor: J.Liedtke *) (* Stand: 09.12.82 *) scheduler : LET std background prio = 7 , highest background prio = 5 , long slice = 6000 , short slice = 600 , blocked busy = 4 ; INT VAR slice , foreground workers , background workers ; BOOL VAR is logging ; REAL VAR fore cpu load , back cpu load , paging load ; access catalogue ; TASK CONST ur task := brother (supervisor) ; TASK VAR actual task ; PROC scheduler : IF yes ("mit eumelmeter") THEN is logging := TRUE ELSE is logging := FALSE FI ; task password ("-") ; break ; set autonom ; command dialogue (FALSE) ; forget ("scheduler", quiet) ; disable stop; REP scheduler operation; clear error PER; END PROC scheduler; PROC scheduler operation: enable stop; IF is logging THEN init log FI; slice := short slice ; init system load moniting ; REP pause (slice) ; monit system load ; look at all active user tasks and block background workers ; activate next background workers if possible ; IF is logging THEN log (foreground workers, background workers) FI PER . init system load moniting : REAL VAR time x := clock (1) , fore cpu x := clock (4) , back cpu x := clock (5) , paging x := clock (2) + clock (3) . monit system load : REAL VAR interval := clock (1) - time x ; fore cpu load := (clock (4) - fore cpu x) / interval ; back cpu load := (clock (5) - back cpu x) / interval ; paging load := (clock (2) + clock (3) - paging x) / interval ; time x := clock (1) ; fore cpu x := clock (4) ; back cpu x := clock (5) ; paging x := clock (2) + clock (3) . ENDPROC scheduler operation; PROC look at all active user tasks and block background workers : foreground workers := 0 ; background workers := 0 ; actual task := myself ; next active (actual task) ; WHILE NOT (actual task = myself) REP IF actual task < ur task THEN look at this task FI ; next active (actual task) END REP . look at this task : IF channel (actual task) >= 0 THEN foreground workers INCR 1 ELSE background workers INCR 1 ; block actual task if simple worker FI . block actual task if simple worker : IF son (actual task) = niltask THEN pause (5) ; block (actual task) ; IF status (actual task) = blocked busy THEN set background prio ; into background que (actual task) ELIF prio (actual task) < highest background prio THEN unblock (actual task) FI FI . set background prio : IF prio (actual task) < highest background prio THEN prio (actual task, std background prio) FI . ENDPROC look at all active user tasks and block background workers ; PROC activate next background workers if possible : INT VAR lowest activation prio , max background workers , active background workers := 0 ; strategic decision (foreground workers, background workers, fore cpu load, back cpu load, paging load, lowest activation prio, max background workers) ; IF background permitted THEN try to activate background workers FI ; IF active background workers > 0 THEN slice := short slice ELSE slice := long slice FI . background permitted : max background workers > 0 . try to activate background workers : get first from background que (actual task, lowest activation prio) ; IF NOT is niltask (actual task) THEN delete from background que (actual task) FI ; WHILE active background workers < max background workers REP IF is niltask (actual task) THEN LEAVE try to activate background workers ELIF status (actual task) <> blocked busy THEN delete from background que (actual task) ELSE unblock (actual task) ; active background workers INCR 1 FI ; get next from background que (actual task, lowest activation prio) PER . ENDPROC activate next background workers if possible ; ENDPACKET scheduler ; scheduler;