system/multiuser/1.7.5/src/supervisor

Raw file
Back to index

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
(* ------------------- 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 ;