|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 330240 (0x50a00) Types: TextFile Names: »mon8part1«
└─⟦a8311e020⟧ Bits:30003039 RC 8000 Monitor Kildetekst └─⟦9ab0fc1ed⟧ └─⟦this⟧ »mon8part1«
1 0 b.a800,b200 w. 2 0 2 0 m. 2 0 mondef - monitor definitions 3 0 3 0 ; release number and date of monitor base text: 4 0 a133=79 07 24 ; date of monitor 5 0 a134=12 00 00 ; time of monitor 6 0 a135=8 ; release number 7 0 a136=0 ; version number 8 0 8 0 b.i30 w. 9 0 i0=82 06 15, i1=12 00 00 10 0 10 0 ; if newtime (i0,i1) > oldtime (a133,a134) then oldtime:=newtime; 11 0 c.i0-a133 12 0 c.i0-a133-1, a133=i0, a134=i1, z. 13 0 c.i1-a134-1, a134=i1, z. 14 0 z. 15 0 15 0 i10=i0, i20=i1 16 0 16 0 i15=i10/100000 , i10=i10-i15*100000 , i25=i20/100000 , i20=i20-i25*100000 17 0 i14=i10/10000 , i10=i10-i14*10000 , i24=i20/10000 , i20=i20-i24*10000 18 0 i13=i10/1000 , i10=i10-i13*1000 , i23=i20/1000 , i20=i20-i23*1000 19 0 i12=i10/100 , i10=i10-i12*100 , i22=i20/100 , i20=i20-i22*100 20 0 i11=i10/10 , i10=i10-i11*10 , i21=i20/10 , i20=i20-i21*10 21 0 21 0 i2: <: date :> 22 24 (:i15+48:)<16+(:i14+48:)<8+46 23 26 (:i13+48:)<16+(:i12+48:)<8+46 24 28 (:i11+48:)<16+(:i10+48:)<8+32 25 30 25 30 (:i25+48:)<16+(:i24+48:)<8+46 26 32 (:i23+48:)<16+(:i22+48:)<8+46 27 34 (:i21+48:)<16+(:i20+48:)<8+ 0 28 36 28 36 i3: al. w0 i2. ; write date: 29 38 rs w0 x2+0 ; first free:=start(text); 30 40 al w2 0 ; 31 42 jl x3 ; return to slang(status ok); 32 44 32 44 jl. i3. ; 33 46 e. 34 46 j. 34 0 date 82.06.15 12.00.00 35 0 35 0 35 0 ; rc 4000 system tape 36 0 ; per brinch hansen 37 0 ; this tape is an autoload version of the rc 4000 multiprogramming 38 0 ; system. it is written in the slang 3 language and consists of 39 0 ; 10 segments surrounded by a global block: 40 0 ; 41 0 ; global block, definitions: 42 0 ; a names define system constants; 43 0 ; b names define entries in the monitor table; 44 0 ; segment 1; start monitor segment 10: 45 0 ; contains a jump to segment 10; 46 0 ; segment 2, monitor: 47 0 ; contains interrupt response code and monitor procedures; 48 0 ; segment 3, external processes: 49 0 ; contains send message and code for input/output; 50 0 ; segment 4, process descriptions: 51 0 ; contains name table, process descriptions, and message buffers; 52 0 ; segment 5, initialize monitor: 53 0 ; executed and removed immediately after loading; 54 0 ; segment 6, process functions: 55 0 ; contains code for catalog administration and the 56 0 ; creation and removal of processes; 57 0 ; segment 7, initialize process functions: 58 0 ; executed and removed immediately after loading; 59 0 ; segment 8, operating system s: 60 0 ; contains code which allows the operators to 61 0 ; create and control new process from consoles; 62 0 ; segment 9, initialize catalog 63 0 ; starts the multiprogramming system and is 64 0 ; itself immediately executed as a part of the 65 0 ; process s; it can initialize the backing store 66 0 ; with catalog entries and binary programs 67 0 ; input from paper tape or magnetic tape; 68 0 ; segment 10: move monitor: 69 0 ; allocates segment 2 - 9 after autoloading 70 0 70 0 70 0 ; global block, definitions 71 0 71 0 ; size options: 72 0 ; a1 = no of area processes 73 0 ; a3 = no of internal processes 74 0 ; a5 = no of message buffers 75 0 ; a7 = no of pseudoprocesses 76 0 ; a87 = inspection interval 77 0 ; a109 = min aux-cat key 78 0 ; a110 = max cat key 79 0 ; a111 = min key for entries between standard and max interval 80 0 ; a112 = no. of bs-devices 81 0 ; a113 = no. of drum chains 82 0 ; a114 = size of drum chains 83 0 ; a115 = no. of disc chains 84 0 ; a116 = size of disc chains 85 0 ; a117 = no of messagebuffers assigned to consoles 86 0 ; a118 = update aux cat 87 0 87 0 87 0 ; predefinition of option variables: 88 0 a1=0 ; 89 0 a3=0 ; 90 0 a5=0 ; 91 0 a9=0 ; number of subdevices 92 0 a80=-1-1<11 ; all drivers included excl. rc8601 93 0 a82=-1 ; ... with statistics on 94 0 a84=-1 ; ... and test on 95 0 a85=256 ; max time slice in 0.1 ms 96 0 a89=8.4777 7777; standard interrupt mask 97 0 a90= 1<0 ; special facility mask : fpacoredump 1<0 98 0 a91=0 ; 99 0 a92=1<10+1<21 ; 100 0 a93=1<23 ; 101 0 a109=2 ; 102 0 a110=3 ; 103 0 a111=3 ; 104 0 a113=0 ; number of drums 105 0 a114=0 ; 106 0 a116=0 ; 107 0 a128=0 ; a128=0 : std monitor gen. 108 0 ; >0 : option gen. 109 0 ; a128 o. 1<1 : read special s size options in segment 6 110 0 ; a128 o. 1<2 : rc 6000 monitor 111 0 a123=0 ; net-identification(jobhost) 112 0 a124=0 ; home-region(jobhost) 113 0 ; a125= ; job host identification 114 0 a130=00 00 00 ; date, time of options 115 0 a131=00 00 00 ; (yy mm dd, hh mm ss) 116 0 a198=1<23+0<3 ; device addr of cpu 117 0 a199=2 ; device number of mainconsole 118 0 a400=0 ; coroutine monitor inclusion (default no) 119 0 119 0 ; **** definition of coroutine monitor formats: 120 0 ; 121 0 ; coroutine description; 122 0 a694 = -6 ; next in semaphore queue 123 0 a696 = -4 ; previous in semaphore queue 124 0 a698 = -2 ; priority 125 0 a700 = 0 ; save ic (return) 126 0 a702 = 2 ; next coroutine 127 0 a704 = 4 ; prev coroutine 128 0 a706 = 6 ; timer 129 0 a708 = 8 ; mask f. waitchained 130 0 a710 = 10 ; save w0(for test purposes only) or result 131 0 a712 = 12 ; save w1 132 0 a714 = 14 ; save w2 133 0 a716 = 16 ; testmask 134 0 a718 = 18 ; ident 135 0 a720 = 20 ; user exit (0 or exit addr) 136 0 a722 = 22 ; return address for waitsem,waitchained,cwaitanswer 137 0 a724 = 24 ; ref. to operation (waitchained) or buf (cwaitanswer) 138 0 138 0 ; operation: 139 0 a670 = +0 ; next operation 140 0 a672 = +2 ; prev operation 141 0 a674 = +4 ; type 142 0 142 0 ; chained semaphore: 143 0 a650 = +0 ; next coroutine 144 0 a652 = +2 ; prev coroutine 145 0 a654 = +4 ; next operation 146 0 a656 = +6 ; prev operation 147 0 147 0 ; simple semaphore: 148 0 a660 = +0 ; next coroutine 149 0 a662 = +2 ; prev coroutine 150 0 a664 = +4 ; count 151 0 151 0 151 0 ; second process extension. 152 0 ; contains key variables of the coroutine system . 153 0 a538 = -12 ; start of testbuffer 154 0 a540 = -10 ; start of next record in test buffer 155 0 a542 = -8 ; top of test buffer 156 0 a544 = -6 ; test output flag (1 = on) 157 0 157 0 a546 = -4 ; next in active queue 158 0 a548 = -2 ; prev in active queue 159 0 a550 = 0 ; current coroutine 160 0 a552 = 2 ; next in timer queue 161 0 a554 = 4 ; prev in timer queue 162 0 a556 = 6 ; name of the testoutput process 163 0 a566 = 16 ; start of testoutput message 164 0 a582 = 32 ; last event pointer 165 0 a584 = 34 ; message decriptor pointer(cur) 166 0 a586 = 36 ; start of table containing references to user defined procedures 167 0 a588 = 38 ; first message buffer extension 168 0 a590 = 40 ; start of common message-answer area 169 0 a616 = 56 ; name of 'clock' 170 0 a626 = 66 ; start of 'clock'-message 171 0 a630 = 70 ; answer descriptor for answer from 'clock' 172 0 t. 172 0* type 173 0 \f 173 0 ; monitor options. 174 0 174 0 m. 174 0 nye mon options (newopt) - 79.08.01 12.00.00 175 0 175 0 a130= 79 03 27 ; date 176 0 a131= 19 00 00 ; time 177 0 177 0 a1= 133 ; areas 178 0 a3= 11 ; internals 179 0 a5= 157 ; message buffers 180 0 a80= -1 ; all drivers included 181 0 a90= 0 ; fpa power dump excluded 182 0 ; a82= 0 ; statistics off 183 0 ; a84= 0 ; testoutput off 184 0 a115= 4 ; number of discs 185 0 a116=2046 ; max number of slices in disc slice tabel 186 0 a117= 18 ; number of mess buffers reserved for subprocesses 187 0 a125=117 ; jobhost identification 188 0 n.m. 188 0 monitor size options included 189 0 189 0 ; a2 = size of area process description 190 0 ; a4 = size of internal process description 191 0 ; a8 = size of pseudoprocesses 192 0 192 0 a112 = a113 + a115 193 0 a8=0 194 0 a118 = a112-2, a119 = a118 195 0 195 0 ; a88 = size of catalog entry 196 0 ; a89 = standard interrupt mask 197 0 ; a85 = max time slice in 0.1 msec 198 0 ; a107 = min lower limit in bases 199 0 ; a108 = max upper limit in bases 200 0 200 0 a88=34, a107=8.4000 0001, a108=8.3777 7776 201 0 201 0 ; driver options. 202 0 ; the inclusion of drivers is controlled by the parameters a80, a82 and a84. 203 0 ; a80 determines whether a driver shall be included, and a82 and a84 whether 204 0 ; it shall be included with statistics and/or testoutput. 205 0 ; 206 0 ; a80 = driver inclusion 207 0 ; a82 = statistics 208 0 ; a84 = testoutput 209 0 ; 210 0 ; the function of the bits in the parameters are - 211 0 ; 1<0 : clock 212 0 ; 1<1 : disc (dsc 801) 213 0 ; 1<2 : mainproc 214 0 ; 1<3 : receiver (fpa 801) 215 0 ; 1<4 : transmitter (fpa 801) 216 0 ; 1<5 : hostproc 217 0 ; 1<6 : subprocs 218 0 ; 1<7 ; host, subhost 219 0 ; 1<11 : rc8601 220 0 ; 1<12 ; subdriver terminal 221 0 ; 1<13 ; - magtape 222 0 ; 1<14 ; - disc 223 0 ; 1<15 ; - flexible disc 224 0 224 0 224 0 ; testoptions: 225 0 ; testoptions are used during debugging of the system. 226 0 ; they are defined by bits in the identifier a92 as follows: 227 0 ; testcase i a92=a92 o. 1<i 0<=i<=17 228 0 ; teststatus a92=a92 o. 1<18 229 0 ; testcall a92=a92 o. 1<19 230 0 ; testoutput a92=a92 o. 1<20 231 0 ; print w, type w 232 0 ; procfunc interrupt a92=a92 o. 1<21 233 0 ; procfunc testbuffer a92=a92 o. 1<22 234 0 ; testoptions in s are defined by bits in the identifier a93 235 0 ; as explained in s. 236 0 a48 = -4 ; lower limit(interval) 237 0 a49 = -2 ; upper limit(interval) 238 0 a10 = 0 ; kind 239 0 a11 = 2 ; name 240 0 a12 = 10, a13 = 11 ; stop count, state 241 0 a14 = 12 ; identification bit 242 0 a15 = 14 ; next event 243 0 ; last event 244 0 a16 = 18 ; next process 245 0 ; last process 246 0 a17 = 22 ; first address (logical) 247 0 a18 = 24 ; top address (logical) 248 0 a19 = 26, a20 = 27 ; buffer claim, area claim 249 0 a21 = 28, a22 = 29 ; internal claim, function mask 250 0 a301= 30 ; priority 251 0 a24 = 32, a25 = 33 ; mode (= protection register, protection key) 252 0 a26 = 34 ; interrupt mask 253 0 a27 = 36 ; user exception address (interrupt address) (logical) 254 0 a170= 38 ; user escape address (logical) 255 0 a171= 40 ; initial cpa 256 0 a172= 42 ; - base 257 0 a173= 44 ; - lower write limit (physical) 258 0 a174= 46 ; - top - - (physical) 259 0 a175= 48 ; - interrupt levels 260 0 a34 = 50 ; parent description address 261 0 a35 = 52 ; quantum 262 0 a36 = 54 ; run time 263 0 a38 = 58 ; start run 264 0 a39 = 62 ; start wait 265 0 a40 = 66 ; wait address 266 0 a42 = 68, a43 = 70 ; catalog base 267 0 a44 = 74 ; max interval 268 0 a45 = 78 ; standard interval 269 0 a28 = 80 ; save w0, = first of regdump 270 0 a29 = 82 ; - w1 271 0 a30 = 84 ; - w2 272 0 a31 = 86 ; - w3 273 0 a32 = 88 ; - status 274 0 a33 = 90 ; - ic (logical) 275 0 a176= 92 ; - cause 276 0 a177= 94 ; - sb 277 0 a176= 96 ; top of regdump 278 0 a181= 96 ; current cpa = first of fixed parameters 279 0 a182= 98 ; - base 280 0 a183= 100 ; - lower write limit (physical) 281 0 a184= 102 ; - top - - (physical) 282 0 a185= 104 ; - interrupt levels 283 0 a179= a181-a28 ; (displacement between fixed params and first of regdump) 284 0 ; a180: ; see c29 285 0 a302= 106 ; save area address 286 0 ; save area for g20-g24, b18, b19 287 0 a303= 124 ; top of save area 288 0 a46 = 124 ; bs claims start 289 0 ; chain0: key0: slices , entries 290 0 ; key1: - , - 291 0 ; key2: - , - 292 0 ; key3: - , - 293 0 ; (........................) 294 0 ; chain1: key0: - , - 295 0 ; (........................) 296 0 ; bs claims top 297 0 ; calculate size of process- 298 0 a4=a46+(:a110<1+2:)*a112-a48 299 0 a4 = a4 ; size of internal process 300 0 a35 = 52 ; <quantum> 301 0 a36 = 54 ; <run time> 302 0 a38 = 58 ; <start run> 303 0 a39 = 62 ; <start wait> 304 0 a40 = 66 ; <wait address> 305 0 a42 = 68, a43 = 70 ; <catalog base> 306 0 a44 = 74 ; <max interval> 307 0 a45 = 78 ; <standard interval> 308 0 b. j0 w. 309 0 j0 = 80 310 0 a28 = j0, j0 = j0+2 ; save w0, = first of regdump 311 0 a29 = j0, j0 = j0+2 ; - w1 312 0 a30 = j0, j0 = j0+2 ; - w2 313 0 a31 = j0, j0 = j0+2 ; - w3 314 0 a32 = j0, j0 = j0+2 ; - status 315 0 a33 = j0, j0 = j0+2 ; - ic 316 0 a176= j0, j0 = j0+2 ; - cause 317 0 a177= j0, j0 = j0+2 ; - sb 318 0 a178= j0 ; top of regdump 319 0 a181= j0, j0 = j0+2 ; current cpa = first of fixed parameters 320 0 a182= j0, j0 = j0+2 ; - base 321 0 a183= j0, j0 = j0+2 ; - lower write limit 322 0 a184= j0, j0 = j0+2 ; - top - - 323 0 a185= j0, j0 = j0+2 ; - interrupt levels 324 0 a179= a181-a28 ; (displacement between fixed params and first of regdump) 325 0 ; a180: see c29 326 0 a302= j0, j0 = j0+2 ; save area address 327 0 j0 = j0+14; save area for g20-g24, b18, b19 328 0 a303= j0 ; top of save area 329 0 a305= j0, j0 = j0+2 ; first process extension 330 0 a306= j0, j0 = j0+2 ; second process extension 331 0 a46 = j0 ; bs claims start 332 0 j0=j0+(:a110<1+2:)*a112; top of bs claim list 333 0 ; a48 = first of internal process 334 0 ; j0 = top - - - 335 0 a4 = j0-a48 ; size of internal process 336 0 e. 337 0 a23 = 27 ; use area processes as pseudoprocesses 338 0 338 0 ; format of save area: 339 0 ; 8 words, used by deliver-result-procedures 340 0 a304 = 16 ; address of wait first event 341 0 341 0 ; internal process states: 342 0 342 0 ; actual bitpatterns are relevant to process functions only 343 0 a95 = 2.01001000 ; running 344 0 a96 = 2.00001000 ; running after error 345 0 a97 = 2.10110000 ; waiting for stop by parent 346 0 a98 = 2.10100000 ; waiting for stop by ancestor 347 0 a99 = 2.10111000 ; waiting for start by parent 348 0 a100= 2.10101000 ; waiting for start by ancestor 349 0 a101= 2.11001100 ; waiting for process function 350 0 a102= 2.10001101 ; waiting for message 351 0 a103= 2.10001110 ; waiting for answer 352 0 a104= 2.10001111 ; waiting for event 353 0 353 0 353 0 ; bit patterns used to test or change the above states: 354 0 a105 = 2.00100000; waiting for stop or start 355 0 a106 = 2.00001000; waiting for start 356 0 356 0 \f 356 0 ; format of area process description: 357 0 357 0 a349= -6 ; <start of process> 358 0 a250= -6 ; <driver proc descr address> 359 0 a48 = -4 ; <lower limit> 360 0 a49 = -2 ; <upper limit> 361 0 361 0 a10 = 0 ; <kind> 362 0 a11 = 2 ; <name> 363 0 a50 = 10, a51 = 11 ; <process descr addr of bs device> 364 0 a52 = 12 ; <reserved> 365 0 a53 = 14 ; <users> 366 0 a60 = 16 ; <first slice> 367 0 a61 = 18 ; <number of segments> 368 0 a62 = 20 ; <document name> 369 0 a411= 28 ; number of times written 370 0 a412= 30 ; number of times read 371 0 a2 = a412+2-a349 ; size of area process 372 0 372 0 ; format of pseudo process 373 0 a48 = -4, a49 = -2 ; <interval> 374 0 a10 = 0 ; <kind> 375 0 a11 = 2 ; <name> 376 0 a50 = 10 ; <main process> 377 0 a60 = 16 ; <mess descr> 378 0 378 0 \f 378 0 ; format of device description: 379 0 379 0 ; definition of device-dependant part of device-description 380 0 380 0 b. j0 w. 381 0 381 0 j0 = 0 ; (used to set up the definitions) 382 0 382 0 ; pointers to private area in device descriptor, used by driver and start-io: 383 0 383 0 a220= j0, j0 = j0+2 ; first of private area, rel to a10 384 0 a221= j0, j0 = j0+2 ; top of private area, rel to a10 385 0 385 0 ; the following word is used to indicate a transfer in progress 386 0 ; (sender descr) a.1 = 1 : transfer to driver process 387 0 ; (sender descr) a.(-2)>0: transfer to sender process 388 0 ; (sender descr) = 0 : no transfer 389 0 a225= j0, j0 = j0+2 ; transfer code 390 0 390 0 ; pointers to channel program area, in device descriptor, used by start-io: 391 0 391 0 a226= j0, j0 = j0+2 ; first of channel program area, rel to a10 392 0 a227= a226+2,j0=j0+2; top of channel program area, rel to a10 393 0 393 0 ; standard status area: used when the controller delivers an interrupt: 394 0 394 0 a230= j0, j0 = j0+8 ; channel program address 395 0 a231= a230+2 ; remaining character count 396 0 a232= a230+4 ; current status 397 0 a233= a230+6 ; event status 398 0 398 0 ; device address, also used as index to controller table: 399 0 399 0 a235= j0, j0 = j0+2 ; device address 400 0 400 0 ; interrupt operation, as needed by monitor interrupt response: 401 0 401 0 a240= j0, j0 = j0+2 ; <jl w2 c51> (monitor service instruction) 402 0 a241= a240+2 ; <after jl w2 ...> 403 0 a242= a241, j0=j0+2 ; next operation link 404 0 a243= a242+2,j0=j0+2; prev operation link 405 0 a244= j0, j0 = j0+2 ; timeout / result from start-io 406 0 406 0 ; interrupt operation, as needed by driver process: 407 0 407 0 a245= a244+2,j0=j0+2; interrupt address in driver code (logic addr) 408 0 a246= j0, j0 = j0+2 ; <jl w1 c30> (driver service instruction) 409 0 a247= a246+2 ; <after jl w1 ...> 410 0 410 0 ; which driver process governs this device ? (used by monitor): 411 0 411 0 a250= j0, j0 = j0+2 ; driver description addr (abs addr) 412 0 412 0 ; the last of these fields should have been adjacent to the 413 0 ; field 'interval low' i.e. relative to a48: 414 0 414 0 j0 = j0 - a48 415 0 a220=a220-j0, a221=a221-j0 416 0 a225=a225-j0, a226=a226-j0, a227=a227-j0 417 0 a230=a230-j0, a231=a231-j0, a232=a232-j0, a233=a233-j0 418 0 a235=a235-j0 419 0 a240=a240-j0, a241=a241-j0, a242=a242-j0, a243=a243-j0, 420 0 a244=a244-j0, a245=a245-j0, a246=a246-j0, a247=a247-j0, 421 0 a250=a250-j0 422 0 422 0 ; some of the above given field were known under another name 423 0 ; in the earlier versions of this monitor: 424 0 424 0 ; a50 = a235 ; device address 425 0 ; a56 = a245 ; interrupt address 426 0 426 0 e. 427 0 427 0 ; a48 lower interval 428 0 ; a49 upper interval 429 0 ; a10 kind 430 0 ; a11 name 431 0 ; a52 reserver 432 0 ; a53 users 433 0 a54 = 16 ; next message 434 0 a55 = 18 ; previous message 435 0 ; a70 optional parameters 436 0 ; etc 437 0 437 0 437 0 437 0 ; format of peripheral process description: 438 0 ; a250 driver process description address 439 0 a48 = -4, a49 = -2 ; <interval> 440 0 440 0 a10 = 0 ; <kind> 441 0 a11 = 2 ; <name> 442 0 a50 = 10 ; <device number*64> 443 0 a52 = 12 ; <reserved> 444 0 a53 = 14 ; <users> 445 0 a54 = 16 ; <next message> 446 0 a55 = 18 ; <last message> 447 0 a56 = 20 ; <interrupt address> 448 0 448 0 ; optional parameters for peripheral devices: 449 0 a70 = 22 ; <parameter 0> 450 0 a71 = 24 ; <parameter 1> 451 0 a72 = 26 ; <parameter 2> 452 0 a73 = 28 ; <parameter 3> 453 0 a74 = 30 ; <parameter 4> 454 0 a75 = 32 ; <parameter 5> 455 0 a76 = 34 ; <parameter 6> 456 0 a77 = 36 ; <parameter 7> 457 0 a78 = 38 ; <parameter 8> 458 0 458 0 ; parameters used in connection with subprocesses: 459 0 a63 = a70+14 460 0 a64 = a63+2 461 0 461 0 ; format of controller description 462 0 462 0 a310= 0 ; first of channel program 463 0 a311= 2 ; first of std status 464 0 a312= 4 ; interrupt destination 465 0 a313= 6 ; interrupt number 466 0 a314= 8 ; size of controller description 467 0 467 0 ; format of std status 468 0 468 0 a315= 0 ; top of last executed command 469 0 a316= 2 ; remaining character count 470 0 a317= 4 ; current status 471 0 a318= 6 ; event status 472 0 472 0 ; format of logic channel program (as demanded by the start i/o procedure) 473 0 473 0 a321= 0 ; address code < 12 + command < 8 + modif 474 0 a322= 2 ; param 1 475 0 a323= 4 ; param 2 476 0 476 0 a320= 6 ; size of channel program entry 477 0 477 0 \f 477 0 ; format of message buffer: 478 0 478 0 a139=-2 ; mess flag (saved w2 in send message) 479 0 a140= 0 ; links: next buffer, previous buffer 480 0 a141= 4 ; receiver (or result) 481 0 a142= 6 ; sender 482 0 a145= 8 ; start of message/answer 483 0 a150= a145 ; operation < 12 + mode status word 484 0 a151= a145+2 ; first storage address number of bytes 485 0 a152= a145+4 ; last storage address number of chars 486 0 a153= a145+6 ; first segment number 487 0 a146= 24 ; top of message/answer 488 0 a6 = a146-a139 ; size of message buffer 489 0 489 0 489 0 ; message buffer states: 490 0 490 0 ; the possible states of a message buffer are defined by the 491 0 ; values of the sender and receiver parameters: 492 0 ; 493 0 ; sender param: receiver param: state: 494 0 ; 0 0 buffer available 495 0 ; sender descr receiver descr message pending from existing sender 496 0 ; sender descr -receiver descr message received from existing sender 497 0 ;-sender descr receiver descr regretted message pending 498 0 ;-sender descr -receiver descr regretted message received 499 0 ; sender descr 1 normal answer pending 500 0 ; sender descr 2 dummy answer pending (message rejected) 501 0 ; sender descr 3 dummy answer pending (message unintelligible) 502 0 ; sender descr 4 dummy answer pending (receiver malfunction) 503 0 ; sender descr 5 dummy answer pending (receiver does not exist) 504 0 504 0 504 0 504 0 ; the possible states of a message buffer are defined by the values of the sender and 505 0 ; receiver fields in the buffer: 506 0 ; 507 0 ; sender: receiver: state: 508 0 ; 1. 0 0 free 509 0 ; 2. sender addr receiver addr message pending 510 0 ; 3. sender addr -receiver addr message received 511 0 ; 4. -sender addr receiver addr (not possible) 512 0 ; 5. -sender addr -receiver addr message received, but regretted by sender 513 0 ; 6. sender addr -receiver addr - 1 immediate-message received 514 0 ; 7. -sender addr -receiver addr - 1 immediate-message received, but regretted by sender ('s parent) 515 0 ; 8. sender addr 1 pending answer, result = normal 516 0 ; 9. sender addr 2 - - result = rejected 517 0 ; 10. sender addr 3 - - result = unintelligible 518 0 ; 11. sender addr 4 - - result = malfunction 519 0 ; 12. sender addr 5 - - result = unknown 520 0 ; 521 0 ; explanations: 522 0 ; sender addr > 0 : message buffer claim of the sender has been decreased 523 0 ; receiver addr > 0 : message buffer has not been detected by the receiver, i.e. mess 524 0 ; buf claim of sender is untouched. the message buffer may be removed 525 0 ; from the receivers queue without further actions. 526 0 ; receiver addr < 0 : mess buf claim of receiver has been decreased, indicating that the 527 0 ; receiver has deposited a mess buff in the pool, while the receiver 528 0 ; is processing the original one. 529 0 ; sender addr < 0 : the sender has regretted the message, or has been removed. the mess buf 530 0 ; claim of the sender has been increased, i.e. the sender may now use 531 0 ; the deposited message buffer. 532 0 ; 1 <= receiver <= 5 : the mess buf claim of the receiver has been readjusted, i.e. the 533 0 ; receiver has regained its deposited mess buf claim 534 0 ; receiver addr odd : immediate message 535 0 ; 536 0 ; 537 0 ; the following table shows how the different monitor procedures react upon the possible 538 0 ; bufferstates. the table contains the new state. 539 0 ; 540 0 ; <-----------------sender/parent-----------------> 541 0 ; remove <-------------receiver-------------><---drivers---> 542 0 ; process/ 543 0 ; send regret wait stop wait get wait send link next 544 0 ; message message answer process event event message answer operation 545 0 ; 546 0 ; 1 free 2 illegal illegal 3 illegal illegal - illegal illegal - 547 0 ; 2 message pending - 1 unch. - 3 3 3 illegal 2 2 548 0 ; 3 message received - 5 unch. - 2-3 3 - 8-12 2 - 549 0 ; 5 mess rec, but regr. - illegal illegal - 1 5 - 1 1 - 550 0 ; 8-12 pending answer - 1 1 - unch. 1 - illegal illegal - 551 0 ; 552 0 ; modify/ 553 0 ; remove 554 0 ; process 555 0 ; 556 0 ; 6 imm. mess received - 7 illegal - illegal illegal - 1 illegal - 557 0 ; 7 imm. mess rec.,regr - - illegal - illegal illegal - 1 illegal - 558 0 ; 559 0 \f 559 0 559 0 m. 559 0 moncentral - monitor central logic 560 0 560 0 b.i30 w. 561 0 i0=82 01 25, i1=12 00 00 562 0 562 0 ; if newtime (i0,i1) > oldtime (a133,a134) then oldtime:=newtime; 563 0 c.i0-a133 564 0 c.i0-a133-1, a133=i0, a134=i1, z. 565 0 c.i1-a134-1, a134=i1, z. 566 0 z. 567 0 567 0 i10=i0, i20=i1 568 0 568 0 i15=i10/100000 , i10=i10-i15*100000 , i25=i20/100000 , i20=i20-i25*100000 569 0 i14=i10/10000 , i10=i10-i14*10000 , i24=i20/10000 , i20=i20-i24*10000 570 0 i13=i10/1000 , i10=i10-i13*1000 , i23=i20/1000 , i20=i20-i23*1000 571 0 i12=i10/100 , i10=i10-i12*100 , i22=i20/100 , i20=i20-i22*100 572 0 i11=i10/10 , i10=i10-i11*10 , i21=i20/10 , i20=i20-i21*10 573 0 573 0 i2: <: date :> 574 24 (:i15+48:)<16+(:i14+48:)<8+46 575 26 (:i13+48:)<16+(:i12+48:)<8+46 576 28 (:i11+48:)<16+(:i10+48:)<8+32 577 30 577 30 (:i25+48:)<16+(:i24+48:)<8+46 578 32 (:i23+48:)<16+(:i22+48:)<8+46 579 34 (:i21+48:)<16+(:i20+48:)<8+ 0 580 36 580 36 i3: al. w0 i2. ; write date: 581 38 rs w0 x2+0 ; first free:=start(text); 582 40 al w2 0 ; 583 42 jl x3 ; return to slang(status ok); 584 44 584 44 jl. i3. ; 585 46 e. 586 46 j. 586 0 date 82.01.25 12.00.00 587 0 \f 587 0 587 0 587 0 587 0 ; segment 1 : enter monitor after load 588 0 ; the monitor is entered in word 8. the words +2,+4 must at entry contain - 589 0 ; +2 load flag, writetext 590 0 ; +4 medium 591 0 ; where 592 0 ; load flag: 1 autoload of device controllers 593 0 ; 0 no autoload 594 0 594 0 s. i2 595 0 w. 596 0 596 0 i0: i2. ; length of segment 1 597 2 0 ; init cat switch: writetext 598 4 i1: 0 ; init cat switch: medium 599 6 599 6 ; entry from autoloader: 600 6 al. w3 i0. ; calculate top address of 601 8 rl w2 x3 ; last segment; 602 10 wa w3 4 ; 603 12 se w2 0 ; (i.e. until segment size = 0) 604 14 jl. -6 ; 605 16 al. w2 i2. ; insert start address of segment 2; 606 18 dl. w1 i1. ; get init cat switches 607 20 jd x3-2 ; jump to segment 10 608 22 i2: ; first word of segment 2 609 22 609 22 ; exit with: 610 22 ; w0, w1 = init cat switches 611 22 ; w2 = start address of segment 2 612 22 612 22 e. ; end segment 1 613 22 613 22 613 22 b. v100, r28, g70, f20, e65, d140, c200 614 22 \f 614 22 614 22 ; segment 2: monitor 615 22 615 22 s. k = 8, j0 616 8 w.b127=k, j0, k=k-2 617 8 ; segment structure: 618 8 ; monitor table (b names) 619 8 ; interrupt response (c names) 620 8 ; utility procedures (d names) 621 8 ; monitor procedures (e names) 622 8 ; name table (f names) 623 8 ; process descriptions (f names) 624 8 ; buffers (f names) 625 8 ; 626 8 ; (g and h and i names are used locally) 627 8 627 8 ; monitor table 628 8 628 8 ; all addresses are absolute addresses 629 8 ; an integer after the semicolon means, that the address can't 630 8 ; be changed, because it - unfortunately - has been published 631 8 ; or because they have a hardware-function 632 8 632 8 b65: 0-0-0 ; 8: base of controller description table 633 10 b66: c25 ; 10: power up entry 634 12 b67: 0-0-0 ; first controller table entry 635 14 b68: 0-0-0 ; top controller table entry 636 16 b69: b69 ; queue head: software timeout 637 18 b69 ; (for devices) 638 20 b70: 0 , 0 ; time when last inspected 639 24 b72: 0-0-0 ; b53 ; start of interrupt table 640 26 b73: 0-0-0 ; b54 ; max external interrupt number 641 28 b0: 0-0-0 ; b53 - b16 ; (relative start of interrupt table 642 30 b74: a198 ; device address of this cpu 643 32 b75: 0 ; after powerfail (0==false, else true) 644 34 644 34 b18: 0 ; current buffer address 645 36 b19: 0 ; current receiver 646 38 b20: c96 ; address of simple wait event procedure 647 40 b21: 0-0-0 ; owner of std-driver-locations 648 42 b101:0 ; return from subprocs 649 44 b102:0-0-0 ; a66 ; start of table(subproc-drivers) 650 46 b103:0 ; address of entry for send message for linkdriver areas 651 48 b76: 0 ; start of secondary interrupt chain 652 50 b30: 0-0-0 ; errorlog proc 653 52 b31: g66 ; errorlog entry 654 54 r. (:64-k+2:) > 1 ; 60-62 reserved for testprograms 655 64 a135<12+a136 ; 64: release, version of monitor 656 66 b1: 0 ; 66: current process 657 68 b2: b2 ; time slice queue head: next process 658 70 b2 ; last process 659 72 b3: 0-0-0 ; 72: name table start 660 74 b4: 0-0-0 ; 74: first device in name table 661 76 b5: 0-0-0 ; 76: first area in name table 662 78 b6: 0-0-0 ; 78: first internal in name table 663 80 b7: 0-0-0 ; 80: name table end 664 82 b8: b8 ; mess buf pool queue head: next buf 665 84 b8 ; last buf 666 86 0-0-0 ; 86: first byte of mess buf pool area 667 88 0-0-0 ; 88: last byte of mess buf pool area;( last word of last monitor table) 668 90 a6 ; 90: size of message buffer 669 92 b22: 0-0-0 ; 92: first drum chain in name table 670 94 b23: 0-0-0 ; 94: first disc chain in name table 671 96 b24: 0-0-0 ; 96: chain end in name table 672 98 b25: 0 ; 98: main cat chain table 673 100 0-0-0 ;(100) not used ??? 674 102 b10: a85 ; maximum time slice 675 104 b11: 0 ;104: time slice (of current process) 676 106 0 ;106: zero (earlier: micro seconds) 677 108 b13: 0 , 0 ;108:110: time (unit of 0.1 milli seconds) 678 112 b14: 0 ; last sensed clock value 679 114 0 ; (not used) 680 116 b12: 0-0-0 ;116: number of storage bytes 681 118 a111<12 + a109 ;118: min global key, min aux cat key ????? 682 120 b15: 0 , 0 ; clockchange, after set clock: 683 124 ; newtime - oldtime 684 124 c.a400-1 685 124 b27: 0 ;124: first process extension(cur) 686 124 b28: 0 ;126: second process extension(cur) 687 124 b141:0 ;128: coroutine testoutput address 688 124 ; links to cmon procedures: 689 124 b140:c100 ;130: address of cmon procedure start 690 124 c101 ;132: - '' - wait 691 124 c102 ;134: - '' - pass 692 124 c103 ;136: - '' - inspect 693 124 c104 ;138: - '' - csendmessage 694 124 c105 ;140: - '' - cwaitanswer 695 124 c106 ;142: - '' - answer_arrived 696 124 c107 ;144: - '' - signal_binary 697 124 c108 ;146: - '' - signal_sem 698 124 c109 ;148: - '' - wait_sem 699 124 c110 ;150: - '' - signal_chained 700 124 c111 ;152: - '' - inspect_chained 701 124 c112 ;154: - '' - wait_chained 702 124 c113 ;156: - '' - sem_send_mess 703 124 c114 ;158: - '' - sem_answer_proc 704 124 c115 ;160: - '' - message_received 705 124 c116 ;162: - '' - timer_message 706 124 c117 ;164: - '' - timer_scan 707 124 c118 ;166: - '' - cregretmessage 708 124 c119 ;168: - '' - user testoutput 709 124 z. 710 124 b26 = b5 ; use area processes as pseudo processes 711 124 711 124 ; definition of general registers in rc8000 712 124 712 124 b90 = 8.14 * 2 ; ilevc : interrupt level limit copy 713 124 b91 = 8.15 * 2 ; inf : current interrupt stack element address 714 124 b92 = 8.17 * 2 ; size : top available core address 715 124 b93 = 8.20 * 2 ; montop : 1 < 11 - top monitor procedure number 716 124 b94 = 8.62 * 2 ; clock 717 124 b95 = 8.57 * 2 ; ir : used to clear selected bits in interrupt reg 718 124 b97 = 8.60 * 2 ; dswr : data swithes 719 124 b98 = 8.61 * 2 ; regsel : register swithes 720 124 b99 = 8.60 * 2 ; display 721 124 ; 722 124 b100= 8.21*2 ; cpukind: 0: /45 723 124 ; -1: /15, /25, /35 724 124 ; 50: /50 725 124 ; 55: /55 726 124 726 124 ; definition of interrupt stack. 727 124 ; parameters are relative to base of stack element (i.e. 1,3,5,..) 728 124 728 124 b.j0 729 124 j0=-1 , j0=j0+2 ; base of stack element 730 124 730 124 a326=j0 , j0=j0+2 ; regdump 731 124 a327=j0 , j0=j0+2 ; exception routine 732 124 a328=j0 , j0=j0+2 ; escape routine 733 124 a329=j0 , j0=j0+2 ; monitor call entry 734 124 a330=j0 , j0=j0+2 ; external interrupt entry 735 124 a331=j0 , j0=j0+2 ; interrupt limits, disabled/enabled 736 124 736 124 a325=j0-a326 ; size of interrupt stack element 737 124 737 124 e. 738 124 738 124 ; external interrupt entry: 739 124 ; 740 124 ; when an external interrupt occurs, or when 'user exception first' 741 124 ; or 'user escape first' are zero, the cpu will save all registers 742 124 ; in the current process descrition. 743 124 ; exit is made to here with: 744 124 ; w1 = top register dump 745 124 ; w2 = 2 * interrupt number 746 124 ; ex = 0 747 124 747 124 c1: wa w2 b0 ; monfunc := cause + int.table.base - mon.proc.base; 748 126 748 126 ; monitor call entry: 749 126 ; 750 126 ; if the current process executes a montor call, the cpu will 751 126 ; save all the registers in the current process description. 752 126 ; exit is made to here with: 753 126 ; w1 = top register dump 754 126 ; w2 = monitor function 755 126 ; ex = 0 756 126 756 126 c0: al w1 x1-a178 ; w1 := current process; 757 128 jl. (x2+b16.) ; switch out through int.table or monproc.table; 758 130 758 130 ; second level external interrupt entry: 759 130 ; 760 130 ; exit is made to here with: 761 130 ; w1 = top register dump 762 130 ; w2 = 2 * interrupt number 763 130 763 130 c8: sn w2 2*6 ; if cause = powerfail then 764 132 jl c6 ; goto power fail routine; 765 134 jl -3<1 ; halt; 766 136 766 136 ; program errors in the current process are transferred to here, 767 136 ; (as external interrupts): 768 136 ; 769 136 ; w1 = cur 770 136 c2: ; internal interrupts, overflow, spill, escape errors: 771 136 c3: ; monitor bugs (i.e. exception- or escape-addresses 772 136 ; outside write-limits of process) 773 136 c4: ; bus error in operand transfer: (no strategy yet) 774 136 c5: ; bus error in instruction fetch: (- - - ) 775 136 jl w2 (b31) ; call errorlog 776 138 al w0 a96 ; state := running after error; 777 140 jl w3 d9 ; remove internal(cur, running after error); 778 142 jl c99 ; goto interrupt return; 779 144 779 144 ; parameter errors in monitor call: 780 144 ; 781 144 ; all monitor procedures check that the parameters are 782 144 ; within certain limits. 783 144 ; if the parameters are wrong, the calling process is break'ed. 784 144 ; 785 144 ; (all regs irrellevant) 786 144 786 144 b. j10 w. ; 787 144 ; definitin of exception regdump: 788 144 j0 = a29 - a28 ; w0, w1 789 144 j1 = a31 - a28 ; w2, w3 790 144 j2 = a33 - a28 ; status, ic 791 144 j3 = a177- a28 ; cause, sb 792 144 a180 = j3 + 2 ; top of exception regdump = new rel ic 793 144 793 144 c29: ; internal 3: 794 144 rl w1 b1 ; 795 146 al w3 6 ; 796 148 rs w3 x1+a176 ; cause (cur) := 6; i.e. monitor call break; 797 150 797 150 rl w2 x1+a27 ; w2 := exception address (cur); 798 152 sn w2 0 ; if exception address = 0 then 799 154 jl c2 ; goto internal interrupt; 800 156 al w3 x2 ; save w2 and 801 158 jl w2 (b31) ; call errorlog 802 160 al w2 x3 ; restore w2 803 162 803 162 wa w2 x1+a182 ; w2 := abs exception address; 804 164 804 164 dl w0 x1+a29 ; move: save w0 805 166 ds w0 x2+j0 ; save w1 806 168 dl w0 x1+a31 ; save w2 807 170 ds w0 x2+j1 ; save w3 808 172 dl w0 x1+a33 ; save status 809 174 ds w0 x2+j2 ; save ic 810 176 ; rs w0 x1+a28 ; save w0 := save ic; 811 176 ; al w0 14<2+0 ; 812 176 ; rs w0 x1+a29 ; save w1 := 'jd'-instruction; 813 176 dl w0 x1+a177 ; save cause (= 6) 814 178 ds w0 x2+j3 ; save sb to user exception addres; 815 180 ; rs w0 x1+a30 ; save w2 := save sb; 816 180 ; rs w3 x2+a31 ; save w3 := save cause (= 6); 817 180 ws w2 x1+a182 ; w2 := logic user exception address; 818 182 al w2 x2+a180 ; 819 184 rs w2 x1+a33 ; save ic := exception address + no of regdump bytes 820 186 e. ; 821 186 ;. ..... husk at nulstille addresse-bits i status ..... 822 186 ; continue with interrupt return; 823 186 823 186 ; interrupt return: 824 186 ; a new internal process may have been put up in front of 825 186 ; the time slice queue, due to an external interrupt, or because 826 186 ; the current monitor call was 'send message' or the like. 827 186 ; therefore it must be tested, that the current process is still 828 186 ; the one in front. if not: select that one. 829 186 829 186 c24: ; dummy interrupt 830 186 c99: ; interrupt return: 831 186 dl w2 b2 ; w1 := cur; w2 := first in time slice queue; 832 188 sn w1 x2-a16 ; if cur = first then 833 190 ri a179 ; return interrupt; 834 192 ; (preferably without reloading limit-copies) 835 192 835 192 ; initialize the previous interrupt stack element: 836 192 al w2 x2-a16 ; cur := new cur; i.e. first in time slice queue; 837 194 rs w2 b1 ; 838 196 rl w0 x2+a35 ; time slice := quantum(new current); 839 198 rs w0 b11 ; 840 200 gg w3 b91 ; w3 := inf (= address of current stack element); 841 202 dl w1 x2+a170 ; move: user escape address (cur) 842 204 ; user exception address (cur) 843 204 ds w1 x3+a325+a328; 844 206 al w0 x2+a28 ; address of regdump area (cur) 845 208 rs w0 x3+a325+a326; to: previous interrupt stack element; 846 210 846 210 c.a400-1 847 210 ; insert process extension addresses in monitor table 848 210 dl w1 x2+a306 ; 849 210 wa w0 x2+a182 ; 850 210 wa w1 x2+a182 ; 851 210 ds w1 b28 ; 852 210 z. 853 210 853 210 ; if the new current process is a driver process then maybe 854 210 ; exchange driver std-locations: 855 210 855 210 rl w0 x2+a302 ; if the new current process has not 856 212 se w0 0 ; defined a 'wait first event' 857 214 sn w2 (b21) ; or the new cur = owner of std-locations then 858 216 ri a179 ; return interrupt; 859 218 ; (limit-copies must be initialized) 860 218 860 218 ; the contents of the std-driver-locations have to be exchanged: 861 218 ; 862 218 ; save the old contents in the outpointed process description: 863 218 ; 864 218 rl w3 b21 ; w3 := previous owner of std locations; 865 220 dl w1 g21 ; move: g20 866 222 ds w1 x3+a302+4 ; g21 867 224 dl w1 g23 ; g22 868 226 ds w1 x3+a302+8 ; g23 869 228 rl w1 g24 ; g24 870 230 rs w1 x3+a302+10; b18 871 232 dl w1 b19 ; b19 872 234 ds w1 x3+a302+14; to: previous process description; 873 236 873 236 ; restore the std-locations from the new current process: 874 236 rs w2 b21 ; new owner := current process; 875 238 dl w1 x2+a302+4 ; move: g20 876 240 ds w1 g21 ; g21 877 242 dl w1 x2+a302+8 ; g22 878 244 ds w1 g23 ; g23 879 246 rl w1 x2+a302+10; g24 880 248 rs w1 g24 ; b18 881 250 dl w1 x2+a302+14; b19 882 252 ds w1 b19 ; from: new current process; 883 254 883 254 ri a179 ; return interrupt; 884 256 ; (limit-copies must be initialized) 885 256 885 256 ; power failure: 886 256 ; 887 256 ; may occur at any level 888 256 ; 889 256 ; save the current interrupt stack entry address, unless 890 256 ; already saved 891 256 ; (this should prevent powerfail-cascades from disturbing the system) 892 256 892 256 b. h10, i10 w. ; 893 256 c6: gg w2 b91 ; w2 := current stack element; 894 258 rl w3 h0 ; w3 := previous power up element; 895 260 sn w3 0 ; if previous element is free then 896 262 rs w2 h0 ; power up element := current stack element; 897 264 al w2 0 ; ilevc := 0; 898 266 gp w2 b90 ; (i.e. the following will provoke a systemfault) 899 268 jl -1<1 ; halt; 900 270 900 270 h0: b49 ; power up element: initially monitor element 901 272 901 272 ; power up: 902 272 ; 903 272 ; initialize: montop (i.e. max monitor function) 904 272 ; size (i.e. core size) 905 272 ; inf (i.e. power up element) 906 272 ; 907 272 ; clear any pending interrupt bits, because they may be irrellevant 908 272 ; 909 272 ; entry conditions: 910 272 ; inf register = 1 911 272 ; totally disabled 912 272 912 272 c25: al w3 -1<11 ; montop := 1 < 11 913 274 ac w3 x3+b17 ; - top monitor function number; 914 276 gp w3 b93 ; 915 278 915 278 rl w3 b12 ; size := number of storage bytes; 916 280 gp w3 b92 ; 917 282 c.(:a90>0 a.1:)-1 918 282 jl. w3 d140. ; dump core via fpa 919 282 z. 920 282 920 282 920 282 al w3 6 ; ilevc := 0 < 12 + 6; 921 284 gp w3 b90 ; i.e. enable for powerfail; 922 286 922 286 rl w3 h0 ; w3 := power up element; 923 288 sn w3 0 ; if power up element = 0 then 924 290 jl -2<1 ; halt; i.e. power fail was not serviced; 925 292 rs w3 b75 ; after powerfail := true; 926 294 ; (should be tested by clockdriver) 927 294 927 294 rl w2 b73 ; intno := max external interrupt number; 928 296 i0: gp w2 b95 ; rep: clear (intno) in cpu; 929 298 al w2 x2-1 ; intno := intno - 1; 930 300 sl w2 6+1 ; if intno > powerfail then 931 302 jl i0 ; goto rep; 932 304 al w1 0 ; (prepare a new h0...) 933 306 933 306 je k+2 ; (if any power fail during this start up, 934 308 jd k+2 ; it will be 'serviced' now, i.e. systemfault) 935 310 935 310 ; the following sequence of instructions have to be executed 936 310 ; without any disturbance, else the system won't work 937 310 rs w1 h0 ; clear previous power up element; 938 312 ; (i.e. prevent two consecutive powerups) 939 312 gp w3 b91 ; inf := power up element; 940 314 ri a179 ; return interrupt; 941 316 ; (the limit-copies must be initialized) 942 316 e. ; end of power fail/restart 943 316 943 316 ; procedure deliver external interrupt 944 316 ; 945 316 ; when an external interrupt is accepted by the monitor, 946 316 ; control is transferred out into the corresponding 947 316 ; device description, which should contain: 948 316 ; 949 316 ; dev descr + a240 : jl w2 c51 950 316 ; 951 316 ; return must be made to the standard interrupt return action, 952 316 ; which will take care of a possible selection of the driver. 953 316 ; 954 316 ; call: w2 = dev descr + a241 955 316 ; return address = interrupt return 956 316 956 316 c51: rl w3 x2-a241+a230; w3 := top of executed channel program; 957 318 al w0 4 ; result := 4; (i.e. prepare for abnormal termination) 958 320 se w3 0 ; if top command address defined then 959 322 bl w3 x3-6+1 ; w3 := last command executed; 960 324 sn w3 -1<8 ; if last command = 'stop' then 961 326 al w0 0 ; result := 0; 962 328 sn w3 4<8 ; if last command = 'wait' then 963 330 al w0 5 ; result := 5; 964 332 964 332 c50: al w3 c99 ; link := interrupt return; 965 334 ; continue with deliver interrupt 966 334 966 334 ; procedure deliver interrupt 967 334 ; function: delivers the interrupt operation in the event queue 968 334 ; of the corresponding driver process. 969 334 ; the driver process is started, if it was waiting for 970 334 ; an event. 971 334 ; 972 334 ; call: w0 = result (=0, 1, 2, 3, 4, 5, 6), w2 = operation, w3 = link 973 334 ; exit: all regs undef 974 334 ; return address: link 975 334 975 334 b. h10 w. ; 976 334 d121:rs w3 h0 ; save (return); 977 336 jl w1 d131 ; set result and descrease all stopcounts; 978 338 ; w2 = device descr 979 338 979 338 rl w1 x2+a250 ; driver := driverproc (device descr); 980 340 sh w1 0 ; if driver undefined then 981 342 jl (h0) ; return; 982 344 982 344 al w2 x2+a241 ; oper := timeout operation (device descr); 983 346 rl w3 h0 ; restore (return); 984 348 984 348 bz w0 x1+a13 ; state := state(driver); 985 350 sn w0 a104 ; if driver is waiting for event then 986 352 jl d127 ; goto take interrupt; 987 354 987 354 al w1 x1+a15 ; link (event queue (driver) , oper); 988 356 jl d6 ; return; 989 358 h0: 0 ; saved return; 990 360 e. ; 991 360 991 360 ; procedure take interrupt 992 360 ; function: let the driver receive the interrupt operation at once 993 360 ; 994 360 ; call: w1 = driver process, w2 = interrupt operation, w3 = link 995 360 ; exit: all regs undef 996 360 ; return address: link 997 360 997 360 d127:al w2 x2-a241+a246; 998 362 rs w2 x1+a30 ; save w2 (driver) := address of driver service inst 999 364 999 364 al w0 2 ; save w0 (driver) := 2; i.e. indicate interrupt; 1000 366 rs w0 x1+a28 ; link internal (driver); 1001 368 ; (only relevant after deliver interrupt) 1002 368 jl d10 ; return; 1003 370 1003 370 ; procedure prepare driver(proc) 1004 370 ; function: initializes current external process and current buffer 1005 370 ; exits to the interrupt address given in proc: 1006 370 ; int addr : normal exit 1007 370 ; 1008 370 ; the call must be made like this: 1009 370 ; 1010 370 ; proc + a246: jl w1 c30 ; driver service instruction 1011 370 ; --- 1012 370 ; proc + a245: interrupt address 1013 370 ; --- 1014 370 ; proc + a54 : next message buf 1015 370 ; 1016 370 ; call: w1 = proc + a247 1017 370 ; exit: w0 = result(proc), w1 = proc, w2 = buf(proc) 1018 370 ; int.addr : normal exit 1019 370 1019 370 c30: al w1 x1-a247 ; 1020 372 rs w1 b19 ; current receiver := buf; 1021 374 rl w2 x1+a54 ; 1022 376 rs w2 b18 ; current buffer address := next mess(proc); 1023 378 rl w0 x1+a244 ; result := timeout(proc); 1024 380 jl (x1+a245) ; goto interrupt address(proc); 1025 382 1025 382 ; procedure clear device 1026 382 ; 1027 382 ; function: everything is cleared-up in the device description, 1028 382 ; i.e. the controller is reset (except after 'wait'-program) 1029 382 ; a possible pending interrupt is cleared 1030 382 ; a possible pending interrupt operation is removed 1031 382 ; if any stopcounts were increased, they will be decreased 1032 382 ; 1033 382 ; call: w1 = link, w2 = device descr 1034 382 ; exit: w2 = unchanged, w0, w1, w3 = undef 1035 382 ; return address: link 1036 382 1036 382 d129: ; unconditionally reset: 1037 382 am a235-a225; (point at something <> 0) 1038 384 d130: ; conditionally reset: 1039 384 rl w0 x2+a225 ; get transfer code to see if transfer in progress; 1040 386 rl w3 x2+a235 ; w3 := device address(device description); 1041 388 ; it should be noted, that the controller is not reset when a wait-program is timed out 1042 388 se w0 0 ; if transfer code <> 0 then 1043 390 do w3 x3+2.01<1 ; reset device (device address); 1044 392 1044 392 ls w3 1 ; entry := device address 1045 394 ls w3 -1 ; (remove bit 0) 1046 396 wa w3 b65 ; + controller table base; 1047 398 1047 398 rl w0 x3+a313 ; w0 := interrupt number(controller table (entry)); 1048 400 gp w0 b95 ; clear interrupt bit in cpu; 1049 402 1049 402 al w2 x2+a242 ; oper := timeout operation(device descr); 1050 404 ; continue with set result and decrease all stopcounts 1051 404 ; (result = undef) 1052 404 1052 404 ; procedure set result and decrease all stopcounts 1053 404 ; 1054 404 ; call: w0 = result: 0 = transfer terminated by stop 1055 404 ; 1 = bus reject when started 1056 404 ; 2 = bus timeout when started (i.e. disconnected) 1057 404 ; (3 = software timeout) 1058 404 ; 4 = transfer terminated, before stop 1059 404 ; 5 = wait-program terminated 1060 404 ; (6 = power restart) 1061 404 ; w1 = link w2 = timeout operation 1062 404 ; exit: w2 = device description, w0, w1, w3 = undef 1063 404 1063 404 d131:rs w0 x2-a241+a244; save result in timeout-field; 1064 406 se w2 (x2) ; (if in timer queue then 1065 408 jl w3 d5 ; remove(timeout operation); ) 1066 410 al w2 x2-a241 ; w2 := device descr; 1067 412 ; continue with decrease all stopcounts 1068 412 1068 412 ; procedure decrease all stopcounts 1069 412 ; 1070 412 ; function: if any stopcounts increased, then decrease them again 1071 412 ; transfer code(device descr) := 0 1072 412 ; 1073 412 ; call: w1 = link, w2 = device descr 1074 412 1074 412 b. h10, i10 w. ; 1075 412 d132:ds w2 h1 ; save (link, device descr); 1076 414 rl w1 x2+a225 ; get transfer code(device descr); 1077 416 sn w1 -1 ; if no transfer to processes then 1078 418 jl i1 ; goto clear up; 1079 420 1079 420 so w1 2.1 ; if transfer code odd then 1080 422 jl i0 ; begin i.e. transfer to/from driver area; 1081 424 1081 424 rl w1 x2+a250 ; driver := driver process (device descr); 1082 426 jl w3 d133 ; decrease stopcount(driver); 1083 428 1083 428 rl w2 h1 ; restore(device descr); 1084 430 al w1 -1<1 ; 1085 432 la w1 x2+a225 ; restore (transfer code) (even) 1086 434 i0: ; end; 1087 434 sn w1 0 ; if transfer code shows transfer to/from sender the 1088 436 jl i1 ; begin 1089 438 1089 438 jl w3 d133 ; decrease stopcount(sender); 1090 440 rl w2 h1 ; restore (device descr); 1091 442 ; end; 1092 442 i1: al w1 0 ; clear up: 1093 444 rs w1 x2+a225 ; transfer code(device descr) := 0; i.e. no transfer 1094 446 jl (h0) ; return; 1095 448 1095 448 h0: 0 ; saved return 1096 450 h1: 0 ; saved device descr 1097 452 e. ; 1098 452 1098 452 ; procedure decrease stopcount 1099 452 ; 1100 452 ; function: the stopcount of the process is decreased by 1. 1101 452 ; if the stopcount becomes zero, and the process is waiting 1102 452 ; to be stopped, the process is stopped now (i.e. put in 1103 452 ; the state 'waiting for start by...'), and the following will 1104 452 ; be done: 1105 452 ; if the process was stopped by its parent, the stop-answer 1106 452 ; will be send to the parent (as defined by the wait-address 1107 452 ; in the process), indicating that the stopping has been 1108 452 ; accomplished. 1109 452 ; the decrease-action is repeated for the parent etc.etc. 1110 452 ; 1111 452 ; call: w1 = process, w3 = link 1112 452 ; exit: all regs undef 1113 452 ; return address: link 1114 452 1114 452 b. i10 w. ; 1115 452 d133: ; decrease stopcount: 1116 452 i0: al w0 -1 ; loop: 1117 454 ba w0 x1+a12 ; stopcount (process) := 1118 456 hs w0 x1+a12 ; stopcount (process) - 1; 1119 458 bz w2 x1+a13 ; 1120 460 sn w0 0 ; if stopcount <> 0 or 1121 462 so w2 a105 ; process not waiting for being stopped then 1122 464 jl x3 ; return; 1123 466 1123 466 al w0 x2+a106 ; state (process) := state (process) 1124 468 hs w0 x1+a13 ; + 'waiting for start'; 1125 470 1125 470 ; prepare for repeating the loop: 1126 470 rl w2 x1+a40 ; buf := wait address(process); 1127 472 rl w1 x1+a34 ; process := parent (process); 1128 474 se w0 a99 ; if state <> 'waiting for start by parent' then 1129 476 jl i0 ; goto loop; 1130 478 1130 478 ; prepare the buffer for returning the answer: 1131 478 al w0 1 ; receiver(buf) := result := 1; 1132 480 rs w0 x2+a141 ; 1133 482 al w0 x3 ; (save return) 1134 484 jl. w3 d15. ; deliver answer(buf); 1135 486 rl w3 0 ; (restore return) 1136 488 jl i0 ; goto loop; 1137 490 e. ; 1138 490 1138 490 ; return result in save w0(cur); 1139 490 ; entry: w1=cur 1140 490 r5: am 5-4 ; 1141 492 r4: am 4-3 ; 1142 494 r3: am 3-2 ; 1143 496 r2: am 2-1 ; 1144 498 r1: am 1-0 ; 1145 500 r0: al w0 0 ; 1146 502 r28: rs w0 x1+a28 ; save w0:=result; 1147 504 jl c99 ; goto interrupt return; 1148 506 1148 506 ; elementary link-procedures: 1149 506 1149 506 ; procedure remove(elem); 1150 506 ; comment: removes a given element from its queue and leaves the element linked to itself. 1151 506 ; call: w2=elem, w3=link 1152 506 ; exit: w0, w1, w2=unchanged, w3=next(elem) 1153 506 ; return address: link 1154 506 1154 506 b. i1 w. 1155 506 1155 506 d5: rs w3 i0 ; save return; 1156 508 rl w3 x2 ; w3 := next(elem); 1157 510 rx w2 x2+2 ; w2 := prev(elem); prev(elem) := elem; 1158 512 rs w3 x2 ; next(w2) := next(elem); 1159 514 rx w2 x3+2 ; w2 := elem; prev(next(elem)) := old prev(elem); 1160 516 rs w2 x2 ; next(elem) := elem; 1161 518 jl (i0) ; return; 1162 520 1162 520 ; procedure increase bufclaim, remove release buf; 1163 520 ; comment: bufclaim(cur) is increased, continue with release buf 1164 520 ; call: w1=cur, w2=buf, w3=link 1165 520 ; exit: w0, w1=undef, w2, w3=unchanged 1166 520 ; return address: link 1167 520 1167 520 d109: ; 1168 520 al w0 1 ; 1169 522 ba w0 x1+a19 ; increase(bufclaim(cur)); 1170 524 hs w0 x1+a19 ; 1171 526 ; continue with d106 1172 526 1172 526 ; procedure remove release buf; 1173 526 ; comment: removes the buffer from its queue, continue with release mess buf 1174 526 ; call: w2=buf, w3=link 1175 526 ; exit: w0, w2, w3=unchanged, w1=undef 1176 526 ; return address: link 1177 526 1177 526 d106: ; 1178 526 al w1 x3 ; save return 1179 528 jl w3 d5 ; remove (buf); 1180 530 al w3 x1 ; restore return; 1181 532 ; continue with d13 1182 532 1182 532 ; procedure release mess buf(buf); 1183 532 ; comment: clears sender and receiver and links the buffer to the pool. 1184 532 ; call: w2=buf, w3=link 1185 532 ; exit: w0=unchanged, w1=undef, w2, w3=unchanged 1186 532 ; return address: link 1187 532 1187 532 d13: al w1 0 ; sender(buf):=0; 1188 534 rs w1 x2+4 ; receiver(buf):=0; 1189 536 rs w1 x2+6 ; 1190 538 c. (:a128>2 a. 1:) - 1; if rc6000 then 1191 538 rl w1 b8 ; head:=next(mess buf pool); (i.e. link in front of pool) 1192 538 z. ; else 1193 538 c. - (:a128>2 a. 1:) ; 1194 538 al w1 b8 ; head := mess buf pool head; (i.e. link in rear); 1195 540 z. ; 1196 540 1196 540 ; procedure link(head, elem); 1197 540 ; comment: links the element to the end of the queue 1198 540 ; call: w1=head, w2=elem, w3=link 1199 540 ; exit: w0, w1, w2=unchanged, w3=old last(head); 1200 540 1200 540 d6: rs w3 i0 ; save return; 1201 542 rl w3 x1+2 ; old last:=last(head); 1202 544 rs w2 x1+2 ; last(head):=elem; 1203 546 rs w2 x3+0 ; next(old last):=elem; 1204 548 rs w1 x2+0 ; next(elem):=head; 1205 550 rs w3 x2+2 ; last(elem):=old last; 1206 552 jl (i0) ; return; 1207 554 i0: 0 ; saved return: remove, link 1208 556 e. 1209 556 1209 556 ; procedure remove user(internal, proc); 1210 556 ; procedure remove reserver(internal, proc); 1211 556 ; comment: removes the id-bit of internal from the reserver- and-or userbits 1212 556 ; call: w1=internal, w2=proc, w3=link 1213 556 ; exit: w0=undef, w1,w2,w3=unchanged 1214 556 ; return address: link 1215 556 1215 556 d123:rl w0 x2+a53 ; users.proc := 1216 558 sz w0 (x1+a14) ; users.proc exclusive internal; 1217 560 ws w0 x1+a14 ; 1218 562 rs w0 x2+a53 ; 1219 564 1219 564 d124:rl w0 x2+a52 ; reserver.proc := 1220 566 sz w0 (x1+a14) ; reserver.proc exclusive internal; 1221 568 ws w0 x1+a14 ; 1222 570 rs w0 x2+a52 ; 1223 572 1223 572 jl x3 ; return; 1224 574 1224 574 ; procedure insert reserver(internal, proc); 1225 574 ; procedure insert user(internal, proc); 1226 574 ; comment: adds the id-bit of internal to reserver- and-or userbits 1227 574 ; call: w1=internal, w2=proc, w3=link 1228 574 ; exit: w0=undef, w1,w2,w3=unchanged 1229 574 ; return address: link 1230 574 1230 574 d125:rl w0 x2+a52 ; reserver.proc := 1231 576 lo w0 x1+a14 ; reserver.proc inclusive internal; 1232 578 rs w0 x2+a52 ; 1233 580 1233 580 d126:rl w0 x2+a53 ; users.proc := 1234 582 lo w0 x1+a14 ; users.proc inclusive internal; 1235 584 rs w0 x2+a53 ; 1236 586 1236 586 jl x3 ; return; 1237 588 1237 588 ; procedure check user; 1238 588 ; 1239 588 ; call: w1=internal, w2=proc, w3=link 1240 588 ; exit: w0=undef, w1, w2, w3=unchanged 1241 588 ; return address: link+2: cur was user 1242 588 ; link : cur was not user 1243 588 1243 588 d102: ; 1244 588 rl w0 x2+a53 ; if user(proc) logand idbit(internal) = 1 then 1245 590 sz w0 (x1+a14) ; 1246 592 jl x3+2 ; return to link+2; i.e. user 1247 594 jl x3 ; return to link; i.e. not user 1248 596 1248 596 ; procedure check any reserver; 1249 596 ; 1250 596 ; call: w1=internal, w2=proc, w3=link 1251 596 ; exit: w0=undef, w1, w2, w3=unchanged 1252 596 ; return address: link : other process is reserver 1253 596 ; link+2: internal is reserver 1254 596 ; link+4: not reserved by anyone 1255 596 1255 596 d113: ; 1256 596 rl w0 x2+a52 ; if reserver(proc)=0 then 1257 598 sn w0 0 ; 1258 600 jl x3+4 ; return to link+4; i.e. not reserved 1259 602 se w0 (x1+a14) ; if reserver(proc) <> idbit(cur) then 1260 604 jl x3 ; return to link; i.e. other reserver; 1261 606 jl x3+2 ; return to link+2; i.e. already reserved 1262 608 1262 608 ; procedure check mess area and name(save w3) area; 1263 608 ; procedure check name(save w3) area; 1264 608 ; procedure check name(save w2) area; 1265 608 ; comment: checks that the areas are within the process 1266 608 ; call: w1=cur, w3=link 1267 608 ; exit: w0=undef, w1=unchanged, w2=name, w3=unchanged 1268 608 ; return address: link: within process 1269 608 ; c29 : not within process 1270 608 1270 608 d110: ; check message area and name area: 1271 608 rl w2 x1+a29 ; 1272 610 al w0 x2+14 ; mess:=save w1(cur); 1273 612 sh w0 0 ; 1274 614 jl c29 ; if overflow or 1275 616 sl w2 (x1+a17) ; mess<first addr(cur) or 1276 618 sl w0 (x1+a18) ; mess+14>=top addr(cur) then 1277 620 jl c29 ; goto internal 3; 1278 622 1278 622 d17: am a31-a30; check name(save w3) area: 1279 624 d111: ; check name(save w2) area: 1280 624 rl w2 x1+a30 ; 1281 626 al w0 x2+6 ; 1282 628 1282 628 ; procedure check within(first, last); 1283 628 ; comment: checks that the specified area is within the process 1284 628 ; call: w0=last, w1=cur, w2=first, w3=link 1285 628 ; exit: w0, w1, w2, w3=unchanged 1286 628 ; return address: link: within process 1287 628 ; c29 : not within process 1288 628 1288 628 d112: ; check within: 1289 628 sh w0 0 ; 1290 630 jl c29 ; if overflow or 1291 632 sl w2 (x1+a17) ; first<first addr(cur) or 1292 634 sl w0 (x1+a18) ; last>=top addr(cur) then 1293 636 jl c29 ; goto internal 3; 1294 638 jl x3 ; return; 1295 640 1295 640 ; procedure check message area and buf (=d18+d12); 1296 640 ; 1297 640 ; call: w1=cur, w3=link 1298 640 ; exit: w0=undef, w1=cur, w2=buf, w3=unchanged 1299 640 ; return address: link: ok 1300 640 ; c29 : mess area outside cur 1301 640 ; c29 : buf not message buf 1302 640 1302 640 d103: ; 1303 640 rl w2 x1+a29 ; mess:=save w1(cur); 1304 642 al w0 x2+14 ; 1305 644 sh w0 0 ; if overflow or 1306 646 jl c29 ; 1307 648 sl w2 (x1+a17) ; mess<first addr(cur) or 1308 650 sl w0 (x1+a18) ; mess+14>=top addr(cur) then 1309 652 jl c29 ; goto internal 3; 1310 654 1310 654 ; procedure check message buf; 1311 654 ; comment: checks whether the save w2 of the internal process is a message buffer address 1312 654 ; call: w1=internal, w3=link 1313 654 ; exit: w0=undef, w1=cur, w2=buf, w3=unchanged 1314 654 ; return address: link: buffer ok 1315 654 ; c29 : save w2 not message buffer 1316 654 1316 654 d12: rl w2 x1+a30 ; buf:=save w2(internal); 1317 656 sl w2 (b8+4) ; if buf<mess buf pool start or 1318 658 sl w2 (b8+6) ; buf >=mess buf pool end then 1319 660 jl c29 ; goto internal 3; 1320 662 al w1 x2 ; 1321 664 ws w1 b8+4 ; if (buf-pool start) mod mess buf size 1322 666 al w0 0 ; <>0 then 1323 668 wd w1 b8+8 ; goto internal 3; 1324 670 rl w1 b1 ; w1:=cur; 1325 672 sn w0 0 ; 1326 674 jl x3 ; return; 1327 676 jl c29 ; 1328 678 1328 678 ; procedure check event(proc, buf); 1329 678 ; comment: checks that buf is the address of an operation in the event queue of the internal process 1330 678 ; call: w1=proc, w2=buf, w3=link 1331 678 ; exit: w0=undef, w1, w2, w3=unchanged 1332 678 ; return address: link: buffer address ok 1333 678 ; c29 : buf is not in the queue 1334 678 1334 678 b. i0 w. 1335 678 d19: al w0 x2 ; 1336 680 al w2 x1+a15 ; oper:=event q(proc); 1337 682 i0: rl w2 x2+0 ; next: oper:=next(oper); 1338 684 sn w2 x1+a15 ; if oper=event q(proc) then 1339 686 jl c29 ; goto internal 3; (i.e. not in queue); 1340 688 se w0 x2 ; if buf<>oper then 1341 690 jl i0 ; goto next; 1342 692 jl x3 ; return; 1343 694 e. 1344 694 1344 694 ; procedure check and search name (=d17+d11); 1345 694 ; 1346 694 ; call: w1=cur, save w3(cur)=name, w3=link 1347 694 ; exit: w0, w1=unchanged, w2=name, w3=entry 1348 694 ; return address: link: entry not found 1349 694 ; link+2: entry found 1350 694 ; c29 : name area outside current process 1351 694 b. i20 w. 1352 694 1352 694 d101: ; 1353 694 ds w1 i1 ; save(w0, cur); 1354 696 rl w2 x1+a31 ; name:=save w3(cur); 1355 698 al w0 x2+6 ; 1356 700 sh w0 0 ; if overflow or 1357 702 jl c29 ; 1358 704 sl w2 (x1+a17) ; name<first addr(cur) or 1359 706 sl w0 (x1+a18) ; name+6>=top addr(cur) then 1360 708 jl c29 ; goto internal 3; 1361 710 dl w1 x1+a43 ; w0w1:=catbase(cur); 1362 712 jl i14 ; goto search name(name, entry, base); 1363 714 1363 714 ; the following procedures searches the name table for a given entry and delivers its entry in 1364 714 ; the name table. if name is undefined, the entry is name table end. 1365 714 1365 714 ; procedure search name(name, entry); 1366 714 ; call: w2=name, w3=link 1367 714 ; exit: w0, w1, w2=unchanged, w3=entry 1368 714 ; return address: link : name not found, w3=(b7) 1369 714 ; link+2: name found 1370 714 1370 714 d11: ds w1 i1 ; save(w0, w1); 1371 716 am (b1) ; 1372 718 dl w1 +a43 ; base:=catbase(cur); 1373 720 i14: al w3 x3+1 ; link := link + 1; i.e. destinguish between normal and error return; 1374 722 1374 722 ; procedure search name(name, entry, base); 1375 722 ; call: w0, w1=base, w2=name, w3=link 1376 722 ; exit: w0, w1=undef, w2=unchanged, w3=entry 1377 722 ; return address: link : name not found, w3=(b7) 1378 722 ; link : name found, w3 <> (b7) 1379 722 1379 722 d71: ds w3 i3 ; save (name, return); 1380 724 i4: al w1 x1-1;used ; 1381 726 bs w0 i4+1 ; 1382 728 ds w1 i6 ; base:=base+(1, -1); 1383 730 dl w1 d73 ; 1384 732 ds w1 i8 ; min base:=extreme; 1385 734 rl w1 b7 ; 1386 736 rs w1 i9 ; found:=name table end; 1387 738 rl w1 b1 ; get physical name address 1388 740 wa w2 x1+a182 ; 1389 742 dl w1 x2+6 ; 1390 744 ds w1 i13 ; move name to last name in name table; 1391 746 dl w1 x2+2 ; 1392 748 sn w0 0 ; if name(0)<>0 then 1393 750 jl i18 ; 1394 752 ds w1 i11 ; 1395 754 rl w3 b3 ; for entry:=name table start 1396 756 jl i17 ; 1397 758 i15: dl w1 i11 ; 1398 760 i16: al w3 x3+2 ; step 2 until name table end do 1399 762 i17: rl w2 x3 ; 1400 764 sn w1 (x2+a11+2) ; begin 1401 766 se w0 (x2+a11+0) ; proc:=name table(entry); 1402 768 jl i16 ; 1403 770 dl w1 i13 ; 1404 772 sn w0 (x2+a11+4) ; 1405 774 se w1 (x2+a11+6) ; if name.proc=name and 1406 776 jl i15 ; 1407 778 sn w2 c98 ; 1408 780 jl i18 ; 1409 782 dl w1 x2+a49 ; 1410 784 sl w0 (i7) ; lower.proc>=lower.min and 1411 786 sl w0 (i5) ; lower.proc<=lower.base and 1412 788 jl i15 ; 1413 790 sh w1 (i8) ; upper.proc<=upper.min and 1414 792 sh w1 (i6) ; upper.proc>=upper base then 1415 794 jl i15 ; begin 1416 796 ds w1 i8 ; min:=interval.proc; 1417 798 rs w3 i9 ; found:=entry; 1418 800 jl i15 ; end; 1419 802 i18: ; end; 1420 802 dl w0 i0 ; restore(w0, w1, w2); 1421 804 dl w2 i2 ; w3:=found; 1422 806 sn w3 (b7) ; if w3=name table end then 1423 808 jl (i3) ; return to link 1424 810 am (i3) ; else 1425 812 jl +1 ; return to link+1; 1426 814 1426 814 i9: 0 ;i0-2: found (i.e. current best entry, or (b7)) 1427 816 i0: 0 ;i1-2: saved w0 1428 818 i1: 0 ;i2-2: saved w1 1429 820 i2: 0 ;i3-2: saved w2 1430 822 i3: 0 ; saved return 1431 824 i5: 0 ;i6-2: lower base+1 for search 1432 826 i6: 0 ; upper base-1 for search 1433 828 i7: 0 ;i8-2: lower minimum 1434 830 i8: 0 ; upper minimum 1435 832 1435 832 ; the last entry in name table must point here: 1436 832 c98 = k-a11 1437 832 i10: 0 ; name to search for 1438 834 i11: 0 ; 1439 836 i12: 0 ; 1440 838 i13: 0 ; 1441 840 1441 840 a107 ; max base lower 1442 842 d72: a108 ; max base upper 1443 844 a107-1 ; extreme lower 1444 846 d73: a108+1 ; extreme upper 1445 848 e. 1446 848 1446 848 1446 848 ; procedure claim buffer 1447 848 ; 1448 848 ; call: w1=cur, w2=buf, w3=link 1449 848 ; exit: w0=undef, w1, w2, w3=unchanged 1450 848 ; return address: link: claim decreased ok 1451 848 ; c99 : claims exceeded, save w2(cur):=0 1452 848 1452 848 b. i0 w. 1453 848 d108: ; 1454 848 bz w0 x1+a19 ; if bufclaim(cur)=0 then 1455 850 sn w0 0 ; 1456 852 jl i0 ; goto no buffer; 1457 854 bs. w0 1 ; 1458 856 hs w0 x1+a19 ; decrease(bufclaim(cur)); 1459 858 ac w0 (x2+4) ; 1460 860 rs w0 x2+4 ; receiver(buf):=-receiver(buf); 1461 862 jl x3 ; return to link; 1462 864 i0: rs w0 x1+a30 ; no buffer: save w2(cur):=0; 1463 866 jl c99 ; goto interrupt return; 1464 868 e. 1465 868 1465 868 ; procedure regretted message 1466 868 ; comment simulates the release of a message buffer, as in wait answer. the bufclaim of the 1467 868 ; sender is increased. the buffer is removed and released (unless in state: received) 1468 868 ; 1469 868 ; call: w2=buf, w3=link 1470 868 ; exit: w0, w1, w2=unchanged, w3=undef 1471 868 1471 868 b. i20 w. 1472 868 i0: 0 ; saved w0 1473 870 i1: 0 ; saved w1 1474 872 i2: 0 ; saved w2 1475 874 i3: 0 ; saved w3 1476 876 i8: 0 ; internal 1477 878 d75: rs w3 i3 ; save(return); 1478 880 ds w1 i1 ; save(w0, w1); 1479 882 rl w1 x2+6 ; proc:=sender(buf); 1480 884 sh w1 0 ; if proc<=0 then 1481 886 jl i6 ; goto exit; (message already regretted); 1482 888 ac w0 x1 ; (only relevant from remove process); 1483 890 rs w0 x2+6 ; sender(buf):=-proc; (i.e. regretted); 1484 892 rl w0 x1+a10 ; if kind(proc) = pseudo kind 1485 894 sn w0 64 ; then proc:= main(proc); 1486 896 rl w1 x1+a50 ; if proc is neither internal process nor 1487 898 sz w0 -1-64 ; pseudo process 1488 900 rl w1 x1+a250 ; then proc:= driver proc(proc); 1489 902 1489 902 bz w3 x1+a19 ; 1490 904 al w3 x3+1 ; increase(bufclaim(proc)); 1491 906 hs w3 x1+a19 ; 1492 908 ; check if the buffer is claimed by receiver, or contains an answer: 1493 908 rl w1 x2+4 ; receiver:=receiver(buf); 1494 910 sh w1 0 ; if receiver<=0 then 1495 912 jl i6 ; goto exit; (i.e. claimed); 1496 914 sh w1 5 ; if receiver<=5 then 1497 916 jl i5 ; goto remove and release; (i.e. an answer); 1498 918 ; the message is neither answered nor claimed: 1499 918 rl w0 x1+a10 ; kind:=kind(receiver); 1500 920 se w0 0 ; if receiver is internal process or 1501 922 sn w0 64 ; pseudo process then 1502 924 jl i5 ; goto remove and release; 1503 926 i4: se w2 (x1+a54) ; if buf is first in queue then 1504 928 jl i5 ; 1505 930 al w0 -1 ; decrease(interrupt addr(proc)) 1506 932 wa w0 x1+a56 ; 1507 934 sz w0 1 ; unless already odd 1508 936 rs w0 x1+a56 ; 1509 938 i5: jl w3 d106 ; remove release(buf); 1510 940 i6: dl w1 i1 ; exit: restore(w0, w1); 1511 942 jl (i3) ; return; 1512 944 1512 944 ; procedure move mess(from, to); 1513 944 ; comment: moves 8 message (or answer) words from a given storage address to another. 1514 944 ; call: w1=from, w2=to, w3=link 1515 944 ; exit: w0=undef, w1, w2=unchanged, w3=undef 1516 944 ; return address: link 1517 944 1517 944 d14: rs w3 i3 ; 1518 946 dl w0 x1+2 ; 1519 948 ds w0 x2+2 ; 1520 950 dl w0 x1+6 ; move 8 words from (from) to (to); 1521 952 ds w0 x2+6 ; 1522 954 dl w0 x1+10 ; 1523 956 ds w0 x2+10 ; 1524 958 dl w0 x1+14 ; 1525 960 ds w0 x2+14 ; 1526 962 jl (i3) ; return; 1527 964 e. 1528 964 1528 964 1528 964 ; procedure update time(slice); 1529 964 ; comment: senses the timer and updates current time slice and time; 1530 964 ; 1531 964 ; call: w3=link 1532 964 ; exit: w0=undef, w1=unchanged, w2=slice, w3=unchanged 1533 964 ; return address: link 1534 964 1534 964 b. i9 w. 1535 964 d7: gg w2 b94 ; 1536 966 al w0 x2 ; new value:=sense(timer); 1537 968 ws w2 b14 ; increase:=new value-clock; 1538 970 rs w0 b14 ; clock:=new value; 1539 972 sh w2 -1 ; if increase<0 then 1540 974 wa w2 i9 ; increase:=increase+size of clock; 1541 976 ; comment: timer overflowed...; 1542 976 al w0 x2 ; 1543 978 wa w2 b11 ; slice:=slice+increase; 1544 980 rs w2 b11 ; 1545 982 1545 982 wa w0 b13+2 ; 1546 984 rs w0 b13+2 ; time low:=time low+increase; 1547 986 sx 2.01 ; 1548 988 jl i8 ; if carry then 1549 990 jl x3 ; 1550 992 1550 992 i8: al w0 1 ; time high:=time high+1; 1551 994 wa w0 b13 ; 1552 996 rs w0 b13 ; 1553 998 jl x3 ; return; 1554 1000 i9: 1<16 ; increase when timer overflows; 1555 1002 1555 1002 ; the following entries removes the current process from the timequeue, and initializes state. 1556 1002 ; call: w1=cur 1557 1002 ; return address: interrupt return 1558 1002 1558 1002 d105: ; remove wait message: 1559 1002 ; bz w0 x1+a19 ; 1560 1002 ; sn w0 0 ; if buf claim(cur)=0 then 1561 1002 ; jl d108 ; goto claim buffer (and exit with save w2=0); 1562 1002 am a102-a104 ; state:=wait message; 1563 1004 d107: ; remove wait event: 1564 1004 am a104-a103 ; state:=wait event; 1565 1006 d104: ; remove wait answer: 1566 1006 al w0 a103 ; state:=wait answer; 1567 1008 al w3 c99 ; return:=interrupt return; 1568 1010 ; continue with remove internal; 1569 1010 1569 1010 ; procedure remove internal(internal, proc state); 1570 1010 ; comment: removes the internal process from the timer queue and sets its state 1571 1010 ; after this a new current process is selected. 1572 1010 ; call: w0=proc state, w1=cur, w3=link 1573 1010 ; exit: w0, w1=undef, w2=cur+a16, w3=undef 1574 1010 ; return address: link 1575 1010 1575 1010 d9: rs w3 i0 ; save(return); 1576 1012 hs w0 x1+a13 ; state(cur):=proc state; 1577 1014 jl w3 d7 ; update time(slice); 1578 1016 rs w2 x1+a35 ; quantum(cur):=slice; 1579 1018 dl w3 b13+2 ; 1580 1020 ds w3 x1+a39+2 ; start wait(cur):=time; 1581 1022 al w2 x1+a16 ; 1582 1024 rl w3 i0 ; 1583 1026 jl d5 ; remove(cur+a16); 1584 1028 ; return; 1585 1028 1585 1028 i0: 0 ; saved return 1586 1030 1586 1030 ; procedure link internal(proc); 1587 1030 ; comment: links the internal process to the timer queue. the timer queue is kept as a 1588 1030 ; sorted list, according to the priority. (the smaller the priority is, the better 1589 1030 ; is the priority). 1590 1030 ; if the time quantum is less than the maximum time slice, the process will be 1591 1030 ; linked up in front of other processes with the same priority. otherwise in the 1592 1030 ; rear (the time quamtum of the process is transferred to runtime(proc), except 1593 1030 ; the amount which is already used of the next quantum). 1594 1030 ; call: w1=proc, w3=link 1595 1030 ; exit: w0, w1, w2, w3=undef 1596 1030 d10: bz w0 x1+a13 ; if state(proc) = running then 1597 1032 sn w0 a95 ; 1598 1034 jl x3 ; return; 1599 1036 1599 1036 rs w3 i0 ; save(return); 1600 1038 al w0 a95 ; 1601 1040 hs w0 x1+a13 ; state(proc):=running; 1602 1042 1602 1042 al w2 x1+a16 ; 1603 1044 rl w3 x1+a301 ; priority:=priority(proc); 1604 1046 rl w1 x1+a35 ; 1605 1048 sl w1 (b10) ; if quantum(proc)>=max slice then 1606 1050 jl i3 ; goto insert in rear; 1607 1052 1607 1052 al w3 x3-1 ; (code facility); 1608 1054 al w1 b2 ; worse:=timer q head; 1609 1056 i1: rl w1 x1 ; next: worse:=next(worse); 1610 1058 sl w3 (x1-a16+a301) ; if priority(worse)<priority then 1611 1060 jl i1 ; goto next; 1612 1062 i2: ; insert process: 1613 1062 jl w3 d6 ; link(worse, proc+a16); 1614 1064 se w3 b2 ; if proc is not linked as the front 1615 1066 jl (i0) ; internal then return; 1616 1068 rl w1 b1 ; 1617 1070 jl w3 d7 ; update time(slice); 1618 1072 rs w2 x1+a35 ; quantum(cur):=slice; (may actually be >= max slice); 1619 1074 sh w2 (b10) ; if old quantum <= max slice then 1620 1076 jl (i0) ; return; 1621 1078 ; the following will take care of the round-robin time scheduling; 1622 1078 rl w2 (b2) ; proclink := second proc in timer queue; 1623 1080 jl w3 d5 ; remove(proclink); 1624 1082 rl w3 x2-a16+a301; priority:=priority(proc); (as above) 1625 1084 rl w1 x2-a16+a35 ; quantum:=quantum(proc); (as above) 1626 1086 1626 1086 ; the process has been in front of the queue for more than the max time slice. 1627 1086 ; the run time should be updated with all the quantum, but this would give the process a 1628 1086 ; complete time slice next time. instead the used quantum is split in two parts: 1629 1086 ; the amount by which it exceeds a multiplum of the max slice, and the rest. these parts 1630 1086 ; are the increase in runtime and the new quantum. 1631 1086 ; finally the process is inserted in the rear of the timer queue, according to priority. 1632 1086 1632 1086 i3: al w0 a85-1 ; w0 := mask for extracting new quantum; 1633 1088 la w0 2 ; quantum(proc) := quantum(proc) extract slice; 1634 1090 rs w0 x2-a16+a35; 1635 1092 ws w1 0 ; 1636 1094 al w0 0 ; 1637 1096 aa w1 x2-a16+a36+2; add the remaining part of quantum to 1638 1098 ds w1 x2-a16+a36+2; runtime(proc); 1639 1100 1639 1100 ; at this point there is at least one process in the timer queue, 1640 1100 ; i.e. either the dummy process or a 'better' process 1641 1100 ; the following is intended for skipping quickly the dummy process: 1642 1100 rl w1 b2+2 ; worse := rear of timer queue; (normally dummy process); 1643 1102 sl w3 (x1-a16+a301); if priority >= priority(worse) then 1644 1104 jl i5 ; goto found; (only in case of inserting dummy process) 1645 1106 1645 1106 al w3 x3+1 ; (code facility) 1646 1108 i4: rl w1 x1+2 ; next: worse:=last(worse); 1647 1110 sn w1 b2 ; if worse<>timer q head and 1648 1112 jl i5 ; 1649 1114 sh w3 (x1-a16+a301) ; priority(worse)>priority then 1650 1116 jl i4 ; goto next; 1651 1118 1651 1118 ; notice: the loop went one step to far . . .; 1652 1118 i5: rl w1 x1 ; now w1 has been repaired; 1653 1120 jl i2 ; goto insert proc; 1654 1122 e. 1655 1122 \f 1655 1122 1655 1122 ; to facilitate the error recovery the interrupt stack and the 1656 1122 ; stationary pointers of the monitor table are placed at fixed 1657 1122 ; addresses. 1658 1122 1658 1122 b128=1200, 0,r.(:b128-k+2:)>1-6 1659 1188 a130 ; date of options 1660 1190 a131 ; time of options 1661 1192 0, r.4 ; room for machine id. 1662 1200 1662 1200 m. 1662 1200 copies of some mon table entries, int stack, mon reg dump (24, 32, 26 hw) 1663 1200 1663 1200 ; copy of some monitor pointers: 1664 1200 1664 1200 0-0-0 ; b3: 72: name table start 1665 1202 0-0-0 ; b4: 74: first device in name table 1666 1204 0-0-0 ; b5: 76: first area in name table 1667 1206 0-0-0 ; b6: 78: first internal in name table 1668 1208 0-0-0 ; b7: 80: name table end 1669 1210 0-0-0 ; b8+4: 86: first byte of mess buf pool area 1670 1212 0-0-0 ; b8+6: 88: last byte of mess buf pool area 1671 1214 0-0-0 ; b22: 92: first drum chain in name table 1672 1216 0-0-0 ; b23: 94: first disc chain in name table 1673 1218 0-0-0 ; b24: 96: chain end in name table 1674 1220 b50 ; start of interrupt stack 1675 1222 0-0-0 ; b86: driver proc save area 1676 1224 1676 1224 ; definition of interrupt stack: 1677 1224 1677 1224 b50: 0 ; end of stack 1678 1226 b49=k-1 ; terminating stack-address 1679 1226 1679 1226 ; power fail element: 1680 1226 0 ; (irrellevant regdump) 1681 1228 0 ; (exception disabled) 1682 1230 0 ; (escape disabled) 1683 1232 0 ; (monitor call not permitted in monitor) 1684 1234 c8 ; external interrupt, second level 1685 1236 1 < 23 + 0 ; monitor mode + totally disabled 1686 1238 1686 1238 ; monitor element: 1687 1238 b52 ; monitor regdump 1688 1240 0 ; monitor exception routine 1689 1242 0 ; monitor escape routine 1690 1244 c0 ; monitor call entry 1691 1246 c1 ; external interrupt entry, first level 1692 1248 1 < 23 + 6 ; monitor mode + disable all but power/bus error 1693 1250 1693 1250 ; user element: 1694 1250 0-0-0 ; user regdump (initialized by select internal) 1695 1252 0-0-0 ; user exception ( - - - - ) 1696 1254 0-0-0 ; user escape ( - - - - ) 1697 1256 1697 1256 ; monitor regdump area 1698 1256 ; 1699 1256 ; used when initializing the whole system, 1700 1256 ; and to hold the working registers etc. in case of 1701 1256 ; powerfailure or buserror during monitor code 1702 1256 1702 1256 b52: 0 ; w0 = 0 (irrellevant) 1703 1258 0 ; w1 = 0 (irrellevant) 1704 1260 0 ; w2 = 0 (irrellevant) 1705 1262 0 ; w3 = 0 (irrellevant) 1706 1264 1 < 23 ; status = monitor mode 1707 1266 c99 ; ic = interrupt return 1708 1268 0 ; cause = 0 (irrellvant) 1709 1270 0 ; sb = 0 (irrellvant) 1710 1272 1710 1272 0 ; cpa = 0 (irrellevant) 1711 1274 0 ; base = 0 (irrellevant) 1712 1276 8 ; lower write limit 1713 1278 8.3777 7777 ; upper write limit = all possible core 1714 1280 0 < 12 + 6 ; interrupt limits 1715 1282 \f 1715 1282 1715 1282 1715 1282 1715 1282 ; comment: the following utility procedures are used by external 1716 1282 ; processes during input/output; 1717 1282 1717 1282 ; procedure deliver result(result) 1718 1282 ; comment: moves the general input/output answer to the beginning of the driver process. 1719 1282 ; (the last 3 words of the message buffer are copied too, so they will remain unchanged). 1720 1282 ; the answer is send with the specified result to the sender of the buffer. 1721 1282 ; 1722 1282 ; call: w0 = result, w3 = link, b18 = buffer 1723 1282 ; exit: w0 = undef, w1 = proc (= b19), w2 = undef, w3= unchanged 1724 1282 ; return address: link: answer delivered 1725 1282 ; (internal 3 if buf not claimed and claims exceeded) 1726 1282 1726 1282 b. i10 w. 1727 1282 g3: am 5-4 ; result 5: 1728 1284 g4: am 4-3 ; result 4: 1729 1286 g5: am 3-2 ; result 3: 1730 1288 g6: am 2-1 ; result 2: 1731 1290 g7: al w0 1 ; result 1: w0 := result; 1732 1292 rl w3 b20 ; return := wait-next action in driver process; 1733 1294 jl g19 ; goto deliver result; 1734 1296 g18: al w0 1 ; result 1: w0 := result; 1735 1298 1735 1298 g19: ; deliver result: 1736 1298 jd k+2 ; disable; 1737 1300 ds w0 i3 ; save(link, result); 1738 1302 1738 1302 rl w1 b1 ; 1739 1304 rl w2 b18 ; buf := current buffer; 1740 1306 ac w3 (x2+4) ; 1741 1308 sl w3 0 ; if receiver(buf) > 0 then 1742 1310 jl i0 ; begin comment: buf not claimed, see link operation; 1743 1312 bz w0 x1+a19 ; if bufclaim(cur) <> 0 then 1744 1314 sn w0 0 ; begin 1745 1316 jl i0 ; decrease(bufclaim(cur)); 1746 1318 bs. w0 1 ; receiver(buf) := -receiver(buf); 1747 1320 hs w0 x1+a19 ; end; (i.e. claims exceeded will provoke a break below); 1748 1322 rs w3 x2+4 ; end; 1749 1324 i0: rl w0 x1+a182 ; 1750 1326 rl w1 x1+a302 ; 1751 1328 wa w1 0 ; get physical address of save area 1752 1330 dl w0 x2+a151 ; save first four words of mess. 1753 1332 ds w0 g29 ; (used by errorlog ) 1754 1334 dl w0 x2+a153 ; 1755 1336 ds w0 g30 ; 1756 1338 1756 1338 dl w0 x2+22 ; move last 3 words from buf 1757 1340 ds w0 x1+14 ; to area; 1758 1342 rl w0 x2+18 ; (to retain compatibility with old conventions) 1759 1344 rl w3 g24 ; 1760 1346 ds w0 x1+10 ; move the 5 std answer words 1761 1348 dl w0 g23 ; to area; 1762 1350 ds w0 x1+6 ; 1763 1352 dl w0 g21 ; 1764 1354 ds w0 x1+2 ; (you are disabled, so do not worry about timeslicing...); 1765 1356 1765 1356 dl w0 i3 ; restore (link, result); 1766 1358 am (b1) ; 1767 1360 rl w1 +a302 ; get logical address of save area 1768 1362 jd 1<11+22; send answer(result, area, buf); 1769 1364 1769 1364 rl w1 b19 ; w1 := current receiver; 1770 1366 rl w2 x1 ; if kind of receiver=subprocess then 1771 1368 se w2 84 ; check status 1772 1370 sn w2 85 ; else return 1773 1372 jl. i1. ; 1774 1374 jd x3 ; 1775 1376 1775 1376 i1: rl w2 g20 ; if one or more of statusbits 1,2,4,9,10,11 1776 1378 se. w1 (b32.) ; or if receiver = special watched receiver 1777 1380 sz. w2 (i5.) ; then 1778 1382 jl w2 (b31) ; call errorlog 1779 1384 jd x3 ; restore link and return 1780 1386 1780 1386 i2: 0 ; saved link 1781 1388 i3: 0 ; saved result 1782 1390 b32: 0 ; proc adr for special watched receiver 1783 1392 m. 1783 1392 statusmask for errorlog 1784 1392 i5: 8.36070000 ; status mask: bit 1 2 3 4 9 10 11 1785 1394 1785 1394 ; procedure link operation (buf) 1786 1394 ; comment: links a message to the receiver and returns to the receiver, in case it is the only 1787 1394 ; message in the queue (and interrupt address is even). 1788 1394 ; otherwise it returns to the wait-next action in the driver process. 1789 1394 ; 1790 1394 ; call: w2 = buf, w3 = link 1791 1394 ; exit: w0 = operation, w1 = proc, w2 = unchanged, w3 = unchanged 1792 1394 ; return address: link: single in queue 1793 1394 ; (b20): others in queue 1794 1394 ; (b20): interrupt addr odd (i.e. driver busy) 1795 1394 1795 1394 g17: jd k+2 ; link operation: 1796 1396 rs w3 i3 ; save return; 1797 1398 ac w3 (x2+4) ; 1798 1400 sh w3 0 ; if receiver(buf) < 0 then 1799 1402 jl i4 ; begin comment: buf claimed. now release claim; 1800 1404 rs w3 x2+4 ; receiver(buf) := -receiver(buf); i.e. positive; 1801 1406 rl w1 b1 ; 1802 1408 bz w3 x1+a19 ; increase(buf claim(cur)); 1803 1410 al w3 x3+1 ; 1804 1412 hs w3 x1+a19 ; end; 1805 1414 1805 1414 i4: am (b19) ; 1806 1416 al w1 +a54 ; 1807 1418 jl w3 d6 ; link(mess q(proc), buf); 1808 1420 se w3 x1 ; if old last <> mess q(proc) then 1809 1422 c33: jl (b20) ; goto wait next(driver process); 1810 1424 1810 1424 al w1 x1-a54 ; w1 := proc; 1811 1426 rl w0 x1+a56 ; w0 := interrupt addr(proc); 1812 1428 so w0 2.1 ; if interrupt addr(proc) is odd then 1813 1430 jl w3 g64 ;+2 goto wait next(driver process); 1814 1432 jl (b20) ;+2 examine queue: empty => goto wait next; 1815 1434 jl (i3) ; return 1816 1436 1816 1436 e. 1817 1436 1817 1436 1817 1436 ; procedure check user 1818 1436 ; comment: checks whether an external process is used 1819 1436 ; by the current internal process. if the external is reserved 1820 1436 ; it is also checked whether it is reserved by the current 1821 1436 ; internal process. 1822 1436 ; call: return: 1823 1436 ; w0 destroyed 1824 1436 ; w1 cur cur 1825 1436 ; w2 buf buf 1826 1436 ; w3 link link 1827 1436 1827 1436 b.i24 ; begin 1828 1436 w.g14:am (b19) ; 1829 1438 rl w0 a52 ; 1830 1440 sn w1 (b1) ; if cur = sender then 1831 1442 jl x3 ; return ok; 1832 1444 se w0 0 ; mask:=if reserved(proc)<>0 1833 1446 jl i0 ; then reserved(proc) 1834 1448 am (b19) ; else user(proc); 1835 1450 rl w0 a53 ; bit:=identification(cur); 1836 1452 i0: so w0 (x1+a14) ; if mask(bit)=0 1837 1454 jl g6 ; then goto result 2; 1838 1456 jl x3+0 ; 1839 1458 e. ; end 1840 1458 1840 1458 ; procedure check reservation 1841 1458 ; comment: checks whether an external process is reserved 1842 1458 ; by the current internal process. 1843 1458 ; call: return: 1844 1458 ; w0 reserved 1845 1458 ; w1 cur cur 1846 1458 ; w2 buf buf 1847 1458 ; w3 link link 1848 1458 1848 1458 b.i24 ; begin 1849 1458 w.g15:am (b19) ; 1850 1460 rl w0 a52 ; mask:=reserved(proc); 1851 1462 sn w1 (b1) ; if sender = cur then 1852 1464 jl x3 ; return ok; 1853 1466 so w0 (x1+a14) ; bit:=identification(cur); 1854 1468 jl g6 ; if mask(bit)=0 1855 1470 jl x3+0 ; then goto result 2; 1856 1472 e. ; end 1857 1472 1857 1472 ; procedure check operation(oper mask, mode mask) 1858 1472 ; comment: checks whether the operation and mode are 1859 1472 ; within the repertoire of the receiver. the legal values are 1860 1472 ; defined by two bitpatterns in which bit i=1 indicates 1861 1472 ; that operation (or mode) number i is allowed. if the 1862 1472 ; operation is odd, it is checked whether the input/output 1863 1472 ; area is within the internal process. 1864 1472 ; call: return: 1865 1472 ; w0 oper mask destroyed 1866 1472 ; w1 mode mask destroyed 1867 1472 ; w2 buf buf 1868 1472 ; w3 link destroyed 1869 1472 1869 1472 b.i24 ; begin 1870 1472 w.g16:rs w3 i0 ; 1871 1474 bz w3 x2+9 ; 1872 1476 ls w1 x3+0 ; 1873 1478 bz w3 x2+8 ; 1874 1480 ls w0 x3+0 ; 1875 1482 sh w0 -1 ; if mode mask(mode(buf))=0 1876 1484 sl w1 0 ; or oper mask (operation(buf))=0 1877 1486 jl g5 ; then goto result 3; 1878 1488 so w3 1 ; 1879 1490 jl (i0) ; 1880 1492 rl w1 x2+6 ; 1881 1494 dl w0 x2+12 ; if odd(operation(buf)) 1882 1496 la w3 g50 ; make first and 1883 1498 la w0 g50 ; last address in buf even; 1884 1500 sl w3 (x1+a17) ; and (first addr(buf)<first addr(sender) 1885 1502 sl w0 (x1+a18) ; or last addr(buf)>=top addr(sender) 1886 1504 jl g5 ; 1887 1506 sh w0 x3-2 ; or first addr(buf)>last addr(buf)) 1888 1508 jl g5 ; then goto result 3; 1889 1510 ds w0 x2+12 ; message even; 1890 1512 jl (i0) ; 1891 1514 i0: 0 ; 1892 1516 e. ; end 1893 1516 1893 1516 ; input/output answer: 1894 1516 w.g20: 0 ; status 1895 1518 g21: 0 ; bytes 1896 1520 g22: 0 ; characters 1897 1522 g23: 0 ; file count 1898 1524 g24: 0 ; block count 1899 1526 1899 1526 g40: 0 ; word5 1900 1528 g41: 0 ; word6 1901 1530 g42: 0 ; word7 1902 1532 0 ; mess(1) operation 1903 1534 g29: 0 ; mess(2) first 1904 1536 0 ; mess(3) last 1905 1538 g30: 0 ; mess(4) segment no 1906 1540 1906 1540 1906 1540 ; procedure next operation 1907 1540 ; comment: examines the message queue of the receiver and 1908 1540 ; returns to the receiver if there is a message from a 1909 1540 ; not-stopped sender. otherwise it returns to the current 1910 1540 ; internal process. 1911 1540 ; call: return: 1912 1540 ; w0 oper 1913 1540 ; w1 proc 1914 1540 ; w2 buf 1915 1540 ; w3 link sender 1916 1540 1916 1540 b.i24 ; begin 1917 1540 w.g25:rs w3 i2 ; 1918 1542 jl w3 g64 ; examine queue( 1919 1544 jl c33 ; dummy interrupt); 1920 1546 jl (i2) ; 1921 1548 i2: 0 ; 1922 1550 e. ; end 1923 1550 1923 1550 ; procedure examine queue(queue empty) 1924 1550 ; call: return: 1925 1550 ; w0 operation 1926 1550 ; w1 proc 1927 1550 ; w2 buf 1928 1550 ; w3 link sender 1929 1550 1929 1550 b.i24 ; begin 1930 1550 w.g64:rs w3 i2 ; 1931 1552 i0: rl w1 b19 ; exam q:proc:=current receiver; 1932 1554 rl w2 x1+a54 ; buf:=next(mess q(proc)); 1933 1556 sn w2 x1+a54 ; if buf=mess q(proc) 1934 1558 jl (i2) ; then goto queue empty; 1935 1560 rs w2 b18 ; 1936 1562 rl w3 x2+6 ; internal:=sender(buf); 1937 1564 xl x2+8 ; 1938 1566 sh w3 -1 ; 1939 1568 ac w3 x3+0 ; 1940 1570 bz w0 x3+a13 ; 1941 1572 rl w3 x2+6 ; if state(internal)=stopped 1942 1574 sx 2.1 ; and operation(buf)(23)=1 1943 1576 so w0 a105 ; or internal<0 1944 1578 sh w3 -1 ; then 1945 1580 jl i1 ; begin 1946 1582 bz w0 x2+8 ; 1947 1584 am (i2) ; no operation; 1948 1586 jl 2 ; goto exam q; 1949 1588 i1: jl w3 g26 ; end; 1950 1590 jl i0 ; oper:=byte(buf+8); 1951 1592 i2: 0 ; 1952 1594 e. ; end 1953 1594 1953 1594 ; procedure no operation 1954 1594 ; call: return: 1955 1594 ; w0 destroyed 1956 1594 ; w1 proc 1957 1594 ; w2 destroyed 1958 1594 ; w3 link destroyed 1959 1594 1959 1594 b.i24 ; begin 1960 1594 w.g26:al w0 1 ; 1961 1596 g27:al w1 0 ; 1962 1598 rs w1 g20 ; status:= 1963 1600 g28:rs w1 g21 ; bytes:= 1964 1602 rs w1 g22 ; character:=0; 1965 1604 jl g19 ; deliver result(1); 1966 1606 e. ; end 1967 1606 1967 1606 ; procedure increase stop count 1968 1606 ; comment: increases the stop count of the sender by 1. 1969 1606 ; call: return: 1970 1606 ; w0 unchanged 1971 1606 ; w1 unchanged 1972 1606 ; w2 buf buf 1973 1606 ; w3 link destroyed 1974 1606 1974 1606 b.i24 ; begin 1975 1606 w.g31:rs w3 i0 ; 1976 1608 am (x2+6) ; 1977 1610 bz w3 a12 ; 1978 1612 al w3 x3+1 ; stop count(sender(buf)):= 1979 1614 am (x2+6) ; stop count(sender(buf))+1; 1980 1616 hs w3 a12 ; 1981 1618 jl (i0) ; 1982 1620 i0: 0 ; 1983 1622 e. ; end 1984 1622 1984 1622 ; procedure decrease stop count 1985 1622 ; comment: the stop count of the sender is decreased by 1 1986 1622 ; if the operation is odd. if stop count becomes zero and the 1987 1622 ; sender is waiting to be stopped, the sender is stopped 1988 1622 ; and the stop count of its parent is decreased by 1. 1989 1622 ; if the parent has stopped its child, an answer is sent to 1990 1622 ; the parent in the buffer defined by the wait address of 1991 1622 ; the child. 1992 1622 ; call: return: 1993 1622 ; w0 destroyed 1994 1622 ; w1 destroyed 1995 1622 ; w2 destroyed 1996 1622 ; w3 link destroyed 1997 1622 1997 1622 b.i24 ; begin 1998 1622 w.g32:rs w3 i3 ; 1999 1624 rl w2 b18 ; 2000 1626 bz w0 x2+8 ; 2001 1628 rl w3 x2+6 ; internal:=sender(buf); 2002 1630 sz w0 1 ; if odd(operation(buf)) 2003 1632 sh w3 -1 ; and internal>=0 then 2004 1634 jl (i3) ; begin 2005 1636 bz w0 x3+a12 ; 2006 1638 bs. w0 1 ; stop count(internal):= 2007 1640 hs w0 x3+a12 ; stop count(internal)-1; 2008 1642 i0: se w0 0 ; exam stop: 2009 1644 jl (i3) ; if stop count(internal)=0 2010 1646 bz w1 x3+a13 ; and state(internal)=wait stop 2011 1648 so w1 a105 ; then 2012 1650 jl (i3) ; begin 2013 1652 al w1 x1+a106 ; child state:= 2014 1654 hs w1 x3+a13 ; state(internal):=wait start; 2015 1656 rl w2 x3+a40 ; buf:=wait address(internal); 2016 1658 rl w3 x3+a34 ; internal:=parent(internal); 2017 1660 bz w0 x3+a12 ; 2018 1662 bs. w0 1 ; stop count(internal):= 2019 1664 hs w0 x3+a12 ; stop count(internal)-1; 2020 1666 se w1 a99 ; if child state<>wait start parent 2021 1668 jl i0 ; then goto exam stop; 2022 1670 2022 1670 ; let the current driver claim the buffer, so that 2023 1670 ; it may send the answer: 2024 1670 rl w1 b1 ; 2025 1672 ac w0 x1 ; receiver(buf) := -cur; (i.e. claimed) 2026 1674 rs w0 x2+4 ; 2027 1676 bz w3 x1+a19 ; decrease(bufclaim(cur)); 2028 1678 al w3 x3-1 ; (even if claims would be exceeded) 2029 1680 hs w3 x1+a19 ; 2030 1682 rl w1 x1+a17 ; answer area := first addr(cur); 2031 1684 al w0 1 ; result := 1; 2032 1686 jd 1<11+22; send answer; 2033 1688 jd (i3) ; return disabled; 2034 1690 i2: 0 ; 2035 1692 i3: 0 ; 2036 1694 e. ; end 2037 1694 2037 1694 ; procedure exam sender(sender stopped) 2038 1694 ; call: return: 2039 1694 ; w0 unchanged 2040 1694 ; w1 unchanged 2041 1694 ; w2 unchanged 2042 1694 ; w3 link link 2043 1694 2043 1694 b.i24 ; begin 2044 1694 w.g34:rs w3 i0 ; 2045 1696 am (b18) ; 2046 1698 rl w3 6 ; internal:=sender(buf); 2047 1700 sh w3 -1 ; 2048 1702 jl (i0) ; if internal<0 2049 1704 bz w3 x3+a13 ; 2050 1706 sz w3 a105 ; or state(internal)=stopped 2051 1708 jl (i0) ; then goto sender stopped; 2052 1710 rl w3 i0 ; 2053 1712 jl x3+2 ; 2054 1714 i0: 0 ; 2055 1716 e. ; end 2056 1716 2056 1716 ; procedure follow chain(no. of slices,chain table index, slice) 2057 1716 ; the return value is the chain table index of entry number <no. 2058 1716 ; of slices> in the chain starting at <chain table index> 2059 1716 ; call: return: 2060 1716 ; w0 n.o.s. destroyed 2061 1716 ; w1 unchanged 2062 1716 ; w2 c.t.i. slice 2063 1716 ; w3 link destroyed 2064 1716 2064 1716 b.i8 2065 1716 w.d74:rs w3 i3 ; save return 2066 1718 ac w3 (0) ; 2067 1720 as w3 1 ; count := -2 * no. of slices 2068 1722 jl. i2. ; goto test; repeat: 2069 1724 i0: sl w3 -30 ; if count >= -30 2070 1726 jl. x3+i1. ; then goto advance(-count) 2071 1728 ba w2 x2 ; 2072 1730 r. 16 ; 2073 1760 i1: al w3 x3+32 ; count := count + 32 2074 1762 i2: sh w3 -2 ; test: if count < 0 2075 1764 jl. i0. ; then goto repeat 2076 1766 jl (i3) ; return 2077 1768 i3: 0 ; 2078 1770 e. ; 2079 1770 2079 1770 ; bitpatterns: 2080 1770 2080 1770 g48: 3 ; constant 3 (= number of chars per word) 2081 1772 g50: 8.7777 7776 ; first 23 bits 2082 1774 g51: 8.7777 0000 ; first 12 bits 2083 1776 g52: 8.0000 7777 ; last 12 bits 2084 1778 g53: 8.0000 0377 ; last 8 bits 2085 1780 g49: 1<23 ; bit 0 2086 1782 g62: 1<18 ; bit 5 2087 1784 g65: 8.3777 7777 ; last 23 bits 2088 1786 g63: 1 ; bit 23 2089 1788 \f 2089 1788 2089 1788 m. 2089 1788 monprocs - monitor procedures 2090 1788 2090 1788 b.i30 w. 2091 1788 i0=82 02 23, i1=12 00 00 2092 1788 2092 1788 ; if newtime (i0,i1) > oldtime (a133,a134) then oldtime:=newtime; 2093 1788 c.i0-a133 2094 1788 c.i0-a133-1, a133=i0, a134=i1, z. 2095 1788 c.i1-a134-1, a134=i1, z. 2096 1788 z. 2097 1788 2097 1788 i10=i0, i20=i1 2098 1788 2098 1788 i15=i10/100000 , i10=i10-i15*100000 , i25=i20/100000 , i20=i20-i25*100000 2099 1788 i14=i10/10000 , i10=i10-i14*10000 , i24=i20/10000 , i20=i20-i24*10000 2100 1788 i13=i10/1000 , i10=i10-i13*1000 , i23=i20/1000 , i20=i20-i23*1000 2101 1788 i12=i10/100 , i10=i10-i12*100 , i22=i20/100 , i20=i20-i22*100 2102 1788 i11=i10/10 , i10=i10-i11*10 , i21=i20/10 , i20=i20-i21*10 2103 1788 2103 1788 i2: <: date :> 2104 1812 (:i15+48:)<16+(:i14+48:)<8+46 2105 1814 (:i13+48:)<16+(:i12+48:)<8+46 2106 1816 (:i11+48:)<16+(:i10+48:)<8+32 2107 1818 2107 1818 (:i25+48:)<16+(:i24+48:)<8+46 2108 1820 (:i23+48:)<16+(:i22+48:)<8+46 2109 1822 (:i21+48:)<16+(:i20+48:)<8+ 0 2110 1824 2110 1824 i3: al. w0 i2. ; write date: 2111 1826 rs w0 x2+0 ; first free:=start(text); 2112 1828 al w2 0 ; 2113 1830 jl x3 ; return to slang(status ok); 2114 1832 2114 1832 jl. i3. ; 2115 1834 e. 2116 1834 j. 2116 1788 date 82.02.23 12.00.00 2117 1788 \f 2117 1788 2117 1788 ; list of monitor procedures: 2118 1788 b16: ; start: 2119 1788 2119 1788 e0 ; 0 : set interrupt 2120 1790 e1 ; 2 : reset, priv 2121 1792 e2 ; 4 : process description 2122 1794 e3 ; 6 : initialise process 2123 1796 e4 ; 8 : reserve process 2124 1798 e5 ; 10 : release process 2125 1800 e6 ; 12 : include user 2126 1802 e7 ; 14 : exclude user 2127 1804 e8 ; 16 : send message 2128 1806 e9 ; 18 : wait answer 2129 1808 e10 ; 20 : wait message 2130 1810 e11 ; 22 : send answer 2131 1812 e12 ; 24 : wait event 2132 1814 e13 ; 26 : get event 2133 1816 c99 ; 28 : (type w0, not icluded in rc8000) 2134 1818 c99 ; 30 : (type w1, not icluded in rc8000) 2135 1820 c99 ; 32 : (type w2, not icluded in rc8000) 2136 1822 c99 ; 34 : (type w3, not icluded in rc8000) 2137 1824 e18 ; 36 : get clock 2138 1826 e19 ; 38 : set clock 2139 1828 e20 ; 40 : create entry 2140 1830 e21 ; 42 : lookup entry 2141 1832 e22 ; 44 : change entry 2142 1834 e23 ; 46 : rename entry 2143 1836 e24 ; 48 : remove entry 2144 1838 e25 ; 50 : permanent entry 2145 1840 e26 ; 52 : create area process 2146 1842 e27 ; 54 : create peripheral process 2147 1844 e28 ; 56 : create internal process 2148 1846 e29 ; 58 : start internal process 2149 1848 e30 ; 60 : stop internal process 2150 1850 e31 ; 62 : modify internal process 2151 1852 e32 ; 64 : remove process 2152 1854 e33 ; 66 : test event 2153 1856 e34 ; 68 : generate name 2154 1858 e35 ; 70 : copy 2155 1860 e36 ; 72 : set catalog base 2156 1862 e37 ; 74 : set entry base 2157 1864 e38 ; 76 : lookup head and tail 2158 1866 e39 ; 78 : set backing storage claims 2159 1868 e40 ; 80 : create pseudo process 2160 1870 e41 ; 82 : regret message 2161 1872 e42 ; 84 : general copy 2162 1874 e43 ; 86 : lookup aux entry 2163 1876 e44 ; 88 : clear statistics in entry 2164 1878 e45 ; 90 : permanent entry in aux catalog 2165 1880 e46 ; 92 : create entry lock process 2166 1882 e47 ; 94 : set priority 2167 1884 e48 ; 96 : relocate process 2168 1886 e49 ; 98 : set address base 2169 1888 e50 ; 100 : start io 2170 1890 e51 ; 102 : prepare backing storage 2171 1892 e52 ; 104 : insert entry 2172 1894 e53 ; 106 : insert backing storage 2173 1896 e54 ; 108 : delete backing storage 2174 1898 e55 ; 110 : delete entries 2175 1900 e56 ; 112 : connect main catalog 2176 1902 e57 ; 114 : remove main catalog 2177 1904 e58 ; 116 :set process extensions 2178 1906 c29 ; 118 : not used 2179 1908 e60 ; 120 : create aux entry and area process 2180 1910 e61 ; 122 : remove aux entry 2181 1912 e62 ; 124 : send pseudo message 2182 1914 e63 ; 126 : set cpa 2183 1916 2183 1916 b17=k-b16 ; max monitor call number 2184 1916 2184 1916 2184 1916 2184 1916 b. i20 w. 2185 1916 2185 1916 i0: 0 ; saved w0 2186 1918 i1: 0 ; saved w1 2187 1920 i2: 0 ; saved w2 2188 1922 i3: 0 ; saved w3 2189 1924 i8: 0 ; internal 2190 1926 2190 1926 2190 1926 ; procedure deliver answer; 2191 1926 ; comment: delivers an answer from a receiver to a sender. if the sender is waiting for the 2192 1926 ; answer, it will be started. if the message is regretted (or sender removed), the 2193 1926 ; buffer is returned to the mess buf pool. 2194 1926 ; call: w2=buf, w3=link 2195 1926 ; exit: w0, w1=unchanged, w2, w3=undef 2196 1926 ; return address: link 2197 1926 2197 1926 d15: ds. w1 i1. ; save registers; 2198 1928 rs. w3 i3. ; 2199 1930 2199 1930 i9: dl w1 x2+6 ; internal:=sender(buf); (w0 := receiver(buf)) 2200 1932 sh w1 -1 ; if internal<0 then 2201 1934 jl. i12. ; goto regretted; 2202 1936 2202 1936 rl w3 x1+a10 ; 2203 1938 sn w3 64 ; if kind(sender)=pseudo process then 2204 1940 rl w1 x1+a50 ; internal:=mainproc(sender); 2205 1942 sz w3 -1-64 ; if kind(sender) is neither internal nor pseudo process then 2206 1944 rl w1 x1+a250 ; internal:=driverproc(sender); 2207 1946 rs. w1 i8. ; save(internal); 2208 1948 2208 1948 bz w3 x1+a13 ; w3:=state(internal); 2209 1950 sn w3 a103 ; if state<>wait answer or 2210 1952 se w2 (x1+a30) ; save w2(internal)<>buf then 2211 1954 jl. i13. ; goto event; 2212 1956 2212 1956 rs w0 x1+a28 ; save w0(internal) := result := receiver(buf); 2213 1958 jl w3 d109 ; increase buf claim, remove release buf(internal, buf); 2214 1960 2214 1960 rl. w3 i8. ; restore(internal); 2215 1962 al w1 x2+8 ; from:=buf+8; 2216 1964 rl w2 x3+a29 ; answer:=save w1(internal); 2217 1966 wa w2 x3+a182 ; get physical address of answer area 2218 1968 jl w3 d14 ; move mess(from, answer); 2219 1970 i10: rl. w1 i8. ; 2220 1972 jl w3 d10 ; link internal(internal); 2221 1974 i11: dl. w1 i1. ; exit: restore(w0, w1); 2222 1976 jl. (i3.) ; return; 2223 1978 2223 1978 i12: al. w3 i11. ; regretted: remove release buf; 2224 1980 jl d106 ; goto exit; 2225 1982 2225 1982 i13: jl w3 d5 ; event: 2226 1984 al w1 x1+a15 ; remove(buf); 2227 1986 jl w3 d6 ; link(event q(internal), buf); 2228 1988 bz w0 x1-a15+a13; 2229 1990 se w0 a104 ; if state<>wait event then 2230 1992 jl. i11. ; goto exit; 2231 1994 al w0 1 ; result:=1; (i.e. answer); 2232 1996 rs w0 x1-a15+a28; save w0(internal) := result; 2233 1998 rs w2 x1-a15+a30; save w2(internal):=buf; 2234 2000 jl. i10. ; goto set result; 2235 2002 2235 2002 ; procedure deliver message; 2236 2002 ; comment: delivers the message to an internal process, and starts it if it is waiting for a message; 2237 2002 ; call: w2=buf, w3=link 2238 2002 ; exit: w0, w1=unchanged, w2, w3=undef 2239 2002 ; return address: link 2240 2002 2240 2002 d16: ds. w1 i1. ; save registers; 2241 2004 ds. w3 i3. ; 2242 2006 rl w1 x2+4 ; internal:=receiver(buf); 2243 2008 rl w0 x1+a10 ; 2244 2010 sn w0 64 ; if kind(internal)=pseudo process then 2245 2012 rl w1 x1+a50 ; internal:=mainproc(internal); 2246 2014 sz w0 -1-64 ; if kind(internal) is neither internal process nor pseudo process then 2247 2016 rl w1 x1+a250 ; internal:=driverproc(internal); 2248 2018 sn w1 0 ; if internal not defined then 2249 2020 jl. i16. ; goto unknown; 2250 2022 rs. w1 i8. ; save(internal); 2251 2024 2251 2024 bz w0 x1+a13 ; w0:=state(internal); 2252 2026 se w0 a102 ; if state<>wait message then 2253 2028 jl. i15. ; goto event; 2254 2030 2254 2030 rl w2 x2+6 ; 2255 2032 rs w2 x1+a28 ; save w0(internal):=sender(buf); 2256 2034 rl w3 x1+a31 ; name:=save w3(internal); 2257 2036 wa w3 x1+a182 ; get phys. addr. 2258 2038 dl w1 x2+a11+2 ; move 4 words process name; 2259 2040 ds w1 x3+2 ; 2260 2042 dl w1 x2+a11+6 ; 2261 2044 ds w1 x3+6 ; 2262 2046 2262 2046 rl. w1 i8. ; 2263 2048 rl w2 x1+a29 ; mess := save w1(internal); 2264 2050 wa w2 x1+a182 ; get phys. addr. 2265 2052 rl. w1 i2. ; restore(buf); 2266 2054 al w1 x1+8 ; 2267 2056 jl w3 d14 ; move mess(buf+8, mess); 2268 2058 2268 2058 i14: rl. w1 i8. ; start driver: 2269 2060 jl w3 d10 ; link internal(internal); 2270 2062 rl. w1 i8. ; 2271 2064 rl. w2 i2. ; 2272 2066 jl w3 d108 ; claim buffer (internal, buf); notice: error exit if exceeded 2273 2068 rs w2 x1+a30 ; save w2(internal) := buf; 2274 2070 dl. w1 i1. ; restore(w0, w1); 2275 2072 jl. (i3.) ; return; 2276 2074 2276 2074 i15: al w1 x1+a15 ; event: 2277 2076 jl w3 d6 ; link(event q(internal), buf); 2278 2078 se w0 a104 ; if state<>wait event then 2279 2080 jl. i11. ; goto exit; 2280 2082 al w0 0 ; result:=0; (i.e. message); 2281 2084 rs w0 x1-a15+a28; save w0(internal) := result; 2282 2086 jl. i14. ; goto start driver; 2283 2088 2283 2088 i16: al w0 5 ; unknown: 2284 2090 rs w0 x2+4 ; receiver(buf) := 5; i.e. result := 5; 2285 2092 jl. i9. ; goto deliver answer; 2286 2094 2286 2094 ; procedure deliver general event 2287 2094 ; 2288 2094 ; comment: when a process issues one of the following monitor calls: 2289 2094 ; a. initialize process (switch = 0) 2290 2094 ; b. reserve process (switch = 2) 2291 2094 ; c. release process (switch = 4) 2292 2094 ; concerning an external process, this procedure is called. 2293 2094 ; the sender is stopped, and the process description is linked to the eventqueue 2294 2094 ; of the driver process. 2295 2094 ; 2296 2094 ; the driver process must call ...wait event... in order to get the request. 2297 2094 ; as soon as the driver process reaches a process description in the eventqueue, 2298 2094 ; the process description will be removed from the eventqueue, and a message buffer 2299 2094 ; (taken from the driver process) will be initialized with: 2300 2094 ; 2301 2094 ; links = out of queue 2302 2094 ; receiver = - external process descr. addr. (odd) 2303 2094 ; sender = senders - - - 2304 2094 ; operation= switch 2305 2094 ; 2306 2094 ; this message buffer is given to the driver process. 2307 2094 ; 2308 2094 ; the driver process should now pay attention to the request and (sooner or later) 2309 2094 ; answer the sender (and thereby restart it) by calling the monitor procedure 2310 2094 ; ...send answer..., and return to another call of wait event. 2311 2094 ; 2312 2094 ; --- 2313 2094 ; 2314 2094 ; this is the normal way it should work, but there are - of course - some exceptions 2315 2094 ; to the rule. the sender may be stopped and started - or even worse: it may have 2316 2094 ; its instruction counter modified (i.e. parent break) before it is started. 2317 2094 ; 2318 2094 ; the special cases are: 2319 2094 ; a. the sender is stopped while the process description is still in the event- 2320 2094 ; queue of the driver process (i.e. not remarked by the driver). 2321 2094 ; b. the sender is stopped after the driver process has started processing the 2322 2094 ; request, but before the driver has answered the sender. 2323 2094 ; c. the sender is answered after case b. 2324 2094 ; d. the sender is started by its parent, after case b. 2325 2094 ; e. the sender is modified (or removed) by its parent, after case b. 2326 2094 ; 2327 2094 ; ad a. the instruction counter of the sender may be decreased by 2 (i.e. the call 2328 2094 ; will be repeated later) because the driver has not started processing of 2329 2094 ; the request yet. 2330 2094 ; ad b. the driver process has started processing of the request, i.e. the call may not 2331 2094 ; be repeated as in case a. 2332 2094 ; the sender must be left in a special state, so that a following ...start 2333 2094 ; internal... , ...modify internal... or ...remove internal... will take 2334 2094 ; special actions. 2335 2094 ; ad c. the driver process has now terminated the request, but the sender is stopped by 2336 2094 ; its parent. 2337 2094 ; the state of the sender should just be changed to the usual ...waiting for start... . 2338 2094 ; ad d. the sender may not be started yet, because the driver process has not termi- 2339 2094 ; nated the request-handling. just leave the sender-state as it was before it 2340 2094 ; was stopped (i.e. as before case b.). 2341 2094 ; ad e. the parent of the sender must have rights to force the sender to proceed. 2342 2094 ; since the driver process still presumes that the sender is stopped, the 2343 2094 ; change is signalled by regretting the message buffer that contains informa- 2344 2094 ; tion of the old request. 2345 2094 ; (i.e. the driver process need not be aware of the state of the sender, 2346 2094 ; because the call ...send answer... is completely blind, if the buffer is 2347 2094 ; regretted). 2348 2094 ; 2349 2094 ; 2350 2094 ; call: w0 = switch, w1 = sender, w2 = proc 2351 2094 ; exit address: c99 (interrupt return) 2352 2094 2352 2094 d100:ls w0 -1 ; wait address(sender) := 2353 2096 wa w0 4 ; switch shift (-1) 2354 2098 wa w0 4 ; + 2 * proc; 2355 2100 rs w0 x1+a40 ; (only nescessary in case driver is busy) 2356 2102 rl w3 x2+a10 ; driver := proc; 2357 2104 sn w3 64 ; if receiver is pseudo process then 2358 2106 rl w2 x2+a50 ; driver := main proc(receiver); 2359 2108 sz w3 -1-64 ; if receiver is neither internal nor pseudo process then 2360 2110 rl w2 x2+a250 ; driver := driver process(receiver); 2361 2112 ; evt teste at w2 eksisterer 2362 2112 ds. w2 i2. ; save(sender, driver); 2363 2114 al w0 a101 ; 2364 2116 jl w3 d9 ; remove internal(sender, waiting for procfunc); 2365 2118 2365 2118 rl. w1 i2. ; w1 := driver; 2366 2120 rl. w2 i1. ; w2 := timequeuelink(sender); 2367 2122 al w2 x2+a16 ; 2368 2124 2368 2124 bz w0 x1+a13 ; 2369 2126 sn w0 a104 ; if state(driver) <> waiting for event then 2370 2128 jl. i17. ; begin 2371 2130 2371 2130 al w1 x1+a15 ; link(eventq(driver), sender descr); 2372 2132 al w3 c99 ; goto interrupt return; 2373 2134 jl d6 ; end; 2374 2136 d120: ; take general event: 2375 2136 i17: rs. w1 i8. ; save (driver); 2376 2138 bz w3 x1+a19 ; if bufclaim(driver) = 0 then 2377 2140 sn w3 0 ; 2378 2142 jl. i14. ; goto start driver; 2379 2144 2379 2144 al w3 x3-1 ; decrease(bufclaim(driver)); 2380 2146 hs w3 x1+a19 ; 2381 2148 2381 2148 bz w3 x2-a16+a19; decrease(bufclaim(sender)); 2382 2150 al w3 x3-1 ; (it is just to facilitate regretting etc, 2383 2152 hs w3 x2-a16+a19; so don't care for claims exceeded) 2384 2154 2384 2154 al w0 1 ; make save ic (sender) odd; 2385 2156 lo w0 x2-a16+a33; i.e. signal that the request 2386 2158 rs w0 x2-a16+a33; is being processed; 2387 2160 2387 2160 al w0 2.11 ; unpack switch: 2388 2162 la w0 x2-a16+a40; switch := wait addr(sender) extract 2 shift 1; 2389 2164 ls w0 1 ; 2390 2166 2390 2166 al w3 x2-a16 ; w3 := sender; 2391 2168 2391 2168 rl w2 b8 ; buf := next(mess buf pool); 2392 2170 rs w0 x2+8 ; operation(buf) := switch; 2393 2172 al w0 4 ; 2394 2174 rs w0 x1+a28 ; save w0(driver) := 4; i.e. result = imm. message 2395 2176 2395 2176 ; unpack proc: 2396 2176 al w0 -1<2 ; proc := wait addr(sender) shift (-2) shift 1; 2397 2178 la w0 x3+a40 ; 2398 2180 ls w0 -1 ; 2399 2182 2399 2182 rx w3 0 ; sender(buf) := sender; 2400 2184 ac w3 x3+1 ; receiver(buf) := -proc-1; (i.e. odd, claimed) 2401 2186 ds w0 x2+6 ; (odd == immediate message) 2402 2188 2402 2188 jl w3 d5 ; remove(buf); 2403 2190 rs w2 x1+a30 ; save w2(driver) := buf; 2404 2192 al w3 c99 ; link internal(driver); 2405 2194 jl d10 ; goto interrupt return; 2406 2196 e. 2407 2196 c.(:a90>0 a.1:)-1 2408 2196 2408 2196 ; coredump. 2409 2196 ; only used in connection with power up. the dump is executed 2410 2196 ; using the fpa with io device number 2. 2411 2196 ; call: return: 2412 2196 ; w0 destroyed 2413 2196 ; w1 destroyed 2414 2196 ; w2 destroyed 2415 2196 ; w3 link destroyed 2416 2196 2416 2196 b. c10, d40, i50, r20 w. 2417 2196 2417 2196 d140: rs. w3 d32. ; coredump: 2418 2196 2418 2196 ; start of coredump: 2419 2196 ; change eventually contents of devicebase, unless already done. 2420 2196 2420 2196 i0: al. w0 d11. ; device base := local base; 2421 2196 rx w0 b65 ; 2422 2196 se w0 (b65) ; if device base <> old base then 2423 2196 rx. w0 d30. ; save(old device base); 2424 2196 sn w0 0 ; if saved old device base = 0 then 2425 2196 jl. i40. ; goto end coredump; 2426 2196 2426 2196 ; restart coredump: 2427 2196 ; the coredump starts from coreaddress zero 2428 2196 2428 2196 i10: al w1 -512 ; coreaddr := -512; 2429 2196 rs. w1 d21. ; 2430 2196 2430 2196 ; next coreblock: 2431 2196 2431 2196 i11: rl. w1 d21. ; addr := coreaddr + 512; 2432 2196 al w1 x1+512 ; 2433 2196 di w0 x1+8 ; if addr = top core then 2434 2196 sx 2.111 ; 2435 2196 al w1 -1 ; endblock := true 2436 2196 se w1 -1 ; else 2437 2196 rs. w1 d21. ; coreaddr := addr; 2438 2196 rs. w1 d22. ; 2439 2196 2439 2196 al w0 0 ; retries := 0; 2440 2196 rs. w0 d31. ; 2441 2196 2441 2196 ; send coreblock: 2442 2196 ; initialize transfer-variables 2443 2196 ; start the device and wait for interrupt 2444 2196 2444 2196 i15: al w0 0 ; 2445 2196 rs. w0 d13. ; interrupt := false; 2446 2196 rs. w0 d23. ; received command := illegal; 2447 2196 do. w0 (d10.) ; start device(irrell register); 2448 2196 rl. w1 d0. ; (get loopcount) 2449 2196 i16: ; 2450 2196 se. w0 (d13.) ; wait until interrupt 2451 2196 jl. i30. ; or timeout; 2452 2196 al w1 x1-1 ; 2453 2196 se w1 0 ; if interrupt then 2454 2196 jl. i16. ; goto after interrupt; 2455 2196 2455 2196 ; the transfer did not terminate within a certain time: 2456 2196 ; reset the device, and wait some time 2457 2196 2457 2196 i17: am. (d10.) ; 2458 2196 do w0 +2 ; reset device(irrell register); 2459 2196 ; sx 2.010 ; if disconnected then 2460 2196 ; jl. i40. ; goto end coredump; 2461 2196 rl. w1 d1. ; (get loop count) 2462 2196 i18: ; 2463 2196 al w1 x1-1 ; wait some time; 2464 2196 se w1 0 ; 2465 2196 jl. i18. ; 2466 2196 2466 2196 ; prepare repeat of transfer: 2467 2196 ; increase retries 2468 2196 ; if too many then halt 2469 2196 ; goto send coreblock 2470 2196 2470 2196 i20: rl. w1 d31. ; 2471 2196 al w1 x1+1 ; increase(retries); 2472 2196 rs. w1 d31. ; 2473 2196 sh w1 100 ; if retries < max then 2474 2196 jl. i15. ; goto send coreblock; 2475 2196 2475 2196 jl -1 ; halt; 2476 2196 2476 2196 ; definition of dumpdevice: 2477 2196 2477 2196 r20 = 3 ; 3=fpa transmitter 2478 2196 2478 2196 ; definition of coredump startchar and commandchars: 2479 2196 2479 2196 r10 = 253 ; coredump block 2480 2196 2480 2196 r0 = 128 ; send next block 2481 2196 r1 = 2 ; start coredump 2482 2196 r2 = 12 ; end coredump (= reject from ncp) 2483 2196 r3 = 1 ; retransmit 2484 2196 2484 2196 ; timercounts: 2485 2196 2485 2196 d0: 100000 ; loopcount for transfer 2486 2196 d1: 100000 ; loopcount for reset 2487 2196 2487 2196 ; device address: 2488 2196 2488 2196 d10: 1<23 + r20 < 3 ; 2489 2196 2489 2196 ; device descriptor: 2490 2196 2490 2196 d11 = k - r20 < 3 ; device base for coredump 2491 2196 2491 2196 c0 ; channel program start 2492 2196 d12 ; standard status 2493 2196 d13 ; interrupt address 2494 2196 -1 ; interrupt data 2495 2196 2495 2196 ; status area: 2496 2196 2496 2196 d12 = 0 ; (not used) 2497 2196 2497 2196 ; interrupt word: 2498 2196 2498 2196 d13: 0 ; 0==false, else true 2499 2196 2499 2196 ; coredump channel program: 2500 2196 2500 2196 c0: 0<8 , 0 , 12 ; clear core(0:7) 2501 2196 d20: r10<16+3<8+1<7, d20, 1 ; send startchar (from left char in the command) 2502 2196 d21 = k+2, 3<8+1<7, 0 , 768 ; send coreblock 2503 2196 3<8 , d22, 2 ; send coreaddr (two leftmost chars) 2504 2196 1<8 , d23, 1 ; receive command char 2505 2196 15<8 ; stop 2506 2196 2506 2196 ; coreaddress: -1==endblock, else blockaddress 2507 2196 2507 2196 d22: 0 ; 2508 2196 2508 2196 ; command character 2509 2196 2509 2196 d23: 0 ; (received in leftmost char) 2510 2196 2510 2196 ; miscellaneous: 2511 2196 2511 2196 d30: 0 ; saved device base 2512 2196 d31: 0 ; retries 2513 2196 d32: 0 ; saved link 2514 2196 2514 2196 ; after interrupt: 2515 2196 ; don't care if the output was not actually made. 2516 2196 ; switch out, depending on received command-character. 2517 2196 2517 2196 i30: rl. w0 d23. ; 2518 2196 ls w0 -16 ; w0 := received command, rigth justified; 2519 2196 2519 2196 sn w0 r0 ; if command = next then 2520 2196 jl. i11. ; goto next coreblock; 2521 2196 sn w0 r1 ; if command = start coredump then 2522 2196 jl. i10. ; goto restart; 2523 2196 sn w0 r2 ; if command = end then 2524 2196 jl. i40. ; goto end coredump; 2525 2196 sn w0 r3 ; if command = retransmit then 2526 2196 jl. i15. ; goto send coreblock; 2527 2196 2527 2196 jl. i20. ; goto prepare repeat; 2528 2196 2528 2196 ; end of coredump: 2529 2196 ; restore device base: 2530 2196 2530 2196 i40: rl. w0 d30. ; 2531 2196 rs w0 b65 ; device base := old device base; 2532 2196 jl. (d32.) ; exit: return; 2533 2196 e. 2534 2196 z. 2535 2196 \f 2535 2196 2535 2196 2535 2196 ; procedure set interrupt(address, mask); 2536 2196 ; call: return: 2537 2196 ; save w0 mask unchanged 2538 2196 ; save w1 unchanged 2539 2196 ; save w2 unchanged 2540 2196 ; save w3 address unchanged 2541 2196 2541 2196 b. i2 w. 2542 2196 e0: rl w2 x1+a31 ; address:=save w3 (cur); 2543 2198 2543 2198 al w0 x2+a180 ; (w0 = top of regdump) 2544 2200 se w2 0 ; if address <> 0 then 2545 2202 jl w3 d112 ; check within(address, top regdump); 2546 2204 2546 2204 rl w3 x1+a27 ; 2547 2206 sn w3 (x1+a170) ; if old intaddr = old escape address then 2548 2208 rs w2 x1+a170 ; escape address := address; 2549 2210 2549 2210 rl w0 x1+a176 ; 2550 2212 se w0 0 ; if monitor function <> set interrupt address then 2551 2214 am a170-a27; escape address := address 2552 2216 rs w2 x1+a27 ; else intaddr := address; 2553 2218 2553 2218 se w0 0 ; 2554 2220 am 4 ; 2555 2222 dl. w3 i1. ; 2556 2224 la w2 x1+a28 ; mask := save w0(cur) extract relevant bits; 2557 2226 la w3 x1+a32 ; status := status(cur) remove the corresponding bits; 2558 2228 sn w0 0 ; 2559 2230 ls w2 -3 ; (if set intaddr then oldfashioned rc4000 style) 2560 2232 lo w2 6 ; status(cur) := status 'or' mask; 2561 2234 rs w2 x1+a32 ; 2562 2236 gg w3 b91 ; move: user exception address(cur) 2563 2238 dl w1 x1+a170 ; user escape address(cur) 2564 2240 ds w1 x3+a325+a328; to: previous interrupt stack element; 2565 2242 jl c99 ; goto interrupt return; 2566 2244 2566 2244 8.3000 0000 ; i1-2: extract aritmetic bits (nb: oldfashioned rc4000-way) 2567 2246 i1: 8.7477 7777 ; : remove - - 2568 2248 8.2477 0000 ; i1+2: extract escape bits 2569 2250 8.5300 7777 ; i1+4: remove - - 2570 2252 2570 2252 e. 2571 2252 2571 2252 ; procedure process description(name, result); 2572 2252 ; call: return: 2573 2252 ; save w0 result (=0, proc descr addr) 2574 2252 ; save w1 2575 2252 ; save w2 2576 2252 ; save w3 name 2577 2252 2577 2252 b. i0 w. 2578 2252 e2: jl w3 d101 ; check and search name 2579 2254 al. w3 i0. ;+2 not found: w3:=zero address 2580 2256 rl w0 x3 ; result := proc descr; 2581 2258 jl r28 ; goto return prepared result; 2582 2260 i0: 0 ; 2583 2262 e. 2584 2262 2584 2262 ; procedure initialize process(name, result); 2585 2262 ; - reserve - ( - , - ); 2586 2262 ; call: return: 2587 2262 ; save w0 result (=0, 1, 2, 3) 2588 2262 ; save w1 unchanged 2589 2262 ; save w2 unchanged 2590 2262 ; save w3 name unchanged 2591 2262 2591 2262 e3: am 0-2 ; initialize: 2592 2264 e4: al w0 2 ; reserve: prepare result, in case of internal proc; 2593 2266 jl w3 d101 ; check and search name; 2594 2268 jl r3 ;+2 not found: goto result 3; 2595 2270 rl w2 x3 ;+4 proc:=name table(entry) 2596 2272 rl w3 x2+a10 ; if kind(proc) neither internal process 2597 2274 sz w3 -1-64 ; nor pseudo process then 2598 2276 jl. d100. ; deliver general event (w0=switch, w1=cur, w2=proc) 2599 2278 ; and goto interrupt return; 2600 2278 jl r28 ; goto return prepared result; 2601 2280 2601 2280 ; procedure release process (name); 2602 2280 ; call: return: 2603 2280 ; save w0 unchanged 2604 2280 ; save w1 unchanged 2605 2280 ; save w2 unchanged 2606 2280 ; save w3 name unchanged 2607 2280 2607 2280 e5: jl w3 d101 ; check and search name; 2608 2282 jl c99 ;+2 not found: goto interrupt return; 2609 2284 rl w2 x3 ;+4 proc:=name table(entry); 2610 2286 al w0 4 ; switch:=4; 2611 2288 rl w3 x2+a10 ; if kind(proc) neither internal process 2612 2290 sz w3 -1-64 ; nor pseudo process then 2613 2292 jl. d100. ; deliver generel event (w0=switch, w1=cur, w2=proc) 2614 2294 ; and goto interrupt return; 2615 2294 jl c99 ; goto interrupt return; 2616 2296 2616 2296 ; procedure include user(name, device, result); 2617 2296 ; - exclude - ( - , - , - ); 2618 2296 ; call: return: 2619 2296 ; save w0 result (=0, 2, 3, 4) 2620 2296 ; save w1 device unchanged 2621 2296 ; save w2 unchanged 2622 2296 ; save w3 name unchanged 2623 2296 2623 2296 b. i0 w. 2624 2296 e6: am d126-d123; include: switch := insert user; 2625 2298 e7: al w0 d123 ; exclude: switch := remove user; 2626 2300 rs. w0 i0. ; save(switch); 2627 2302 jl w3 d101 ; check and search name; 2628 2304 jl r3 ;+2 not found: goto result3; 2629 2306 rl w2 x3 ;+4 child:=name table(entry); 2630 2308 rs w2 x1+a28 ; save w0(cur) := child; 2631 2310 rl w3 x2+a10 ; w3:=kind(child); 2632 2312 sn w3 0 ; if kind<>0 or 2633 2314 se w1 (x2+a34) ; cur<>parent(child) then 2634 2316 jl r3 ; goto result 3; 2635 2318 rl w3 x1+a29 ; device:=save w1(cur); 2636 2320 ls w3 1 ; 2637 2322 wa w3 b4 ; entry:=2*device+first device; 2638 2324 sl w3 (b4) ; if entry<first device or 2639 2326 sl w3 (b5) ; entry>=first area then 2640 2328 jl r4 ; goto result 4; 2641 2330 rl w2 x3 ; proc:=name table(entry); 2642 2332 jl w3 d102 ; check user(cur, proc); 2643 2334 jl r2 ;+2 not user: goto result 2; 2644 2336 2644 2336 rl w1 x1+a28 ; restore(child); 2645 2338 jl. w3 (i0.) ; insert/remove user(child, proc); 2646 2340 rl w1 b1 ; restore(cur); 2647 2342 jl r0 ; goto result 0; 2648 2344 i0: 0 ; saved switch 2649 2346 e. 2650 2346 2650 2346 ; procedure send pseudo message(pseudo proc, name, mess, buf); 2651 2346 ; call return 2652 2346 ; save w0 pseudo proc descr unch. 2653 2346 ; save w1 mess unch. 2654 2346 ; save w2 mess flag unch. 2655 2346 ; save w3 name unch. 2656 2346 2656 2346 2656 2346 ; procedure send message(name, mess, buf); 2657 2346 ; call: return: 2658 2346 ; save w0 unchanged 2659 2346 ; save w1 mess unchanged 2660 2346 ; save w2 mess flag unchanged 2661 2346 ; save w3 name unchanged 2662 2346 b. i10 w. 2663 2346 ; send pseudo message: 2664 2346 e62: rl w3 x1+a28 ; proc:= savew0(cur); 2665 2348 sh w3 0 ; if savew0 <= 0 2666 2350 jl c29 ; then goto internal 3; 2667 2352 rl w2 x3+a10 ; 2668 2354 se w2 64 ; if kind(proc) <> pseudo kind 2669 2356 jl c29 ; then goto internal 3; 2670 2358 rl w2 x3+a50 ; 2671 2360 se w2 (b1) ; if main(proc) <> cur 2672 2362 jl c29 ; then goto internal 3; 2673 2364 am -1 ; function:= send pseudo message; 2674 2366 ; send message: 2675 2366 e8: al w0 0 ; function:= send message; 2676 2368 rs. w0 i7. ; save function; 2677 2370 rl w3 x1+a31 ; if savew3(cur) <= last of name table then 2678 2372 sh w3 (b7) ; 2679 2374 jl. i3. ; goto driver message; 2680 2376 i6: jl w3 d110 ; check mess area and name area(name); 2681 2378 wa w2 x1+a182 ; get phys. addr. 2682 2380 rl w3 x2+8 ; entry:=word(name+8); 2683 2382 sl w3 (b3) ; if entry<name table start or 2684 2384 sl w3 (b7) ; entry>=name table end then 2685 2386 jl. i1. ; goto search; 2686 2388 rl w3 x3 ; proc:=name table(entry); 2687 2390 dl w1 x2+2 ; 2688 2392 sn w0 (x3+a11) ; if name in call<>name in monitor then 2689 2394 se w1 (x3+a11+2) ; 2690 2396 jl. i1. ; goto search; 2691 2398 sn w0 0 ; if name(0)=0 then 2692 2400 jl. i2. ; goto unknown; 2693 2402 dl w1 x2+6 ; 2694 2404 sn w0 (x3+a11+4) ; 2695 2406 se w1 (x3+a11+6) ; 2696 2408 jl. i1. ; 2697 2410 2697 2410 ; the receiver is found. now check bufclaim and deliver the message 2698 2410 ; w3=proc 2699 2410 i0: rl. w0 i7. ; if function = send pseudo message then 2700 2412 sn w0 0 ; begin 2701 2414 jl. i10. ; 2702 2416 rl w0 x3+a10 ; if kind(receiver) <> internal 2703 2418 se w0 0 ; then goto internal 3; 2704 2420 jl c29 ; end; 2705 2422 i10: rl w1 b1 ; 2706 2424 bz w0 x1+a19 ; if buf claim(cur)=0 then 2707 2426 sn w0 0 ; goto decrease buffer claim; 2708 2428 jl d108 ; (which exits with save w2=0); 2709 2430 bs. w0 1 ; decrease (bufclaim(cur)); 2710 2432 hs w0 x1+a19 ; 2711 2434 rl w2 b8 ; buf:=next(mess pool); 2712 2436 rs w3 x2+4 ; receiver(buf):=proc; 2713 2438 rl. w3 i7. ; 2714 2440 se w3 0 ; if function = send pseudo message 2715 2442 jl. i8. ; then sender(buf):= pseudo proc 2716 2444 rs w1 x2+6 ; else sender(buf):= cur; 2717 2446 jl. i9. ; 2718 2448 i8: rl w3 x1+a28 ; 2719 2450 rs w3 x2+6 ; 2720 2452 i9: 2721 2452 rl w3 x1+a30 ; 2722 2454 rs w3 x2+a139 ; mess flag(buf):=saved w2; 2723 2456 rs w2 x1+a30 ; save w2(cur):=buf; 2724 2458 rl w3 x1+a29 ; mess:=save w1(cur); 2725 2460 wa w3 x1+a182 ; get phys. addr. 2726 2462 dl w1 x3+2 ; 2727 2464 ds w1 x2+10 ; move 8 words from mess to buf; 2728 2466 dl w1 x3+6 ; 2729 2468 ds w1 x2+14 ; 2730 2470 dl w1 x3+10 ; 2731 2472 ds w1 x2+18 ; 2732 2474 dl w1 x3+14 ; 2733 2476 i4: ds w1 x2+22 ; move last: 2734 2478 jl w3 d5 ; remove(buf); 2735 2480 al w3 c99 ; deliver message(buf); 2736 2482 jl. d16. ; goto interrupt return; 2737 2484 2737 2484 ; the name table address was illegal or not correct: 2738 2484 2738 2484 i1: rl w1 b1 ; w1:= cur 2739 2486 ws w2 x1+a182 ; logical address 2740 2488 jl w3 d11 ; search name(name.entry) 2741 2490 jl. i2. ; not found: goto unknown 2742 2492 wa w2 x1+a182 ; physical buffer address 2743 2494 rs w3 x2+8 ; word(name+8):=entry; 2744 2496 rl w3 x3 ; proc:=name table(entry); 2745 2498 jl. i0. ; goto found; 2746 2500 2746 2500 i2: rl w1 b1 ; unknown: 2747 2502 rl w2 b8 ; buf:=next(mess pool); 2748 2504 rl w3 x1+a30 ; 2749 2506 rs w3 x2+a139 ; mess.flag=saved w2 2750 2508 jl w3 d108 ; claim buffer(cur, buf); 2751 2510 rs w2 x1+a30 ; save w2(cur) := buf; 2752 2512 al w0 5 ; receiver(buf):=result:=5; 2753 2514 rl. w3 i7. ; if function = send pseudo message 2754 2516 se w3 0 ; then sender(buf):= pseudo proc 2755 2518 rl w1 x1+a28 ; else sender(buf):= cur; 2756 2520 ds w1 x2+6 ; sender(buf):=cur; 2757 2522 al w3 c99 ; deliver answer(buf); 2758 2524 jl. d15. ; goto interrupt return; 2759 2526 2759 2526 i3: sl w3 (b5) ; driver message: 2760 2528 sl w3 (b7) ; if save w3(cur) outside nametable then 2761 2530 jl. i6. ; continue normal;; 2762 2532 ; test that save w1(cur) is an external proc description 2763 2532 rl w2 b4 ; 2764 2534 rl w3 x1+a29 ; for w2 := first device in name table 2765 2536 i5: sl w2 (b5) ; step 2 until top device do 2766 2538 jl c29 ; 2767 2540 al w2 x2+2 ; if save w1(cur) = entry(w2) then 2768 2542 se w3 (x2-2) ; goto found; 2769 2544 jl. i5. ; not found: goto internal 3; 2770 2546 rl w0 x3+a10 ; found: 2771 2548 sz w0 -1-64 ; if kind(proc) = internal process or pseudo process 2772 2550 se w1 (x3+a250) ; or cur <> driverproc(proc) then 2773 2552 jl c29 ; goto internal 3; 2774 2554 rl w2 b8 ; buf := next (mess buf pool); 2775 2556 jl w3 d108 ; claim buffer(buf); 2776 2558 rl w3 (x1+a31) ; receiver(buf) := name table(save w3(cur)); 2777 2560 rl w0 x1+a29 ; sender(buf) := proc; i.e. save w1(cur); 2778 2562 ds w0 x2+6 ; 2779 2564 ld w1 -65 ; 2780 2566 ds w1 x2+10 ; clear rest of message; 2781 2568 ds w1 x2+14 ; 2782 2570 ds w1 x2+18 ; 2783 2572 rs w1 x2-2 ; set message flag :=0 2784 2574 jl. i4. ; goto move last; 2785 2576 i7: 0 ; save function; 2786 2578 e. 2787 2578 2787 2578 ; procedure wait answer(buf, answer, result); 2788 2578 ; call: return: 2789 2578 ; save w0 result (=1, 2, 3, 4, 5) 2790 2578 ; save w1 answer unchanged 2791 2578 ; save w2 b uf unchanged 2792 2578 ; save w3 unchanged 2793 2578 b. i5 w. 2794 2578 2794 2578 e9: jl w3 d103 ; check message area and buf; 2795 2580 rl w3 x2+6 ; proc:= sender(buf); 2796 2582 rl w0 x3+a10 ; if kind(proc) = pseudo kind then 2797 2584 se w0 64 ; begin 2798 2586 jl. i0. ; if main(proc) <> cur 2799 2588 rl w0 x3+a50 ; then goto internal 3 2800 2590 se w0 (b1) ; else goto ok; 2801 2592 jl c29 ; end 2802 2594 jl. i1. ; else 2803 2596 i0: se w1 (x2+6) ; if proc <> cur 2804 2598 jl c29 ; then goto internal 3; 2805 2600 i1: ; ok: 2806 2600 rl w0 x2+4 ; w0:=receiver(buf); 2807 2602 sz w0 -8 ; if answer not send then 2808 2604 jl d104 ; goto remove wait answer; 2809 2606 rs w0 x1+a28 ; save w0(cur):=result; 2810 2608 jl w3 d109 ; increase claim, remove release buf(cur, buf); 2811 2610 rl w3 b1 ; w3:=cur; 2812 2612 al w1 x2+8 ; 2813 2614 rl w2 x3+a29 ; move mess(buf+8, answer); 2814 2616 wa w2 x3+a182 ; get physical address of answer area 2815 2618 al w3 c99 ; 2816 2620 jl d14 ; goto interrupt return; 2817 2622 e. 2818 2622 2818 2622 ; procedure wait message(name, mess, buf, result); 2819 2622 ; call: return: 2820 2622 ; save w0 result (=sender descr addr) 2821 2622 ; save w1 mess unchanged 2822 2622 ; save w2 buf 2823 2622 ; save w3 name unchanged 2824 2622 2824 2622 b. i8 w. 2825 2622 2825 2622 e10: jl w3 d110 ; check mess area and name area; 2826 2624 al w3 -8 ; 2827 2626 al w2 x1+a15 ; buf:=event q(cur); 2828 2628 i2: rl w2 x2+0 ; next: buf:=next(buf); 2829 2630 sn w2 x1+a15 ; if buf=event q(cur) then 2830 2632 jl d105 ; goto remove wait message; 2831 2634 sz w3 (x2+4) ; if answer then 2832 2636 jl. i3. ; 2833 2638 jl. i2. ; goto next; 2834 2640 i3: sl w2 (b8+4) ; if buf not message buffer then 2835 2642 sl w2 (b8+6) ; 2836 2644 jl. i2. ; goto next; (i.e. some kind of general event); 2837 2646 sh w3 (x2+4) ; if message buffer not claimed then 2838 2648 jl w3 d108 ; claim buffer(cur,buf); 2839 2650 jl w3 d5 ; remove(buf); 2840 2652 rl w3 x2+6 ; 2841 2654 rs w3 x1+a28 ; save w0(cur):=sender(buf); 2842 2656 rs w2 x1+a30 ; save w2(cur):=buf; 2843 2658 sh w3 0 ; if sender(buf)<=0 then 2844 2660 al w3 x1 ; sender:=dummy name address; 2845 2662 rl w2 x1+a31 ; move 4 words process name 2846 2664 wa w2 x1+a182 ; add base of current process 2847 2666 dl w1 x3+a11+2 ; from sender 2848 2668 ds w1 x2+2 ; 2849 2670 dl w1 x3+a11+6 ; 2850 2672 ds w1 x2+6 ; to name parameter; 2851 2674 rl w2 b1 ; 2852 2676 rl w0 x2+a182 ; get base of current process 2853 2678 dl w3 x2+a30 ; mess:= save w1(cur) 2854 2680 wa w2 0 ; get physical address of message area 2855 2682 al w1 x3+8 ; w1:=buf+8; 2856 2684 al w3 c99 ; move mess(buf+8, mess); 2857 2686 jl d14 ; goto interrupt return; 2858 2688 2858 2688 ; procedure send answer(buf, answer, result); 2859 2688 ; call: return: 2860 2688 ; save w0 result unchanged 2861 2688 ; save w1 answer unchanged 2862 2688 ; save w2 buf unchanged 2863 2688 ; save w3 unchanged 2864 2688 2864 2688 e11: jl w3 d103 ; check message area and buf(cur); 2865 2690 ac w3 (x2+4) ; check state: 2866 2692 sh w3 -1 ; if receiver(buf)>0 2867 2694 jl c29 ; goto internal 3; (i.e. not claimed); 2868 2696 sz w3 2.1 ; make receiver even; 2869 2698 al w3 x3-1 ; (in case of immediate message) 2870 2700 rl w0 x3+a10 ; if kind(-receiver(buf))=pseudoproc then 2871 2702 sn w0 64 ; 2872 2704 rl w3 x3+a50 ; receiver:=-mainproc(-receiver); 2873 2706 sz w0 -1-64 ; if receiver is neither internal process nor pseudo process then 2874 2708 rl w3 x3+a250 ; receiver := driverproc(receiver); 2875 2710 se w1 x3 ; if -receiver<>cur then 2876 2712 jl c29 ; goto internal 3; (i.e. cur not receiver); 2877 2714 2877 2714 rl w3 x2+4 ; if receiver(buf) odd then 2878 2716 sz w3 2.1 ; goto immediate message; 2879 2718 jl. i4. ; 2880 2720 2880 2720 rl w0 x1+a28 ; result:=save w0(cur); 2881 2722 sl w0 1 ; if result<1 or 2882 2724 sl w0 6 ; result>5 then 2883 2726 jl c29 ; goto internal 3; 2884 2728 rs w0 x2+4 ; receiver(buf):=result; 2885 2730 bz w3 x1+a19 ; 2886 2732 al w3 x3+1 ; increase buf claim(cur); 2887 2734 hs w3 x1+a19 ; 2888 2736 rl w0 x1+a182 ; 2889 2738 rl w1 x1+a29 ; 2890 2740 wa w1 0 ; get physical address of answer area 2891 2742 al w2 x2+8 ; 2892 2744 jl w3 d14 ; move mess(answer, buf+8); 2893 2746 al w2 x2-8 ; 2894 2748 al w3 c99 ; deliver answer(buf); 2895 2750 jl. d15. ; goto interrupt return; 2896 2752 2896 2752 ; immediate message 2897 2752 ; originates from a call of initialize process etc 2898 2752 2898 2752 ; entry: w1=cur, w2=buf, w3=receiver (negative, odd) 2899 2752 i4: ac w3 x3+1 ; make receiver even; 2900 2754 rs. w3 i8. ; save(receiver); 2901 2756 dl w0 x2+8 ; 2902 2758 ds. w0 i7. ; save(sender(buf), switch); 2903 2760 jl w3 d109 ; increase bufclaim, remove release buf(cur, buf); 2904 2762 ; now the receiving driver has no responsibilities any longer 2905 2762 2905 2762 rl. w1 i6. ; restore(sender); 2906 2764 sh w1 0 ; if sender <= 0 then 2907 2766 jl c99 ; goto interrupt return; (i.e. regretted) 2908 2768 2908 2768 al w0 -1<1 ; make save ic(sender) even to 2909 2770 la w0 x1+a33 ; indicate that answer is received; 2910 2772 rs w0 x1+a33 ; 2911 2774 2911 2774 bz w3 x1+a19 ; increase(bufclaim(sender)); 2912 2776 al w3 x3+1 ; (remember: the earlier decrease was just 2913 2778 hs w3 x1+a19 ; to facilitate...) 2914 2780 2914 2780 ; maybe transfer result: 2915 2780 rl. w3 i7. ; restore(switch); 2916 2782 rl w2 b1 ; w2 := cur; 2917 2784 rl w0 x2+a28 ; result := save w0(cur); 2918 2786 se w3 4 ; if switch <> 4 then 2919 2788 rs w0 x1+a28 ; save w0(sender) := result; (i.e. unless release process) 2920 2790 2920 2790 ; maybe do the final insertion/removal of user/reserver: 2921 2790 se w0 0 ; if result = 0 then 2922 2792 jl. i5. ; begin 2923 2794 rl w0 x2+a29 ; if save w1(cur) odd 2924 2796 sz w0 2.1 ; 2925 2798 al w3 x3+1 ; and switch = 0 then 2926 2800 sn w3 1 ; 2927 2802 al w3 2 ; switch := 2; i.e. reserve process; 2928 2804 rl. w2 i8. ; restore(receiver); 2929 2806 jl. x3+2 ; case switch(buf) of: 2930 2808 am d126-d125; switch=0: initialize proc: insert user(sender, receiver proc) 2931 2810 am d125-d124; switch=2: reserve proc: insert reserver( - , - - ) 2932 2812 jl w3 d124 ; switch=4: release proc: remove reserver( - , - - ) 2933 2814 i5: ; end; 2934 2814 2934 2814 bz w0 x1+a13 ; if state(sender) = waiting for proc func then 2935 2816 sn w0 a101 ; link internal(sender); 2936 2818 jl w3 d10 ; (i.e. start unless already stopped by parent) 2937 2820 2937 2820 jl c99 ; goto interrupt return; 2938 2822 2938 2822 i6: 0 ; saved sender(buf) 2939 2824 i7: 0 ; saved switch 2940 2826 i8: 0 ; saved receiver(buf) 2941 2828 2941 2828 e. 2942 2828 2942 2828 ; procedure wait event(last buf, next buf, result); 2943 2828 ; call: return: 2944 2828 ; save w0 result (=0, 1) 2945 2828 ; save w1 unchanged 2946 2828 ; save w2 last buf unchanged 2947 2828 ; save w3 unchanged 2948 2828 2948 2828 ; procedure test event(last buf, next buf, result); 2949 2828 ; call: return: 2950 2828 ; saved w0 result (-1: empty, 0: message, 1: answer) 2951 2828 ; saved w1 unchanged/sender(mess)/message flag 2952 2828 ; saved w2 last buf next buf 2953 2828 ; saved w3 unchanged 2954 2828 2954 2828 2954 2828 b. i20 w. 2955 2828 c96: rl w1 b1 ; entry to wait first event: 2956 2830 rl w2 x1+a302 ; goto wait-first-event entry 2957 2832 jl (x2+a304) ; in the driver process; 2958 2834 2958 2834 e33: am -1-0 ; test event: function:=inspect; 2959 2836 2959 2836 e12: al w0 0 ; wait event: function:=wait; 2960 2838 rs. w0 i0. ; 2961 2840 rl w2 x1+a30 ; last buf:=save w2(cur); 2962 2842 se w2 0 ; if last buf<>0 then 2963 2844 jl. i4. ; check event(cur, last buf); 2964 2846 al w2 x1+a15 ; else last buf:=event q(cur); 2965 2848 i3: al w3 x2 ; 2966 2850 al w0 0 ; 2967 2852 jl. i6. ; goto test buf; 2968 2854 i4: jl w3 d19 ; check event: call check event 2969 2856 jl. i3. ; 2970 2858 2970 2858 ; scan the event queue, from last buf, until last buf or already waited buf. 2971 2858 ; in the last case: release the claim. 2972 2858 ; 2973 2858 ; w0=0, w2=buf, w3=last buf 2974 2858 i5: rl w2 x2+0 ; next buf: buf:=next(buf); 2975 2860 sn w2 x3 ; if buf=last buf then 2976 2862 jl. i9. ; goto all buffers released; 2977 2864 i6: se w2 x1+a15 ; test buf: if buf=event q(cur) or 2978 2866 sh w0 (x2+4) ; receiver(buf)>=0 then 2979 2868 jl. i5. ; goto next buf; 2980 2870 sl w2 (b8+4) ; 2981 2872 sl w2 (b8+6) ; if buffer not message buffer then 2982 2874 jl. i5. ; goto next buf; (i.e. some kind of general event); 2983 2876 2983 2876 ; an already claimed buffer is found 2984 2876 sh w0 (x2+6) ; if sender(buf)<0 then 2985 2878 jl. i7. ; begin comment regretted, perform the actual release; 2986 2880 sn w3 x2 ; if last buf=buf then 2987 2882 rl w3 x2+2 ; last buf:=last(buf); 2988 2884 al w0 x3 ; save last buf; 2989 2886 jl w3 d106 ; remove and release buf(buf); 2990 2888 rl w3 0 ; restore last buf; 2991 2890 rl w1 b1 ; restore cur; 2992 2892 jl. i8. ; end 2993 2894 i7: ; else 2994 2894 ws w0 x2+4 ; receiver(buf):=+receiver(buf); 2995 2896 rs w0 x2+4 ; 2996 2898 i8: ; 2997 2898 bz w2 x1+a19 ; 2998 2900 al w2 x2+1 ; increase(buffer claim(cur)); 2999 2902 hs w2 x1+a19 ; 3000 2904 i9: ; buf released: 3001 2904 3001 2904 ; at this point there should not be any claimed buffers in the queue... 3002 2904 ; examine the next event in the queue 3003 2904 ; 3004 2904 ; w3=last buf 3005 2904 rl w2 x3+0 ; buf:=next(last buf); 3006 2906 sn w2 x1+a15 ; if buf=event q(cur) then 3007 2908 jl. i13. ; goto empty; 3008 2910 rs w2 x1+a30 ; save w2(proc):=buf; 3009 2912 3009 2912 ; the buf may either be a message buffer, an interrupt operation 3010 2912 ; or a general event 3011 2912 sl w2 (b8+4) ; if buf is not message buffer then 3012 2914 sl w2 (b8+6) ; 3013 2916 jl. i11. ; goto other operation; 3014 2918 rl w0 x2+4 ; save w0(cur):= 3015 2920 sz w0 -8 ; if 0<=receiver(buf)<8 then 3016 2922 am -1 ; 1 else 0; 3017 2924 al w0 1 ; i.e.: 0==message, 3018 2926 rs w0 x1+a28 ; 1==answer; 3019 2928 rl. w3 i0. ; 3020 2930 se w3 -1 ; if function=test event then 3021 2932 jl. i10. ; if event=message then 3022 2934 sn w0 0 ; saved w1:=sender(message) 3023 2936 am a142-a139; else 3024 2938 rl w3 x2+a139 ; saved w1:=message flag(answer); 3025 2940 rs w3 x1+a29 ; 3026 2942 i10: ; 3027 2942 sn w0 0 ; if message then 3028 2944 jl w3 d108 ; claim buffer(cur, buf); 3029 2946 jl c99 ; goto interrupt return; 3030 2948 3030 2948 i11: ; other operation: 3031 2948 rl w3 (b6) ; 3032 2950 sl w2 x3 ; if operation <> internal process then 3033 2952 sl w2 (b8+4) ; 3034 2954 jl. i12. ; goto interrupt operation; 3035 2956 3035 2956 jl w3 d5 ; remove(operation); 3036 2958 jl. d120. ; goto take general event; 3037 2960 3037 2960 i12: ; interrupt operation: 3038 2960 jl w3 d5 ; remove(operation); 3039 2962 al w3 c99 ; take interrupt operation; 3040 2964 jl d127 ; goto interrupt return; 3041 2966 3041 2966 ; the queue was empty. 3042 2966 i13: rl. w0 i0. ; empty: 3043 2968 se w0 -1 ; if function<>test event then 3044 2970 jl d107 ; goto remove wait event; 3045 2972 rs w0 x1+a28 ; save w0:=-1(:=function); 3046 2974 jl c99 ; goto interrupt return; 3047 2976 3047 2976 i0: 0 ; function 3048 2978 e. 3049 2978 3049 2978 3049 2978 ; procedure get event(buf); 3050 2978 ; call: return: 3051 2978 ; save w0 unchanged 3052 2978 ; save w1 unchanged 3053 2978 ; save w2 buf unchanged 3054 2978 ; save w3 unchanged 3055 2978 3055 2978 b. i0 w. 3056 2978 e13: rl w2 x1+a30 ; buf:=save w2(cur); 3057 2980 jl w3 d19 ; check event(cur, buf); 3058 2982 rl w3 x2+4 ; if 0 <=receiver(buf)<8 then 3059 2984 sz w3 -8 ; begin comment answer; 3060 2986 jl. i0. ; 3061 2988 al w3 c99 ; increase claim, remove release buf(cur, buf); 3062 2990 jl d109 ; goto interrupt return; 3063 2992 i0: ; end; 3064 2992 3064 2992 ; message: if not claimed by means of wait event then claim it now: 3065 2992 sl w3 0 ; if receiver>=0 then 3066 2994 jl w3 d108 ; claim buffer(cur, buf); 3067 2996 3067 2996 al w3 c99 ; remove(buf); 3068 2998 jl d5 ; goto interrupt return; 3069 3000 e. 3070 3000 3070 3000 3070 3000 ; procedure regret message; 3071 3000 ; call: return: 3072 3000 ; save w1 unchanged 3073 3000 ; save w1 unchanged 3074 3000 ; save w2 buf unchanged 3075 3000 ; save w3 unchanged 3076 3000 3076 3000 e41: jl w3 d12 ; check message(buf); 3077 3002 rl w3 x2+6 ; proc:= sender(buf); 3078 3004 sh w3 0 ; 3079 3006 ac w3 x3 ; 3080 3008 rl w0 x3+a10 ; if kind(proc) = pseudo kind 3081 3010 sn w0 64 ; then proc:= main(proc); 3082 3012 rl w3 x3+a50 ; 3083 3014 bz w0 x2+8 ; 3084 3016 sn w3 (b1) ; if proc <> cur or 3085 3018 sz w0 1 ; operation(buf) odd then 3086 3020 jl c29 ; goto internal 3; 3087 3022 al w3 c99 ; regretted message(buf); 3088 3024 jl d75 ; goto interrupt return; 3089 3026 3089 3026 ; procedure get clock(time); 3090 3026 ; call: return: 3091 3026 ; save w0 time high 3092 3026 ; save w1 time low 3093 3026 ; save w2 unchanged 3094 3026 ; save w3 unchanged 3095 3026 3095 3026 e18: jl w3 d7 ; update time; 3096 3028 dl w3 b13+2 ; 3097 3030 ds w3 x1+a29 ; save w0w1(cur):=time; 3098 3032 jl c99 ; goto interrupt return; 3099 3034 3099 3034 ; procedure set clock(time); 3100 3034 ; call: return: 3101 3034 ; save w0 time high unchanged 3102 3034 ; save w1 time low unchanged 3103 3034 ; save w2 unchanged 3104 3034 ; save w3 unchanged 3105 3034 3105 3034 e19: bz w0 x1+a22 ; mask:=function mask(cur); 3106 3036 so w0 1<4 ; if mask(7)=0 then 3107 3038 jl c29 ; goto internal 3; 3108 3040 jl w3 d7 ; update time; 3109 3042 dl w3 b70+2 ; last inspected:= 3110 3044 ss w3 b13+2 ; last inspected 3111 3046 aa w3 x1+a29 ; -time 3112 3048 ds w3 b70+2 ; +newtime; 3113 3050 dl w3 x1+a29 ; 3114 3052 ss w3 b13+2 ; clockchange:= 3115 3054 aa w3 b15+2 ; clockchange+ 3116 3056 ds w3 b15+2 ; newtime - time; 3117 3058 dl w3 x1+a29 ; c. tested by clock driver; 3118 3060 ds w3 b13+2 ; time:=save w0w1(cur); 3119 3062 jl c99 ; goto interrupt return; 3120 3064 3120 3064 ; call of process functions: 3121 3064 ; 3122 3064 ; make a primary check on the parameters to ensure that they are inside the calling process. 3123 3064 ; notice especially that it is not always possible to check the consistence of the parameters, 3124 3064 ; because the circumstances may change before procfunc has time to perform the function. 3125 3064 ; special care must be taken, so that the call may be repeated: if the calling process is 3126 3064 ; stopped before procfunc reaches the process, the call is deleted, and the ic of the process 3127 3064 ; will be decreased to repeat the call as soon as the process is restarted. 3128 3064 3128 3064 b. i20 w. 3129 3064 3129 3064 e61: ; delete aux entry: 3130 3064 jl w3 d111 ; check name (save w2) area; 3131 3066 rl w2 x1+a29 ; first param := save w1(cur); 3132 3068 al w0 x2+a88-2 ; last param := first + entry size - 2; 3133 3070 al. w3 i3. ; check within (first, last); 3134 3072 jl d112 ; goto link call; 3135 3074 3135 3074 e60: ; create aux entry and area process: 3136 3074 jl w3 d111 ; check name (save w2) area; 3137 3076 e56: ; connect main catalog: 3138 3076 e52: ; insert entry: 3139 3076 am i6 ; switch := test entry area; 3140 3078 e51: ; prepare bs: 3141 3078 al. w0 i3. ; switch := link call; 3142 3080 rs. w0 i7. ; save switch; 3143 3082 3143 3082 rl w2 x1+a31 ; first param := save w3(cur); 3144 3084 al w0 x2+a88-2 ; last param := first param + catentrysize - 2; 3145 3086 jl w3 d112 ; check within(first,last); 3146 3088 3146 3088 bz w0 x2+28 ; last param := last slice(chaintable) 3147 3090 al w2 x2+a88-2 ; + first param + catentrysize - 2; 3148 3092 wa w0 4 ; 3149 3094 jl w3 d112 ; check within(first,last); 3150 3096 jl. (i7.) ; goto (saved switch); 3151 3098 i7: 0 ; saved switch 3152 3100 3152 3100 e53: ; insert bs: 3153 3100 e54: ; delete bs: 3154 3100 e55: ; delete entries: 3155 3100 jl w3 d111 ; check name (save w2) area; 3156 3102 jl. i3. ; goto link call; 3157 3104 3157 3104 e39: ; set bs claims: 3158 3104 jl w3 d111 ; check name(save w2) area; 3159 3106 3159 3106 ; get size of param (save w1(cur)): 3160 3106 ; set bs claims (continued): 3161 3106 am a110*4+4-12 ; size:=(maxkey+1)*4; 3162 3108 e28: ; create internal: 3163 3108 e31: ; modify internal: 3164 3108 am 12-8 ; size:=12; 3165 3110 e23: ; rename entry: 3166 3110 am 8-a88 ; size:=8; 3167 3112 e38: ; lookup head and tail: 3168 3112 i0: ; insert entry (continued): 3169 3112 am a88-a88+14 ; size:=catentry size; 3170 3114 e20: ; create entry: 3171 3114 e21: ; lookup entry: 3172 3114 e22: ; change entry: 3173 3114 al w0 a88-14-2 ; size:=catentry size-14; notice -2; 3174 3116 rl w2 x1+a29 ; first param:=save w1(cur); 3175 3118 wa w0 4 ; last param:=first param+size-2; 3176 3120 al. w3 i2. ; check within(first, last); 3177 3122 jl d112 ; goto check name(save w3); 3178 3124 e43: ; lookup-aux-entry: 3179 3124 al w0 a88-14-2 ; size:= catentrysize-14; NOTICE -2 3180 3126 rl w2 x1+a29 ; first param:= save w1(cur) 3181 3128 wa w0 4 ; last param := first param+size-2; 3182 3130 jl w3 d112 ; check within(first,last) 3183 3132 e44: al. w3 i2. ; clear-stat-entry: 3184 3134 jl d111 ; check name( save w2) area; 3185 3136 3185 3136 3185 3136 e46: ; create entry lock process: 3186 3136 rl w2 x1+a31 ; first param:=save w3(cur); 3187 3138 al w0 x2+8 ; last param:=first param+8; 3188 3140 am d112-d111; check within(first, last) 3189 3142 ; instead of 3190 3142 e45: ; permanent entry in auxcat: 3191 3142 jl w3 d111 ; check name(save w2) area; 3192 3144 3192 3144 ; check param (save w3(cur)): 3193 3144 e24: ; remove entry: 3194 3144 e25: ; permanent entry: 3195 3144 e26: ; create area process: 3196 3144 e27: ; create peripheral process: 3197 3144 e32: ; remove process: 3198 3144 e34: ; generate name: 3199 3144 e36: ; set catalog base: 3200 3144 e37: ; set entry interval: 3201 3144 e40: ; create pseudo process: 3202 3144 i2: jl w3 d17 ; check name area; 3203 3146 e57: ; remove main catalog: 3204 3146 3204 3146 ; link the calling process to the process function queue. 3205 3146 ; procfunc is activated if it is waiting for a call. 3206 3146 i3: i6=i0-i3 ; 3207 3146 al w0 a101 ; link call: 3208 3148 jl w3 d9 ; remove internal(wait proc func); (w2 := cur + a16) 3209 3150 ; elem:=process q(cur); 3210 3150 rl w1 (b6) ; proc:=name table(first internal); i.e. proc func; 3211 3152 al w1 x1+a15 ; 3212 3154 jl w3 d6 ; link(event queue(proc func), elem); 3213 3156 al w1 x1-a15 ; 3214 3158 bz w0 x1+a13 ; if state(proc func)=wait message then 3215 3160 sn w0 a102 ; 3216 3162 jl w3 d10 ; link internal(proc func); 3217 3164 jl c99 ; goto interrupt return; 3218 3166 3218 3166 ; procedure reset device: special meaning when called form proc func. 3219 3166 e1: rl w2 (b6) ; proc:=name table(first internal); i.e. proc func; 3220 3168 se w2 x1 ; if proc<>cur then 3221 3170 jl. i4. ; goto reset device; 3222 3172 rl w2 x1+a15 ; proc:=next(event q(cur)); i.e. calling process; 3223 3174 jl w3 d5 ; remove (proc) from proc func queue; 3224 3176 rs. w2 i7. ; save (proc); 3225 3178 al w0 a102 ; 3226 3180 sn w3 x1+a15 ; if next(proc)=event q(cur) (i.e. queue empty) then 3227 3182 jl w3 d9 ; remove internal(wait mess); 3228 3184 rl. w2 i7. ; restore (proc); 3229 3186 al w1 x2-a16 ; 3230 3188 al w3 c99 ; link internal(proc); 3231 3190 jl d10 ; 3232 3192 3232 3192 ; reset device 3233 3192 ; call: return: 3234 3192 ; save w0 resettype result (=0,4) 3235 3192 ; save w1 device unchanged 3236 3192 ; save w2 unchanged 3237 3192 ; save w3 unchanged 3238 3192 3238 3192 i4: rl w2 x1+a29 ; device := save w1(cur); 3239 3194 lx w2 g49 ; exchange bit 0; 3240 3196 wa w2 b65 ; 3241 3198 sl w2 (b67) ; if device address outside 3242 3200 sl w2 (b68) ; controller table then 3243 3202 jl r4 ; goto result 4; 3244 3204 3244 3204 rl w2 x2+a311 ; status addres := status(contr descr); 3245 3206 al w2 x2-a230 ; 3246 3208 jl w1 d130 ; clear device(proc); 3247 3210 rl w1 b1 ; w1 := cur; 3248 3212 al w0 0 ; result:=0; 3249 3214 rx w0 x1+a28 ; if save w0(cur) = 0 then 3250 3216 sn w0 0 ; result := power restart 3251 3218 am 6-3 ; else 3252 3220 al w0 3 ; result := timeout; 3253 3222 al w2 x2+a241 ; w2 := interrupt operation(proc); 3254 3224 al w3 c99 ; deliver interrupt; 3255 3226 jl d121 ; goto interrupt return; 3256 3228 3256 3228 e29: rl w2 (b6) ; start internal process 3257 3230 se w2 x1 ; if cur <> first internal (i.e. proc func) then 3258 3232 jl. i2. ; goto check name(save w3); 3259 3234 ; proc func has issued a call of start process. 3260 3234 ; all processes to be started are linked together, via wait-address, and the start of the 3261 3234 ; chain is given in save w3. 3262 3234 i5: rl w1 x2+a31 ; rep: proc := save w3(proc func); 3263 3236 sn w1 0 ; if end chain then 3264 3238 jl c99 ; goto interrupt return; 3265 3240 3265 3240 rl w0 x1+a40 ; save w3(proc func) := wait address.proc; 3266 3242 rs w0 x2+a31 ; 3267 3244 rl w2 x1+a34 ; father := parent.proc; 3268 3246 bz w3 x2+a12 ; 3269 3248 al w3 x3+1 ; increase(stopcount(father)); 3270 3250 hs w3 x2+a12 ; 3271 3252 al w0 a101 ; 3272 3254 hs w0 x1+a13 ; state.proc := waiting for process function; (prepare for not starting) 3273 3256 rl w0 x1+a33 ; 3274 3258 so w0 1 ; if save ic(proc) even then 3275 3260 jl w3 d10 ; link internal(proc); 3276 3262 rl w2 (b6) ; 3277 3264 jl. i5. ; goto rep; 3278 3266 3278 3266 e30: ; stop internal process: 3279 3266 bz w0 x1+a19 ; if buf claim(cur)=0 then 3280 3268 sn w0 0 ; goto claim buffer(cur, irrellevant); 3281 3270 jl d108 ; (there are no buffers, so save w2:=0 and exit); 3282 3272 3282 3272 ; you may not actually claim the buffer for returning the answer yet, because the calling 3283 3272 ; process may get stopped itself, before procfunc reaches it. when the call is repeated, the 3284 3272 ; buffer might be claimed more than once. 3285 3272 jl. i2. ; goto check name area; 3286 3274 3286 3274 b.j10 w. 3287 3274 3287 3274 ; procedure copy. 3288 3274 ; call return 3289 3274 ; save w0 x z 3290 3274 ; save w1 x z 3291 3274 ; save w2 x z 3292 3274 ; save w3 x z 3293 3274 3293 3274 e35: ; copy message: 3294 3274 jl w3 d12 ; check message buf; 3295 3276 rl w3 x1+a29 ; first:=saved w1; 3296 3278 rl w0 x1+a31 ; last:=saved w3; 3297 3280 3297 3280 sl w3 (x1+a17) ; check: 3298 3282 sl w0 (x1+a18) ; if first<first addr(cur) 3299 3284 jl c29 ; or last>=top addr(cur) 3300 3286 ws w0 6 ; or first>last then 3301 3288 sh w0 -1 ; goto internal 3 3302 3290 jl c29 ; 3303 3292 ; 3304 3292 ac w3 (x2+4) ; rec:= -(-receiver(mess)) 3305 3294 so w3 2.1 ; if rec odd 3306 3296 sh w3 0 ; or rec<=0 then 3307 3298 jl c29 ; goto internal 3 3308 3300 rl w0 x3+a10 ; 3309 3302 sn w0 64 ; if rec is a pseudo process then 3310 3304 rl w3 x3+a50 ; rec:=main(rec); 3311 3306 rl w0 x3+a10 ; 3312 3308 sz w0 -1-64 ; if rec neither internal nor pseudo process then 3313 3310 rl w3 x3+a250 ; rec:=driver proc(rec); 3314 3312 se w3 x1 ; if rec<>cur then 3315 3314 jl c29 ; goto internal3; 3316 3316 3316 3316 bz w3 x2+8 ; 3317 3318 so w3 2.1 ; if operation(mes) even then 3318 3320 jl r3 ; goto result3; 3319 3322 3319 3322 ; further checking is postponed until procfunc. 3320 3322 jl. i3. ; goto link call; 3321 3324 3321 3324 3321 3324 3321 3324 ; procedure general copy 3322 3324 ; copies an area in the calling process to or from an 3323 3324 ; area described in a message buffer. 3324 3324 ; the first word to be copied is defined by its position 3325 3324 ; relative to the first address in the messagebuffer. 3326 3324 ; call return 3327 3324 ; save w0 result (=0,2,3) 3328 3324 ; save w1 params halfwords moved 3329 3324 ; save w2 buf 3330 3324 ; save w3 3331 3324 ; params+0 function (addr pair<1 + mode) 3332 3324 ; +2 first 3333 3324 ; +4 last 3334 3324 ; +6 relative(mess data buffer) 3335 3324 3335 3324 j10=512 ; max number of bytes immidiately transferred 3336 3324 3336 3324 e42: ; general copy: 3337 3324 jl w3 d12 ; check message buf 3338 3326 rl w3 x1+a29 ; param:= parameter address(=cur.w1) 3339 3328 al w0 x3+6 ; if param<first addr(cur) or 3340 3330 sl w3 (x1+a17) ; param+6>=top addr(cur) then 3341 3332 sl w0 (x1+a18) ; 3342 3334 jl c29 ; goto internal 3 3343 3336 wa w3 x1+a182 ; w3:= abs addr of param 3344 3338 rl w0 x3+0 ; 3345 3340 rs. w0 j4. ; function:=function(param); 3346 3342 ls w0 -1 ; if addr pair>12 then 3347 3344 sl w0 14 ; goto internal 3 3348 3346 jl c29 ; 3349 3348 rs. w0 j0. ; pair:=function>1; 3350 3350 ; 3351 3350 rl w0 x3+6 ; rel:= param.relative 3352 3352 sh w0 -1 ; if rel<0 then 3353 3354 jl c29 ; goto internal 3 3354 3356 rs. w0 j1. ; relative:=rel; 3355 3358 ; 3356 3358 dl w0 x3+4 ; first:=param.first addr 3357 3360 ; last:=param.last addr 3358 3360 sl w3 (x1+a17) ; check: 3359 3362 sl w0 (x1+a18) ; if first<first addr(cur) or 3360 3364 jl c29 ; last>=top addr(cur) or 3361 3366 ws w0 6 ; first>last then 3362 3368 sh w0 -1 ; goto internal 3 3363 3370 jl c29 ; 3364 3372 wa w0 x1+a182 ; abs first(cur):=first(cur)+base(cur); 3365 3374 ds. w0 j3. ; size(cur)-2:=last(cur)-first(cur); 3366 3376 ; 3367 3376 rl w2 x1+a30 ; mess:=saved w2; 3368 3378 ac w3 (x2+4) ; rec:= -(-receiver(mess)); 3369 3380 sh w3 0 ;*****aht. driver proc 3370 3382 ac w3 x3 ;***** 3371 3384 so w3 2.1 ; if rec odd 3372 3386 sh w3 0 ; or rec<=0 then 3373 3388 jl c29 ; goto internal 3; 3374 3390 rl w0 x3+a10 ; 3375 3392 sn w0 64 ; if rec is a pseudo process then 3376 3394 rl w3 x3+a50 ; rec:=main(rec); 3377 3396 rl w0 x3+a10 ; 3378 3398 sz w0 -1-64 ; if rec neither internal nor pseudo process then 3379 3400 rl w3 x3+a250 ; rec:=driver proc(rec); 3380 3402 se w3 x1 ; if rec<>cur then 3381 3404 jl c29 ; goto internal3; 3382 3406 3382 3406 rl w3 x2+a142 ; w3 := sender(mess); 3383 3408 bz w0 x2+a150 ; 3384 3410 sz w0 2.1 ; if operation(mess) even 3385 3412 sh w3 0 ; or sender <= 0 (i.e. regretted) then 3386 3414 jl r3 ; goto result 3; 3387 3416 rl w0 x3+a10 ; if kind(sender) = pseudo kind 3388 3418 sn w0 64 ; then sender := main(sender) 3389 3420 rl w3 x3+a50 ; 3390 3422 3390 3422 bz w0 x3+a13 ; if state(sender) = stopped then 3391 3424 sz w0 a105 ; 3392 3426 jl r2 ; goto result 2; 3393 3428 3393 3428 am. (j0.) ; first(mess):=first(mess+pair)+relative; 3394 3430 dl w1 x2+8+2 ; last(mess):=last(mess+pair+2); 3395 3432 wa. w0 j1. ; 3396 3434 sl w0 (x3+a17) ; if first(mess)<first(sender) 3397 3436 sl w1 (x3+a18) ; or last(mess)>last(sender) then 3398 3438 jl. i13. ; goto result3; 3399 3440 3399 3440 ws w1 0 ; size-2:=last(mess)-first(mess); 3400 3442 sh w1 -1 ; if size-2 < 0 3401 3444 jl c29 ; then goto internal 3; 3402 3446 wa w0 x3+a182 ; abs first(mess):=first(mess)+base(sender); 3403 3448 sl. w1 (j3.) ; if size>size(cur) then 3404 3450 rl. w1 j3. ; size:=size(cur); 3405 3452 al w3 x1+2 ; 3406 3454 rx w3 0 ; 3407 3456 rl. w2 j2. ; 3408 3458 3408 3458 ; w0: size, w2: abs first(cur), w3: abs first(mess) 3409 3458 3409 3458 rl. w1 j4. ; 3410 3460 so w1 2.1 ; if mode=1 then from:=cur, to:=mess 3411 3462 rx w2 6 ; else from:=mess, to:=cur; 3412 3464 ; 3413 3464 rl w1 b1 ; 3414 3466 sl w0 j10+1 ; if size>max number trf immidiately then 3415 3468 jl. i3. ; goto call link; 3416 3470 3416 3470 rs w0 x1+a29 ; saved w1:=size; 3417 3472 3417 3472 ; move. 3418 3472 ; w0: size, w1: , w2: from-addr, w3: to-addr 3419 3472 3419 3472 i8: ac w1 (0) ; remaining := - bytes; 3420 3474 so w1 1<1 ; if even number of words to move then 3421 3476 jl. i10. ; goto move fast; 3422 3478 rl w0 x2+0 ; 3423 3480 rs w0 x3+0 ; 3424 3482 al w3 x3+2 ; increase(to-address); 3425 3484 al w2 x2+2 ; increase(from-address); 3426 3486 al w1 x1+2 ; decrease(remaining); (remember: negative) 3427 3488 3427 3488 i10: ; move fast: 3428 3488 rs. w1 j5. ; save(remaining); 3429 3490 sl w1 i12 ; if remaining does no exceed size of move-table 3430 3492 jl. x1+i11. ; then switch out through table; 3431 3494 ; (otherwise move a whole portion) 3432 3494 i9: ; start of move-table: 3433 3494 dl w1 x2+30 ; 3434 3496 ds w1 x3+30 ; 3435 3498 dl w1 x2+26 ; 3436 3500 ds w1 x3+26 ; 3437 3502 dl w1 x2+22 ; 3438 3504 ds w1 x3+22 ; 3439 3506 dl w1 x2+18 ; 3440 3508 ds w1 x3+18 ; 3441 3510 dl w1 x2+14 ; 3442 3512 ds w1 x3+14 ; 3443 3514 dl w1 x2+10 ; 3444 3516 ds w1 x3+10 ; 3445 3518 dl w1 x2+6 ; 3446 3520 ds w1 x3+6 ; 3447 3522 dl w1 x2+2 ; 3448 3524 ds w1 x3+2 ; 3449 3526 i11: ; top of move-table: 3450 3526 i12=i9-i11 ; size of move-table (notice: negative) 3451 3526 3451 3526 al w3 x3-i12 ; increase(to-address); 3452 3528 al w2 x2-i12 ; increase(from-address); 3453 3530 rl. w1 j5. ; restore(remaining); 3454 3532 al w1 x1-i12 ; decrease(remaining); (remember: negative) 3455 3534 sh w1 -1 ; if not all moved yet then 3456 3536 jl. i10. ; goto move fast; 3457 3538 3457 3538 ; now return to result0. 3458 3538 rl w1 b1 ; 3459 3540 jl r0 ; exit: goto result0; 3460 3542 3460 3542 i13: rl w1 b1 ; exit3: 3461 3544 jl r3 ; goto result3; 3462 3546 3462 3546 j0: 0 ; pair 3463 3548 j1: 0 ; relative 3464 3550 j2: 0 ; abs first(cur) 3465 3552 j3: 0 ; size(cur)-2 3466 3554 j4: 0 ; function 3467 3556 j5: 0 ; remaining bytes (multiplum of 4 bytes) 3468 3558 e. 3469 3558 e. ; end of proc func block 3470 3558 3470 3558 3470 3558 ; set priority. 3471 3558 ; saved w0 result(=0,3) 3472 3558 ; saved w1 priority 3473 3558 ; saved w2 3474 3558 ; saved w3 name addr(child) 3475 3558 b.i10,j10 w. 3476 3558 e47: jl w3 d17 ; check name(saved w3); 3477 3560 rl w2 x1+a31 ; name addr:=saved w3; 3478 3562 jl w3 d11 ; search name(name, entry); 3479 3564 jl r3 ; not found: goto result3; 3480 3566 rl w3 x3 ; found: 3481 3568 rs. w3 i0. ; child:=proc(entry); 3482 3570 se w1 (x3+a34) ; if parent(child)<>cur then 3483 3572 jl r3 ; goto result3; 3484 3574 rl w0 x3+a10 ; 3485 3576 se w0 0 ; if child not internal proc then 3486 3578 jl r3 ; goto result3; 3487 3580 rl w0 x1+a29 ; prio:=saved w1; 3488 3582 sh w0 -1 ; if prio<0 then 3489 3584 jl c29 ; goto internal3; 3490 3586 ws w0 x3+a301 ; increment:=prio-priority(proc); 3491 3588 rs. w0 i1. ; 3492 3590 ; search descendents of process and the process itself, and increment their 3493 3590 ; priority values. if they are in timeslice queue, then reinsert them to 3494 3590 ; assure proper displacement in priority-queue. 3495 3590 rl w3 b6 ; 3496 3592 j0: rl w2 x3 ; 3497 3594 j1: sn. w2 (i0.) ; 3498 3596 jl. j3. ; 3499 3598 rl w2 x2+a34 ; 3500 3600 se w2 0 ; 3501 3602 jl. j1. ; 3502 3604 j2: al w3 x3+2 ; 3503 3606 se w3 (b7) ; 3504 3608 jl. j0. ; 3505 3610 jl r0 ; exit: goto result0; 3506 3612 3506 3612 j3: rl w2 x3 ; 3507 3614 rl w0 x2+a301 ; 3508 3616 wa. w0 i1. ; priority(proc):=priority(proc)+increment; 3509 3618 rs w0 x2+a301 ; 3510 3620 ;* rl w0 x2+a16 ; 3511 3620 ;* sn w0 x2+a16 ; if proc in time-slice-queue then 3512 3620 ;* jl. j2. ; 3513 3620 ;* rs. w3 i2. ; save w3; 3514 3620 ;* al w2 x2+a16 ; 3515 3620 ;* jl w3 d5 ; 3516 3620 ;* jl w3 d10 ; 3517 3620 ;* rl. w3 i2. ; 3518 3620 jl. j2. ; 3519 3622 3519 3622 i0: 0 ; proc(child) 3520 3624 i1: 0 ; increment 3521 3626 i2: 0 ; saved w3 3522 3628 3522 3628 e. 3523 3628 3523 3628 3523 3628 ; procedure relocate(name,start address,result) 3524 3628 ; call: return: 3525 3628 ; save w0 result (= 3,6 ) 3526 3628 ; save w1 start address 3527 3628 ; save w2 3528 3628 ; save w3 name address 3529 3628 3529 3628 b.i10,j10 w. 3530 3628 e48: jl w3 d17 ; check name(save w3) 3531 3630 rl w2 x1+a31 ; name addr:= save w3 3532 3632 jl w3 d11 ; search name(name,entry) 3533 3634 jl r3 ; not found: goto result 3 3534 3636 rl w3 x3 ; found : 3535 3638 rs. w3 i0. ; child:= proc(name table entry) 3536 3640 rl w0 x1+a182 ; 3537 3642 rs. w0 i2. ; save address base of calling process 3538 3644 se w1 (x3+a34) ; if parent(child) <> cur 3539 3646 jl r3 ; then goto result 3 3540 3648 rl w0 x3+a10 ; 3541 3650 se w0 0 ; if kind(child) <> internal 3542 3652 jl r3 ; then goto result 3 3543 3654 bz w0 x3+a13 ; if state(child) <> waiting f. start by parent 3544 3656 se w0 a99 ; then goto result 3 3545 3658 jl r3 ; 3546 3660 rl w0 x1+a29 ; 3547 3662 rl w2 x3+a18 ; if child is relocated outside relevant part 3548 3664 ws w2 x3+a17 ; of core then goto internal 3 3549 3666 wa w2 0 ; 3550 3668 sh w2 0 ; if overflow 3551 3670 jl c29 ; then goto result 3 3552 3672 al w2 x2-1 ; 3553 3674 sl w0 (x1+a17) ; 3554 3676 sl w2 (x1+a18) ; 3555 3678 jl c29 ; 3556 3680 rl w0 x1+a29 ; displ:= new start address - old start address 3557 3682 ws w0 x3+a17 ; 3558 3684 rs. w0 i1. ; 3559 3686 rl w3 b6 ; search: 3560 3688 j0: rl w2 x3 ; proc:= next internal in name table 3561 3690 j1: sn. w2 (i0.) ; if proc = child then goto update else 3562 3692 jl. j3. ; begin 3563 3694 rl w2 x2+a34 ; while parent(proc) <> 0 do 3564 3696 se w2 0 ; if parent(proc)=child then goto update 3565 3698 jl. j1. ; else proc:= parent(proc); 3566 3700 j2: ; end; 3567 3700 al w3 x3+2 ; next: 3568 3702 se w3 (b7) ; if more internals in name table 3569 3704 jl. j0. ; then goto search 3570 3706 rl w1 b1 ; 3571 3708 jl r0 ; exit: goto result 0 3572 3710 j3: rl w2 x3 ; update: proc:= proc(name table entry) 3573 3712 rl. w0 i1. ; current base(proc):= current base(parent)+displ; 3574 3714 wa. w0 i2. ; 3575 3716 rs w0 x2+a182 ; 3576 3718 dl w1 x2+a174 ; current lower write limit(proc):= 3577 3720 wa. w0 i1. ; initial lower write limit(proc)+displ; 3578 3722 wa. w1 i1. ; current upper write limit(proc):= 3579 3724 ds w1 x2+a184 ; initial upper write limit(proc)+displ; 3580 3726 jl. j2. ; goto next; 3581 3728 3581 3728 i0: 0 ; save child 3582 3730 i1: 0 ; save displacement 3583 3732 i2: 0 ; save address base of parent 3584 3734 e. 3585 3734 ; procedure change address base(name,displacement,result); 3586 3734 ; call: return: 3587 3734 ; save w0: result (= 1,3,6 ) 3588 3734 ; save w1: displacement 3589 3734 ; save w2: 3590 3734 ; save w3: name address 3591 3734 3591 3734 b.i10,j10 w. 3592 3734 e49: 3593 3734 jl w3 d17 ; check name(save w3) 3594 3736 rl w2 x1+a31 ; name addr:= save w3; 3595 3738 jl w3 d11 ; search name(name,entry); 3596 3740 jl r3 ; not found: goto result 3 3597 3742 rl w3 x3 ; found: proc:= proc(name table entry) 3598 3744 rl w0 x1+a29 ; 3599 3746 la w0 g50 ; remove lsb 3600 3748 rs. w0 i0. ; save displacement 3601 3750 se w1 (x3+a34) ; if parent(proc) <> cur 3602 3752 jl r3 ; then goto result 3 3603 3754 rl w0 x3+a10 ; 3604 3756 se w0 0 ; if kind(proc) <> internal 3605 3758 jl r3 ; then goto result 3 3606 3760 bz w0 x3+a13 ; 3607 3762 se w0 a99 ; if state(proc) <> waiting f. start by parent 3608 3764 jl r3 ; then goto result 3 3609 3766 al w1 x3 ; 3610 3768 rl w3 b6 ; check if actual process has any children. 3611 3770 j1: rl w2 x3 ; in this case goto result 3 3612 3772 sn w1 (x2+a34) ; 3613 3774 jl r3 ; 3614 3776 al w3 x3+2 ; 3615 3778 se w3 (b7) ; 3616 3780 jl. j1. ; 3617 3782 dl w0 x1+a18 ; first addr(proc):= first addr(proc)-displ 3618 3784 ws. w0 i0. ; last addr(proc):= last addr(proc)-displ 3619 3786 ws. w3 i0. ; 3620 3788 sh w3 -1 ; if logical address < 0 or 3621 3790 jl r1 ; wraps around top of core then 3622 3792 sh w0 x3 ; goto result 1 3623 3794 jl r1 ; 3624 3796 ds w0 x1+a18 ; 3625 3798 dl w0 x1+a170 ; if exception addr(proc) <> 0 then 3626 3800 sn w3 0 ; exception addr(proc):=exception addr(proc)-displ; 3627 3802 jl. j2. ; 3628 3804 ws. w3 i0. ; 3629 3806 j2: sn w0 0 ; if escape addr(proc) <> 0 then 3630 3808 jl. j3. ; escape addr(proc):=escape addr(proc); 3631 3810 ws. w0 i0. ; 3632 3812 j3: ds w0 x1+a170 ; 3633 3814 rl w0 x1+a182 ; address base(proc):= address base(proc)+displacement; 3634 3816 wa. w0 i0. ; 3635 3818 rs w0 x1+a182 ; 3636 3820 rl w0 x1+a33 ; ic(proc):= ic(proc)-displacement; 3637 3822 ws. w0 i0. ; 3638 3824 rs w0 x1+a33 ; 3639 3826 rl w1 b1 ; 3640 3828 jl r0 ; exit: goto result 0 3641 3830 3641 3830 i0: 0 ; save displacement 3642 3832 e. 3643 3832 3643 3832 ; procedure set cpa 3644 3832 ; set the cparegister of an internal process. 3645 3832 ; 3646 3832 ; call return 3647 3832 ; 3648 3832 ; save w0 result (=0,2,3,4 ) 3649 3832 ; save w1 cpa 3650 3832 ; save w2 3651 3832 ; save w3 name adr(proc) 3652 3832 ; 3653 3832 3653 3832 b. i10, j10 w. 3654 3832 3654 3832 e63: jl w3 d101 ; check and search name 3655 3834 jl r3 ; not found: result 3 3656 3836 rl w3 x3 ; found : 3657 3838 rs. w3 i1. ; save proc 3658 3840 rl w0 x3+a10 ; if process not an internal process 3659 3842 se w0 0 ; then goto result 3 3660 3844 jl r3 ; 3661 3846 se w1 (x3+a34) ; if parent(proc) <> cur 3662 3848 jl r3 ; then goto result 3 3663 3850 zl w0 x3+a13 ; if state(child) <> waiting for start by parent 3664 3852 se w0 a99 ; then goto result 2 3665 3854 jl r2 ; 3666 3856 rl w0 x1+a29 ; save cpa value 3667 3858 la w0 g50 ; 3668 3860 rs. w0 i0. ; 3669 3862 al w0 x3 ; if the process has any children 3670 3864 rl w3 b6 ; then goto result 2 3671 3866 j1: rl w2 x3 ; 3672 3868 sn w0 (x2+a34) ; 3673 3870 jl r2 ; 3674 3872 al w3 x3+2 ; 3675 3874 se w3 (b7) ; 3676 3876 jl. j1. ; 3677 3878 rl. w0 i0. ; 3678 3880 rl w3 0 ; 3679 3882 rl w2 +88 ; 3680 3884 sn w0 0 ; if cpa := 0 then 3681 3886 al w3 x2 ; cpa := last word of last monitor table 3682 3888 am. (i1.) ; if cpa:= 1 then 3683 3890 rl w2 +a171 ; 3684 3892 sn w0 1 ; cpa:= initial cpa(child) 3685 3894 al w3 x2 ; 3686 3896 rl. w2 i1. ; 3687 3898 sh w3 (x2+a171) ; check cpa: 3688 3900 sh w3 7 ; if cpa > initial cpa(child) or 3689 3902 jl r4 ; cpa < 7 then 3690 3904 rs w3 x2+a181 ; goto result 4 else 3691 3906 jl r0 ; goto result 0 ; end 3692 3908 i0: 0 ; saved cpa 3693 3910 i1: 0 ; saved proc 3694 3912 3694 3912 e. 3695 3912 3695 3912 3695 3912 3695 3912 ; procedure set process extension(first ext,last ext) 3696 3912 ; 3697 3912 ; save w0: result (return) 3698 3912 ; save w1: first process ext (call) 3699 3912 ; save w2: second process ext (call) 3700 3912 ; save w3: - 3701 3912 e58: 3702 3912 3702 3912 c.a400-1 3703 3912 rl w2 x1+a29 ; first:= save w1(cur) 3704 3912 rl w0 x1+a30 ; last:= save w2(cur) 3705 3912 sl w2 (0) ; if last < first then 3706 3912 rx w2 0 ; exchange(first,last) 3707 3912 jl w3 d112 ; check within(first,last) 3708 3912 rl w3 x1+a30 ; w3:= sec. proc. ext. 3709 3912 rl w2 x1+a29 ; w2:= first proc. ext. 3710 3912 ds w3 x1+a306 ; insert log. addr in process description 3711 3912 wa w2 x1+a182 ; 3712 3912 wa w3 x1+a182 ; 3713 3912 ds w3 b28 ; insert phys. addr in monitor table 3714 3912 jl r0 ; goto result 0; 3715 3912 z. 3716 3912 c.a400 3717 3912 jl c29 ; 3718 3914 z. 3719 3914 3719 3914 3719 3914 3719 3914 3719 3914 ; procedure start i/o; 3720 3914 ; call: return: 3721 3914 ; save w0 function select result (=0,1,2,3) 3722 3914 ; save w1 cp start (logic addr) unchanged 3723 3914 ; save w2 0 or buf unchanged 3724 3914 ; save w3 device address unchanged 3725 3914 3725 3914 ; the channelprogram is started using the device address in proc desc+a235. 3726 3914 ; at start time the working register holds the io-device number extracted 3727 3914 ; from the save w3 (only of importance in connection with rc8601). 3728 3914 3728 3914 ; result = 0: channel program etc ok, the interrupt operation will arive 3729 3914 ; (except after 'reset device') 3730 3914 ; 1: message regretted, i.e. no transfer started 3731 3914 ; 2: sender stopped , i.e. no transfer started 3732 3914 ; 3: sender address error, i.e.no transfer started 3733 3914 ; data command specifies buffers outside senders limits 3734 3914 ; (should give the reaction: message unintelligible) 3735 3914 3735 3914 ; the procedure returns always immediatly to the calling process 3736 3914 ; (i.e. the driver), to the instruction just following the call. 3737 3914 ; the driver may however specify (via function select) that 3738 3914 ; execution should be resumed via 'wait first event' (unless 3739 3914 ; result <> 0, in which case the normal resumption is made). 3740 3914 ; in case of parameter errors the driver process is break'ed, as usual. 3741 3914 3741 3914 ; parameter errors: 3742 3914 ; illegal function select 3743 3914 ; save w3 is not a device address 3744 3914 ; device descriptor not governed by current process 3745 3914 ; previous transfer not awaited (if not 'reset...') 3746 3914 ; save w2 not message buffer 3747 3914 ; state of message buffer not legal for transfer (***not implemented***) 3748 3914 ; channel program too long for device description (or outside driver process) 3749 3914 ; wait-command in channel program 3750 3914 ; illegal address code 3751 3914 ; address error (i.e. buffers outside limits (except sender limits) ) 3752 3914 ; illegal data- or skip-chain 3753 3914 ; 3754 3914 ; function select: 3755 3914 ; function a. 1 = 0 : return to just after call 3756 3914 ; = 1 : exit via the std return address 3757 3914 ; 3758 3914 ; function>1 a. 1 = 0 : no reset 3759 3914 ; = 1 : reset device before start of operation 3760 3914 ; 3761 3914 ; function>2 = 0 : no operation 3762 3914 ; = 1 : start channelprogram 3763 3914 ; = 2 : start std wait program 3764 3914 ; = 3 : start std control program 3765 3914 ; function>12 = 0 ; data= deviceno. < 1 (w3 > 2 ) 3766 3914 ; function>12 < > 0 ; data = function > 12 3767 3914 3767 3914 3767 3914 ; address code: 3768 3914 ; code = 0: data area in senders process (i.e. sender(buf)) 3769 3914 ; 2: - - - drivers process 3770 3914 ; 4: - - - device descr 3771 3914 ; 6: - - - message buffer 3772 3914 ; 8: - - - core (no check) 3773 3914 ; 3774 3914 ; first logic address depends on address code: 3775 3914 ; code = 0: logic address in senders process 3776 3914 ; 2: logic address in drivers process 3777 3914 ; 4: relative address in device descr (relative to a10) 3778 3914 ; 6: relative address in message buffer (relative to a140) 3779 3914 ; 8: absolute address, with no limit check 3780 3914 3780 3914 ; timeout: (unit: 0.1 msec) 3781 3914 ; if a channel program is not terminated with an interrupt within 3782 3914 ; the specified period, a software timeout will be generated, which 3783 3914 ; will deliver the interrupt operation to the driver. 3784 3914 ; the device will be reset, exept after a wait-program. 3785 3914 ; notice: if timeout = 0, no software timeout will be provided. 3786 3914 3786 3914 ; channel program: 3787 3914 ; the channel program must be in the drivers area, and will be 3788 3914 ; copied to the device description. 3789 3914 ; 3790 3914 ; the channel program may contain commands with the following format: 3791 3914 ; comm + a321: irrell < 12 + 4095 3792 3914 ; comm + a322: irrell 3793 3914 ; comm + a323: irrell 3794 3914 ; in this case the command will be interpreted as a dummy-command, 3795 3914 ; i.e. will not be copied into the device description 3796 3914 ; 3797 3914 ; if the program contains the commands 0,1,2,3 (i.e. sense, control, 3798 3914 ; read, write with data buffer) without the skip-modification, the 3799 3914 ; commands must have the following format: 3800 3914 ; comm + a321: address code < 12 + command < 8 + modifs 3801 3914 ; comm + a322: first logic address 3802 3914 ; comm + a323: char count 3803 3914 ; char count must be >= 0 (unless in sense commands, where is must be >= 12) 3804 3914 ; (furthermore: if the command is a sense, the 'top chp addr' in the 3805 3914 ; sense-area will be cleared) 3806 3914 ; 3807 3914 ; the stop-command must have the following format: 3808 3914 ; comm + a321: 0 < 12 + 2.1111 < 8 + 0 3809 3914 ; comm + a322: 0 3810 3914 ; comm + a323: timeout 3811 3914 ; (this may prepare for introducing 'jump'-commands with the same 3812 3914 ; format as the 'stop', except for: 3813 3914 ; comm + a322: continue-address ) 3814 3914 3814 3914 b. f20, h40, i60, j50 w. 3815 3914 3815 3914 ; function select table: 3816 3914 h0: f0 ; 0 : no operation 3817 3916 f1 ; 1 : start channelprogram 3818 3918 f2 ; 2 : start std wait program 3819 3920 f3 ; 3 : start std control program 3820 3922 j0=-h0.<1 ; top value of function select 3821 3922 3821 3922 ; address code table: 3822 3922 h1: f10 ;0: sender area 3823 3924 f11 ;2: driver area 3824 3926 f12 ;4: device descr 3825 3928 f13 ;6: message buffer 3826 3930 f14 ;8: abs core address (no limit check) 3827 3932 j1=-h1. ; top address code 3828 3932 3828 3932 h5: 0 ; device descr address 3829 3934 3829 3934 h10: 0 ; sender area used: 0=false, else true 3830 3936 h11: 0 ; =h10+2 ; driver area used: 0=false, else true 3831 3938 3831 3938 h15: 0 ; first of sender area (logic addr) 3832 3940 h16: 0 ; =h15+2 ; top - - - ( - - ) 3833 3942 h17: 0 ; sender process description address 3834 3944 3834 3944 h20: 0 ; abs first of channel program area in device descr 3835 3946 h21: 0 ; =h20+2 ; abs top - - - - - - - 3836 3948 h22: 0 ; last of current chp prog entry in device descr 3837 3950 h23: 0 ; old command 3838 3952 3838 3952 h25: 1<23 ; change bit 0 3839 3954 h26: -1<1 ; make addresses even 3840 3956 h27: 3 ; number of characters per word 3841 3958 3841 3958 h30: 2.1100 < 8 + 1 < 6; mask: databuffer-command without skip 3842 3960 h36: j36 ; mask: sign extended command field 3843 3962 3843 3962 h40: j32 ; std wait channel program 3844 3964 3844 3964 ; format of channel program, in driver area: 3845 3964 ; (used relative to w3 = last of entry) 3846 3964 j11 = -a320 + 2 ; (base of command) 3847 3964 j12 = j11 + a321 ; command field 3848 3964 j13 = j11 + a322 ; param 1 (=first logic address) 3849 3964 j14 = j11 + a323 ; param 2 (=char count, or timeout) 3850 3964 3850 3964 ; format of channel program, in device description: 3851 3964 ; (matches the format prescribed by the controller) 3852 3964 ; (used relative to w2 = last of entry) 3853 3964 j20 = 6 ; (size of entry) 3854 3964 j21 = -j20 + 2 ; (base of command) 3855 3964 j22 = j21 + 0 ; command field 3856 3964 j23 = j21 + 2 ; param 1 3857 3964 j24 = j21 + 4 ; param 2 3858 3964 3858 3964 j30 = 2.0011 < 8 ; mask: sense command 3859 3964 j31 = 12 ; minimum char count in sense command 3860 3964 j34 = -1 < 8 + 1 < 6 ; mask: sense command without skip (sign extended) 3861 3964 3861 3964 j32 = 2.0100 < 8 ; wait command (sign extended) 3862 3964 j33 = -1 < 8 ; stop command (sign extended) 3863 3964 j37 = -1 < 0 ; dummy command (sign extended) 3864 3964 3864 3964 j35 = 1 < 7 + 1 < 6 ; data- + skip-chain 3865 3964 j36 = -1 < 8 ; sign extended command field 3866 3964 3866 3964 j40 = -1 ; status bit: status transfer error 3867 3964 3867 3964 3867 3964 e50: ; start i/o: 3868 3964 ; this first part of the code checks some of the most important 3869 3964 ; parameters. 3870 3964 ; it should be possible to skip this checking, in case the driver 3871 3964 ; contains no errors ??? 3872 3964 rl w3 x1+a31 ; devaddr := save w3(cur); 3873 3966 sz w3 2.111 ; if devaddr not multiplum of 8 (bytes) then 3874 3968 jl c29 ; goto internal 3; i.e. not legal at all; 3875 3970 3875 3970 lx. w3 h25. ; change bit 0 in devaddr; 3876 3972 wa w3 b65 ; controller descr := controller table(devaddr); 3877 3974 sl w3 (b67) ; if controller descr outside 3878 3976 sl w3 (b68) ; controller table then 3879 3978 jl c29 ; goto internal 3; 3880 3980 3880 3980 rl w3 x3+a311 ; status addr := std status(controller descr); 3881 3982 al w3 x3-a230 ; device descr addr := proc(status addr); 3882 3984 rs. w3 h5. ; 3883 3986 se w1 (x3+a250) ; if cur <> driverproc(device) then 3884 3988 jl c29 ; goto internal 3; 3885 3990 3885 3990 rl w2 x1+a30 ; 3886 3992 se w2 0 ; if save w2(cur) <> 0 then 3887 3994 jl w3 d12 ; check message buf; 3888 3996 3888 3996 zl w3 x1+a28+1 ; function select := save w0(cur); 3889 3998 sl w3 0 ; if function select outside limits then 3890 4000 sl w3 j0 ; 3891 4002 jl c29 ; goto internal 3; 3892 4004 3892 4004 ; at this point the following has been checked: 3893 4004 ; save w3 is a legal device address, governed by the current process 3894 4004 ; save w2 is zero or a legal message buffer address 3895 4004 ; save w0 is a legal function select 3896 4004 3896 4004 ; w1 = cur, w3 = function select 3897 4004 3897 4004 so w3 1<1 ; if function select.reset is on then 3898 4006 jl. i6. ; device descr := saved device descr; 3899 4008 rl. w2 h5. ; clear device(device descr); 3900 4010 jl w1 d129 ; 3901 4012 rl w1 b1 ; w1 := cur; 3902 4014 zl w3 x1+a28+1 ; function select:=save(w0); 3903 4016 i6: ls w3 -1 ; function select := function select > 1; 3904 4018 jl. (x3+h0.) ; switch out through function select table; 3905 4020 3905 4020 ; general return actions: 3906 4020 ; a result is delivered to the driver, indicating the result of the call. 3907 4020 ; if result = ok and function select is odd, return to the driver is made 3908 4020 ; via 'wait first event', else a normal return is made 3909 4020 3909 4020 i3: am 3-2 ; result 3: address error: 3910 4022 i2: am 2-1 ; result 2: sender stopped: 3911 4024 i1: am 1-0 ; result 1: message regretted: 3912 4026 i0: al w0 0 ; result 0: ok: 3913 4028 3913 4028 rl w1 b1 ; w1 := cur; 3914 4030 rl w2 x1+a28 ; function select := save w0(cur); 3915 4032 rs w0 x1+a28 ; save w0(cur) := result; 3916 4034 sn w0 0 ; if result <> 0 or 3917 4036 so w2 2.1 ; function select even then 3918 4038 jl c99 ; goto interrupt return; 3919 4040 3919 4040 rl w2 x1+a302 ; get save area address; 3920 4042 rl w0 x2+a304 ; save ic(cur) := wait-first-event entry; 3921 4044 rs w0 x1+a33 ; 3922 4046 jl c99 ; goto interrupt return; 3923 4048 3923 4048 ; function select actions: 3924 4048 3924 4048 ; function select = no operation. 3925 4048 ; w1 = cur 3926 4048 f0=i0 ; goto result 0; 3927 4048 3927 4048 ; function select = start std control program 3928 4048 ; w1 = cur 3929 4048 f3: am. h40. ; first := std wait program; 3930 4050 ; continue with std wait program; 3931 4050 3931 4050 ; function select = start std wait program 3932 4050 ; w1 = cur 3933 4050 f2: al w0 0 ; first := 0 (i.e. no start) 3934 4052 rs. w0 h20. ; abs first of channel program := first; 3935 4054 3935 4054 rl w0 x1+a29 ; timeout := save w1(cur); 3936 4056 3936 4056 al w3 0 ; transfer code := 0; 3937 4058 ; (i.e. 'wait' not considered a transfer...) 3938 4058 jl. i50. ; goto init transfer code; 3939 4060 3939 4060 ; function select = start channel program: 3940 4060 ; w1 = cur 3941 4060 f1: ld w3 -100 ; 3942 4062 ds. w3 h11. ; sender area used := driver area used := false; 3943 4064 rs. w3 h23. ; old command := 0; (i.e. at least not data-chain) 3944 4066 ds. w3 h16. ; first,top sender area := 0; i.e. presume empty 3945 4068 3945 4068 rl w3 x1+a30 ; buf := save w2(cur); 3946 4070 sn w3 0 ; if buf = 0 then 3947 4072 jl. i10. ; goto buffer consistency checked; 3948 4074 3948 4074 ; when a message buffer is specified, it is generally concerning a 3949 4074 ; data-transfer to/from the sender area 3950 4074 ; 3951 4074 ; therefore the message buffer is checked once and for all, and the proper 3952 4074 ; buffer limits are found 3953 4074 ; 3954 4074 ; if any errors are found, the buffer limits will be set to en empty 3955 4074 ; buffer, thus any attempt to specify addresses within the sender area 3956 4074 ; will provoke a buffer limit violation 3957 4074 3957 4074 ; w1 = cur, w3 = buf 3958 4074 3958 4074 dl w2 x3+a142 ; w2 := sender(buf); (w1 := receiver(buf) ) 3959 4076 sh w2 0 ; if sender <= 0 then 3960 4078 jl. i1. ; goto message regretted; 3961 4080 3961 4080 bz w0 x3+a145 ; if operation(buf) is even then 3962 4082 so w0 2.1 ; 3963 4084 jl. i10. ; goto message buffer checked; 3964 4086 3964 4086 ; check that the buffer is a message sent to the driver: 3965 4086 sh w1 -1 ; if message received then 3966 4088 ac w1 x1 ; receiver := - receiver; 3967 4090 sh w1 7 ; if receiver <= 7 then 3968 4092 jl. i10. ; goto message buffer checked; i.e. an answer 3969 4094 3969 4094 rl w0 x1+a10 ; w0 := kind(receiver); 3970 4096 sn w0 64 ; if kind = pseudo process then 3971 4098 rl w1 x1+a50 ; receiver := mainproc (receiver); 3972 4100 sz w0 -1-64 ; if receiver is neither internal process nor 3973 4102 rl w1 x1+a250 ; pseudo process then 3974 4104 se w1 (b1) ; receiver := driverproc (receiver); 3975 4106 jl. i10. ; if receiver <> cur then goto message checked; 3976 4108 3976 4108 ; now buf has shown out to be a message, sent to this driver 3977 4108 ; w2 = sender(buf), w3 = buf 3978 4108 rl w0 x2+a10 ; w0 := kind(sender); 3979 4110 sn w0 64 ; if kind = pseudo process then 3980 4112 rl w2 x2+a50 ; sender := mainproc (sender); 3981 4114 sz w0 -1-64 ; if sender neither internal nor pseudo process then 3982 4116 rl w2 x2+a250 ; sender := driverproc (sender); 3983 4118 ; w2 = internal process, which sent the message buffer 3984 4118 ; w3 = message buffer 3985 4118 dl w1 x3+a152 ; w0w1 := first,last address(buf); (logic addresses) 3986 4120 la. w0 h26. ; make the limits even; 3987 4122 la. w1 h26. ; 3988 4124 sl w0 x1+1 ; if first address > last address then 3989 4126 jl. i10. ; goto message checked; 3990 4128 3990 4128 sl w0 (x2+a17) ; if first,last address area outside 3991 4130 sl w1 (x2+a18) ; the senders area then 3992 4132 jl. i10. ; goto message checked; 3993 4134 al w1 x1+2 ; first of sender area := first address; 3994 4136 ds. w1 h16. ; top - - - := last address + 2; 3995 4138 rs. w2 h17. ; save sender process description address; 3996 4140 3996 4140 ; message buffer consistency checked: 3997 4140 ; prepare moving of the channel program, i.e. get first,last of 3998 4140 ; channel program area in device descr, and transform them to absolute 3999 4140 ; addresses. 4000 4140 ; check that the channel-program-source starts within the driver process. 4001 4140 ; 4002 4140 ; (all regs irrell) 4003 4140 4003 4140 i10: ; message checked: 4004 4140 rl. w1 h5. ; device descr := saved descr; 4005 4142 dl w3 x1+a227 ; abs first of chp area in device descr := 4006 4144 wa w2 2 ; device descr + relative first of chp area; 4007 4146 wa w3 2 ; abs top of chp area in device descr := 4008 4148 ds. w3 h21. ; device descr + relative top of chp area; 4009 4150 4009 4150 rl w1 b1 ; w1 := cur; 4010 4152 rl w3 x1+a29 ; first of channel program := save w1 (cur); 4011 4154 sl w3 (x1+a17) ; if first of channel program 4012 4156 sl w3 (x1+a18) ; is outside current process then 4013 4158 jl c29 ; goto internal 3; 4014 4160 4014 4160 wa w3 x1+a182 ; w3 := first of channel program 4015 4162 al w3 x3-2 ; + base (cur) - 2; i.e. last of entry 4016 4164 al w2 x2-2 ; w2 := last of current entry in device descr; 4017 4166 4017 4166 ; next command: 4018 4166 ; w1 = cur 4019 4166 ; w2 = last of current entry in device descr (abs addr) 4020 4166 ; w3 = last of current entry in driver process (abs addr) 4021 4166 i15: al w2 x2+j20 ; next command: increase(device pointer); 4022 4168 sl. w2 (h21.) ; if outside top of device descr area then 4023 4170 jl c29 ; goto internal 3; i.e. channel program too long 4024 4172 rs. w2 h22. ; save (last of current device entry); 4025 4174 4025 4174 i16: rl w1 b1 ; skip command: 4026 4176 al w3 x3+a320 ; increase(driver pointer); 4027 4178 sl w3 0 ; if overflow or 4028 4180 sl w3 (x1+a18) ; outside top of driver process then 4029 4182 jl c29 ; goto internal 3; 4030 4184 4030 4184 ; move the command unchanged from driver area to device description: 4031 4184 dl w1 x3+j14 ; move (param 1, param 2); 4032 4186 ds w1 x2+j24 ; 4033 4188 rl w0 x3+j12 ; move (command); 4034 4190 rs w0 x2+j22 ; 4035 4192 sz. w0 (h30.) ; if command is not databuffer without skip then 4036 4194 jl. i30. ; goto test chain; 4037 4196 4037 4196 ; the command is sense, control, read or write with databuffer. 4038 4196 ; param 1 (i.e. the first logic addr) must be transformed to an absolute 4039 4196 ; address, using the address code. 4040 4196 ; check that the char count is not too small (command dependant). 4041 4196 ; 4042 4196 ; w0 = command word 4043 4196 ; w1 = param 2 (=char count) 4044 4196 4044 4196 sz w0 j30 ; minimum := if not sense command then 4045 4198 am -j31+1-1; 0 else sense-char-count; 4046 4200 sh w1 j31-1 ; if char count < minimum then 4047 4202 jl c29 ; goto internal 3; 4048 4204 4048 4204 ; compute size (and thereby last) of data buffer area 4049 4204 al w0 0 ; words := chars // number of chars per word; 4050 4206 wd. w1 h27. ; 4051 4208 ls w1 1 ; last byte used := words * 2 4052 4210 sn w0 0 ; - if chars mod (chars per word) = 0 then 4053 4212 al w1 x1-2 ; 2 else 0; 4054 4214 4054 4214 rl w0 x3+j13 ; w0 := first logic address; 4055 4216 wa w1 0 ; w1 := last logic address; (=last byte+first logic) 4056 4218 sl w0 x1+3 ; if first address > last address then 4057 4220 jl c29 ; goto internal 3; i.e. buffer wraps around top of core 4058 4222 4058 4222 ; w0 = first logic address 4059 4222 ; w1 = last logic address 4060 4222 ; w3 = abs last of current chp entry 4061 4222 bz w2 x3+j12 ; w2 := address code(current command); 4062 4224 sh w2 j1-1 ; if address code inside limits then 4063 4226 jl. (x2+h1.) ; switch out through address code table; 4064 4228 jl c29 ; else goto internal 3; i.e. illegal address code 4065 4230 4065 4230 ; address transformation actions: 4066 4230 4066 4230 ; address code = sender area: 4067 4230 ; w0 = first logic address 4068 4230 ; w1 = last logic address 4069 4230 f10: sl. w0 (h15.) ; if buffer area outside sender area then 4070 4232 sl. w1 (h16.) ; 4071 4234 jl. i3. ; goto address error; 4072 4236 4072 4236 rl. w2 h17. ; sender descr := saved sender process descr; 4073 4238 rs. w2 h10. ; sender area used := true; 4074 4240 wa w0 x2+a182 ; transform first address to absolute address; 4075 4242 jl. i20. ; goto first address transformed; 4076 4244 4076 4244 ; address code = driver area 4077 4244 ; w0 = first logic address 4078 4244 ; w1 = last logic address 4079 4244 f11: rl w2 b1 ; driver := cur; 4080 4246 sl w0 (x2+a17) ; if buffer area outside driver process then 4081 4248 sl w1 (x2+a18) ; 4082 4250 jl c29 ; goto internal 3; 4083 4252 4083 4252 rs. w2 h11. ; sender area used := true; 4084 4254 wa w0 x2+a182 ; transform first address to absolute address; 4085 4256 jl. i20. ; goto first address transformed; 4086 4258 4086 4258 ; address code = device description 4087 4258 ; w0 = first relative address 4088 4258 ; w1 = last relative address 4089 4258 f12: rl. w2 h5. ; 4090 4260 sl w0 (x2+a220) ; if buffer area outside 4091 4262 sl w1 (x2+a221) ; private area (device descr) then 4092 4264 jl c29 ; goto internal 3; 4093 4266 4093 4266 wa w0 4 ; transform first relative address to absolute addr; 4094 4268 jl. i20. ; goto first address transformed; 4095 4270 4095 4270 ; address code = message buffer 4096 4270 ; w0 = first relative address 4097 4270 ; w1 = last relative address 4098 4270 f13: sl w0 a145 ; if buffer area outside 4099 4272 sl w1 a146 ; message part of message buffer then 4100 4274 jl c29 ; goto internal 3; 4101 4276 4101 4276 rl w2 b1 ; buf := save w2 (cur); 4102 4278 wa w0 x2+a30 ; transform first relative address to absolute addr; 4103 4280 sh w0 x1 ; if buf <> 0 then 4104 4282 jl. i20. ; goto first address transformed 4105 4284 jl c29 ; else goto internal 3; 4106 4286 4106 4286 ; address code = abs core address 4107 4286 ; w0 = absolute first address 4108 4286 ; w1 = absolute last address 4109 4286 f14: ; continue with first address transformed 4110 4286 4110 4286 ; the legality of the buffer addresses has been checked, 4111 4286 ; and the first address is now an absolute core address 4112 4286 ; w0 = abs first address 4113 4286 ; w3 = last of current chp entry 4114 4286 i20: ; first address transformed: 4115 4286 rl. w2 h22. ; restore (device pointer); 4116 4288 rs w0 x2+j23 ; move abs first address to channel program; 4117 4290 4117 4290 ; now a complete command has been moved. 4118 4290 ; check that the command does not change during data- or skip-chain 4119 4290 ; w2 = last of device descr chp entry 4120 4290 ; w3 = last of current chp entry 4121 4290 i30: ; test chain: 4122 4290 bl w0 x2+j22+1 ; command := command byte(current entry); 4123 4292 sn w0 j37 ; if command = dummy command then 4124 4294 jl. i16. ; goto skip command; 4125 4296 rl. w1 h23. ; prev command := old command; 4126 4298 rs. w0 h23. ; old command := command; 4127 4300 sz w1 j35 ; if previous command contained any chains then 4128 4302 jl. i31. ; begin 4129 4304 jl. i32. ; test that the two commands are equal: 4130 4306 4130 4306 i31: lx w1 0 ; if prev command <> command then 4131 4308 sz w1 j36 ; goto internal 3; 4132 4310 jl c29 ; end; 4133 4312 i32: ; 4134 4312 4134 4312 ; to facilitate the drivers interpretation from the sense-commands, 4135 4312 ; the first word of the sense area is cleared. 4136 4312 ; thereby the driver can detect in a simple way, if that sense 4137 4312 ; has been executed. 4138 4312 ; 4139 4312 ; w0 = command (sign extended) 4140 4312 ; w2 = last of device descr chp entry 4141 4312 ; w3 = last of current chp entry 4142 4312 sz w0 j34 ; if command = sense without skip then 4143 4314 jl. i33. ; begin 4144 4316 al w1 0 ; top chp addr (sense area) := 0; 4145 4318 am (x2+j23) ; 4146 4320 rs w1 +a315 ; 4147 4322 i33: ; end; 4148 4322 4148 4322 ; a driver-supplied channel program may not contain a 'wait'-command, 4149 4322 ; because this migth delay the terminating interrupt infinitly, 4150 4322 ; thereby preventing the processes from being stopped. 4151 4322 ; 4152 4322 ; w0 = command (sign extended) 4153 4322 ; w2 = last of device descr chp entry 4154 4322 ; w3 = last of current chp entry 4155 4322 la. w0 h36. ; w0 := command bits of command; 4156 4324 sn w0 j32 ; if command = 'wait' then 4157 4326 jl c29 ; goto internal 3; 4158 4328 4158 4328 ; if the channel program has not encountered the 'stop'-command 4159 4328 ; then move and translate the next command 4160 4328 ; 4161 4328 ; w0 = command (sign extended) 4162 4328 ; w2 = last of device descr chp entry 4163 4328 ; w3 = last of current chp entry 4164 4328 4164 4328 rl w1 b1 ; w1 := cur; 4165 4330 se w0 j33 ; if command <> 'stop' then 4166 4332 jl. i15. ; goto next command; 4167 4334 4167 4334 ; (maybe it should be tested, that param 1 = 0, i.e. not a 'jump' ?) 4168 4334 ; rl w0 x2+j23 ; 4169 4334 ; se w0 0 ; 4170 4334 ; jl. jump-command 4171 4334 4171 4334 4171 4334 ; get the timeout-parameter from param 2 of the 'stop' command: 4172 4334 rl w0 x2+j24 ; timeout := param 2; 4173 4336 4173 4336 ; in case of transfer to/from senders area: 4174 4336 ; check that the sender is not stopped 4175 4336 ; increase stopcount to prevent further stopping of sender 4176 4336 ; 4177 4336 ; w0 = timeout 4178 4336 ; w1 = driver 4179 4336 4179 4336 rl. w3 h10. ; if sender area used then 4180 4338 sn w3 0 ; 4181 4340 jl. i40. ; begin 4182 4342 4182 4342 rl. w3 h17. ; sender := saved sender descr addr; 4183 4344 bz w2 x3+a13 ; if state(sender) shows 4184 4346 se w2 a99 ; 'waiting for start' then 4185 4348 sn w2 a100 ; 4186 4350 jl. i2. ; goto sender stopped; 4187 4352 4187 4352 bz w2 x3+a12 ; increase (stopcount (sender)); 4188 4354 al w2 x2+1 ; 4189 4356 hs w2 x3+a12 ; 4190 4358 i40: ; end; 4191 4358 4191 4358 ; the driver should actually be put in such a state, that all pending 4192 4358 ; transfers would be aborted, in case the driver is stopped. 4193 4358 ; however, until further, this is only done by means of increasing 4194 4358 ; the stopcount of the driver ( *** independant of transfer/no transfer 4195 4358 ; to/from the driver area *** ) 4196 4358 ; 4197 4358 ; w0 = timeout 4198 4358 ; w1 = driver 4199 4358 ; w3 = transfer code: 0 = no transfer to sender area 4200 4358 ; >0 = sender descr addr 4201 4358 4201 4358 c.-1 ; ++++ not implemented ++++ 4202 4358 rl. w2 h11. ; 4203 4358 sn w2 0 ; if driver area not used then 4204 4358 jl. i41. ; goto init transfer code field; 4205 4358 z. ; ++++ 4206 4358 4206 4358 al w3 x3+1 ; make transfer code odd; i.e. driver transfer 4207 4360 4207 4360 bz w2 x1+a12 ; increase (stopcount (driver) ); 4208 4362 al w2 x2+1 ; 4209 4364 hs w2 x1+a12 ; 4210 4366 4210 4366 c. -1; ++++ not implemented 4211 4366 i41: sn w3 0 ; if no transfers to the involved processes then 4212 4366 al w3 -1 ; transfer code := -1; i.e. transfer pending; 4213 4366 z. ; ++++ 4214 4366 4214 4366 ; initialize the 'transfer code' field in the device description 4215 4366 ; (the field will be used, when the interrupt arrives, 4216 4366 ; to decrease the involved stopcounts) 4217 4366 ; w0 = timeout, w1 = cur, w3 = transfer code 4218 4366 i50: rl. w2 h5. ; 4219 4368 rl w1 x2+a225 ; if transfer code (device descr) <> 0 then 4220 4370 se w1 0 ; goto internal 3; 4221 4372 jl c29 ; (i.e. transfer still in progress) 4222 4374 rs w3 x2+a225 ; move transfer code to device descr; 4223 4376 4223 4376 ; prepare timeout-operation: 4224 4376 ; 4225 4376 ; w0 = timeout 4226 4376 ; w2 = device descr 4227 4376 4227 4376 ; initialize controller table: 4228 4376 am (b1) ; 4229 4378 rl w3 +a31 ; entry:=logical device addr(device); 4230 4380 wa. w3 h25. ; + 1 < 23 4231 4382 wa w3 b65 ; base of controller table; 4232 4384 4232 4384 rl. w1 h20. ; chp start (controller table entry) := 4233 4386 rs w1 x3+a310 ; abs first of channel program area; 4234 4388 se w1 0 ; if chpg start = 0 then 4235 4390 jl. i54. ; begin 4236 4392 al w2 x2+a242 ; oper:= timeout operation address; 4237 4394 jl. i53. ; goto check timeout; 4238 4396 ; end; 4239 4396 4239 4396 ; prepare for receiving an unusual status, i.e. in case the controller 4240 4396 ; could not deliver the standard status informations 4241 4396 i54: al w3 0 ; 4242 4398 rs w3 x2+a230 ; chp addr (std status) := 0; 4243 4400 al w3 j40 ; 4244 4402 rs w3 x2+a233 ; event status (std status) := status transfer error; 4245 4404 4245 4404 al w2 x2+a242 ; oper := timeout operation address; 4246 4406 4246 4406 ; start the device: 4247 4406 ; 4248 4406 ; at this point the monitor migth introduce another strategy, 4249 4406 ; instead of just starting the device immediatly. 4250 4406 ; if the interrupt numbers are sparce, or if the bus migth 4251 4406 ; get overloaded, the actual starting can be delayed until 4252 4406 ; the resources are sufficient. 4253 4406 ; 4254 4406 ; notice that the monitor/driver conventions do not imply that 4255 4406 ; the transfer is started at once, i.e. buserrors or bustimeout 4256 4406 ; etc. are not returned to the driver at the calltime, but 4257 4406 ; when the interrupt-operation is received by the driver. 4258 4406 ; 4259 4406 ; under any circumstances the driver should have the result 0, 4260 4406 ; indicating that the transfer has been accepted to start. 4261 4406 ; 4262 4406 ; w0 = timeout 4263 4406 ; w2 = timeout operation 4264 4406 am (b1) ; if function > 12 = 0 then 4265 4408 zl w1 +a28 ; 4266 4410 se w1 0 ; 4267 4412 jl. i56. ; 4268 4414 am (b1) ; 4269 4416 bz w1 +a31+1 ; 4270 4418 ls w1 -2 ; w1:=io-devno<1; 4271 4420 i56: do w1 (x2-a242+a235) ; start device(device addr(device desc)); 4272 4422 4272 4422 sx 2.111 ; if any exceptions then 4273 4424 jl. i55. ; goto not started; 4274 4426 4274 4426 ; if the operation is in queue, there may be three reasons: 4275 4426 ; 1. a wait program is still in progress, i.e. in timeout-queue 4276 4426 ; (remove the operation and proceed, i.e. regret the wait-program) 4277 4426 ; 2. a wait program is terminated by an event, i.e. in event queue 4278 4426 ; (the operation may not be removed, because the driver has to 4279 4426 ; reset the controller in order to proceed) 4280 4426 ; 3. an uspecified channel program has terminated, i.e. in event queue 4281 4426 ; (this situation is treated as if it was a wait-program, 4282 4426 ; because it does not harm the monitor, but only confuses 4283 4426 ; the driver process) 4284 4426 4284 4426 i53: ; check timeout: 4285 4426 sn w2 (x2+0) ; if timeout operation in queue then 4286 4428 jl. i52. ; begin 4287 4430 4287 4430 ; search through the timeout-queue. 4288 4430 ; if the operation is found here, then simply remove it and proceed, 4289 4430 ; as if it had not been in queue 4290 4430 ; if not found here, it must be in the event-queue of the driver. 4291 4430 ; (just leave it there, because the driver must take proper action on it) 4292 4430 4292 4430 al w1 b69 ; elem := timeout-queue head; 4293 4432 i51: rl w1 x1+0 ; rep: elem := next(elem); 4294 4434 sn w1 b69 ; if end of timer-queue then 4295 4436 jl. i0. ; goto result 0; i.e. in event queue 4296 4438 4296 4438 se w1 x2 ; if elem = timeout operation then 4297 4440 jl. i51. ; goto rep; 4298 4442 4298 4442 ; found in timeout-queue: 4299 4442 jl w3 d5 ; remove(timeout operation); 4300 4444 i52: ; end; 4301 4444 4301 4444 ; w0 = timeout 4302 4444 ; w2 = timeout operation 4303 4444 4303 4444 al w1 b69 ; head := timeout queue head; 4304 4446 rs w0 x2-a242+a244; save timeout in timeout-field(operation); 4305 4448 se w0 0 ; if timeout <> 0 then 4306 4450 jl w3 d6 ; link (timeout queue, timeout operation); 4307 4452 4307 4452 jl. i0. ; goto result 0; i.e. transfer started ok; 4308 4454 4308 4454 ; the transfer could not actually be started, because of 4309 4454 ; some kind of bus/controller error. 4310 4454 ; 4311 4454 ; the interrupt operation must be returned to the driver, 4312 4454 ; together with indication of the kind of malfunction. 4313 4454 ; 4314 4454 ; w2 = linkfield of timeout operation 4315 4454 ; ex = error kind 4316 4454 4316 4454 i55: sx 2.1 ; errorkind := 4317 4456 am 1-2 ; if rejected then 1 4318 4458 al w0 2 ; else 2; 4319 4460 4319 4460 al. w3 i0. ; deliver interrupt(oper, error kind); 4320 4462 jl d121 ; goto result 0; 4321 4464 4321 4464 e. ; end of start i/o; 4322 4464 c.a400-1 4323 4464 \f 4323 4464 m. coroutine monitor 4324 4464 4324 4464 ;************************** c o r o u t i n e m o n i t o r ************************* 4325 4464 4325 4464 4325 4464 4325 4464 ; locations in process extension 1 are used by cmonprocedures as described below: 4326 4464 ; 4327 4464 ; -2: signalch 4328 4464 ; b27 +0: start 4329 4464 ; +2: check_eventqueue 4330 4464 ; +4: check_eventqueue 4331 4464 ; +6: 4332 4464 ; +8: generate_testoutput 4333 4464 ; +10: inspect_chained 4334 4464 ; +12: inspect_chained 4335 4464 ; +14: timermess 4336 4464 ; +16: timerscan 4337 4464 ; +18: timerscan 4338 4464 ; +20: generate_testoutput 4339 4464 ; +22: " - " 4340 4464 ; +24: " - " 4341 4464 \f 4341 4464 b.h50 w. 4342 4464 4342 4464 ; procedure remove(elem); 4343 4464 ; 4344 4464 ; removes a given element from its queue and leaves the element 4345 4464 ; linked to itself. 4346 4464 ; 4347 4464 ; call return 4348 4464 ; w0: - unchanged 4349 4464 ; w1: - next(elem) 4350 4464 ; w2: elem elem 4351 4464 ; w3: link link 4352 4464 4352 4464 h0: rl w1 x2 ; begin 4353 4464 rx w2 x2+2 ; prev(elem):= elem; 4354 4464 rs w1 x2 ; next(prev(elem)):= next(elem); 4355 4464 rx w2 x1+2 ; prev(next(elem)):= old prev(elem); 4356 4464 rs w2 x2 ; next(elem):= elem; 4357 4464 jl x3 ; end; 4358 4464 4358 4464 4358 4464 4358 4464 ; procedure link(head,elem); 4359 4464 ; 4360 4464 ; links the element to the end of the queue; 4361 4464 ; 4362 4464 ; call return 4363 4464 ; w0 - destroyed 4364 4464 ; w1 head head 4365 4464 ; w2 elem elem 4366 4464 ; w3 link old last(head) 4367 4464 4367 4464 4367 4464 h1: al w0 x3 ; begin 4368 4464 rl w3 x1+2 ; old prev:= last(head); 4369 4464 rs w2 x1+2 ; prev(head):= elem; 4370 4464 rs w2 x3+0 ; next(old prev):= elem; 4371 4464 rs w1 x2+0 ; next(elem):= head; 4372 4464 rs w3 x2+2 ; prev(elem):= old prev; 4373 4464 rl w3 0 ; 4374 4464 jl x3 ; end; 4375 4464 \f 4375 4464 4375 4464 ; procedure get_mess_ext(ref); 4376 4464 ; 4377 4464 ; returns a reference to the first free message buffer extension 4378 4464 ; or 0 if no extensions are available. the extension is removed from the chain. 4379 4464 ; 4380 4464 ; call return 4381 4464 ; w0: - destroyed 4382 4464 ; w1: - destroyed 4383 4464 ; w2: - ref or 0 4384 4464 ; w3: link link 4385 4464 4385 4464 b.j5 w. 4386 4464 h7: rl w1 b28 ; begin 4387 4464 rl w2 x1+a588 ; ref:= cur.ext2.buffer_extension_head; 4388 4464 sn w2 0 ; if ref <> 0 then 4389 4464 jl. j0. ; begin 4390 4464 rl w0 x2 ; cur.ext2.buffer_extension_head:= next(ref); 4391 4464 rs w0 x1+a588 ; 4392 4464 4392 4464 al w2 x2+2 ; ref:= ref+2; 4393 4464 ; end; 4394 4464 j0: jl x3 ; end; 4395 4464 e. 4396 4464 4396 4464 \f 4396 4464 ; procedure answer arrived(buf,ref); 4397 4464 ; 4398 4464 ; is called from procedure 'check_event_queue' when an answer appears in 4399 4464 ; the event queue and 'ref.open' is true, i. e. when a coroutine has 4400 4464 ; called 'cwaitanswer(buf)'. the coroutine is activated and the answer 4401 4464 ; descriptor is closed. 4402 4464 ; 4403 4464 ; call return 4404 4464 ; w0: - destroyed 4405 4464 ; w1: ref destroyed 4406 4464 ; w2: buf buf 4407 4464 ; w3: link link 4408 4464 4408 4464 b.j5 w. 4409 4464 c106: am (b27) ; begin 4410 4464 ds w3 +6 ; ext1(4,6):= (buf,link); 4411 4464 am (b28) ; 4412 4464 rl w3 +a544 ; 4413 4464 sn w3 0 ; if testoutput active 4414 4464 jl. j0. ; then generate testoutput(1<6); 4415 4464 jl. w3 h4. ; 4416 4464 3<22+1<6 ; 4417 4464 j0: al w0 0 ; 4418 4464 hs w0 x1 ; ref.open:= false; 4419 4464 rl w2 x1+2 ; corout:= ref.param1; 4420 4464 al w1 1 ; result:= ok; 4421 4464 rl w0 x2+a698 ; priority:= corout.priority; 4422 4464 jl. w3 c100. ; start(corout,priority,ok); 4423 4464 am (b27) ; 4424 4464 dl w3 +6 ; (buf,link):= ext1(4,6); 4425 4464 jl x3 ; end; 4426 4464 e. 4427 4464 4427 4464 \f 4427 4464 ; procedure central wait; 4428 4464 ; 4429 4464 ; central waiting point in coroutine system. checks the eventqueue 4430 4464 ; and schedules pending events. if the active queue is empty the 4431 4464 ; monitor procedure wait event is called otherwise the first co- 4432 4464 ; routine is started. if 'corout.user_exit' <> 0 a jump to 'user_exit' is 4433 4464 ; made with register contents: 4434 4464 ; w0: - 4435 4464 ; w1: - 4436 4464 ; w2: current_coroutine 4437 4464 ; w3: link 4438 4464 4438 4464 4438 4464 b.j5 4439 4464 w. 4440 4464 h2: ; begin 4441 4464 ; repeat 4442 4464 j0: jl. w3 h6. ; check event queue; 4443 4464 rl w2 b28 ; if active queue empty then 4444 4464 rl w3 x2+a546 ; begin 4445 4464 se w3 x2+a546 ; buf:= cur.ext2.last event; 4446 4464 jl. j1. ; wait event(buf,result); 4447 4464 rl w2 x2+a582 ; 4448 4464 jd 1<11+24 ; 4449 4464 jl. j0. ; 4450 4464 ; end; 4451 4464 j1: al w2 x3-2 ; until active queue not empty; 4452 4464 rs w2 (b28) ; corout:= first in active queue; 4453 4464 rl w1 x2+a720 ; if corout.user_exit <> 0 4454 4464 se w1 0 ; then jump to user_exit; 4455 4464 jl w3 x1 ; 4456 4464 rl w3 (b28) ; 4457 4464 dl w1 x3+a712 ; 4458 4464 rl w2 x3+a714 ; restart corout;; 4459 4464 jl (x3) ; end; 4460 4464 e. 4461 4464 \f 4461 4464 4461 4464 4461 4464 ; procedure check eventqueue; 4462 4464 ; 4463 4464 ; inspects the eventqueue starting at 'last event'('last event' = 0 4464 4464 ; if the queue must be inspected from the start). pending events 4465 4464 ; which have arrived after 'last event' are scheduled if 4466 4464 ; 'event descriptor.open' = true. the scheduling is performed by calling 4467 4464 ; either a 'cmon'-standard procedure (even procedure number in event 4468 4464 ; descriptor) or a user defined procedure (odd procedure number which 4469 4464 ; is used as index in the procedure table in process extension 2). 4470 4464 ; 4471 4464 4471 4464 ; a procedure ('user' or 'cmon') which is used for scheduling answers or messages 4472 4464 ; must return with w2=0 if the answer/message is removed from the event queue 4473 4464 ; - otherwise with w2='buf' ; i. e. the event queue must be inspected from the 4474 4464 ; start when an event is removed by a scheduling procedure. 4475 4464 4475 4464 ; exit to 'cmon'- or user-procedure with: 4476 4464 ; w0: - 4477 4464 ; w1: ref(event descriptor) 4478 4464 ; w2: buf 4479 4464 ; w3: link 4480 4464 4480 4464 b. j10 w. 4481 4464 h6: am (b27) ; begin 4482 4464 rs w3 +2 ; ext1(2):= link; 4483 4464 rl w3 b28 ; 4484 4464 rl w2 x3+a582 ; last_buf:= cur.ext2.last_event; 4485 4464 j0: jd 1<11+66 ; repeat 4486 4464 rl w3 b28 ; 4487 4464 sh w0 -1 ; test_event(last_buf,buf,result); 4488 4464 jl. j5. ; if result <> empty then 4489 4464 se w0 0 ; begin 4490 4464 jl. j2. ; if result = message 4491 4464 rl w1 x2+4 ; 4492 4464 ac w1 x1 ; 4493 4464 se w1 (b1) ; then ref:= 4494 4464 jl. j1. ; if buf.receiver = cur then cur.ext2.messdescr 4495 4464 rl w1 x3+a584 ; else buf.receiver.messdescr <* pseudoprocess *> 4496 4464 jl. j2. ; 4497 4464 j1: rl w1 x1+a60 ; else <* answer *> ref:= buf.ref; 4498 4464 j2: hl w0 x1 ; 4499 4464 sn w0 0 ; 4500 4464 jl. j0. ; if ref.open then 4501 4464 hl w0 x1+1 ; begin 4502 4464 sz w0 1 ; if even procedure number 4503 4464 jl. j3. ; then call cmonproc(buf,ref); 4504 4464 am (0) ; 4505 4464 jl w3 (130) ; 4506 4464 jl. j0. ; else 4507 4464 j3: ; begin <* odd procedure number *> 4508 4464 rl w3 x3+a586 ; <* use procedure number in event *> 4509 4464 hl w0 x1+1 ; <* descriptor as index in proce- *> 4510 4464 ls w0 +1 ; <* dure table in cur.ext2 *> 4511 4464 wa w0 x3 ; 4512 4464 am (0) ; 4513 4464 jl w3 (0) ; call userproc(buf,ref); 4514 4464 jl. j0. ; end; 4515 4464 ; end; 4516 4464 ; end; 4517 4464 ; until result = empty; 4518 4464 j5: sn w2 0 ; <* if 'last_buf' points at a message , 'last_event' 4519 4464 jl. j6. ; <* must be reset as the message may be regretted 4520 4464 rl w0 x2+4 ; <* before next scan. 4521 4464 se w0 0 ; 4522 4464 sz w0 -8 ; cur.ext2.last_event:= if last_buf points at message 4523 4464 al w2 0 ; then 0 4524 4464 j6: rs w2 x3+a582 ; else last_buf; 4525 4464 am (b27) ; link:= ext1(2); 4526 4464 jl (2) ; end; 4527 4464 e. 4528 4464 \f 4528 4464 4528 4464 4528 4464 ; procedure entry pass(priority); 4529 4464 ; 4530 4464 ; pending events are scheduled and calling coroutine is restarted 4531 4464 ; with the priority given in call. 4532 4464 ; 4533 4464 ; call return 4534 4464 ; w0: priority destroyed 4535 4464 ; w1: - destroyed 4536 4464 ; w2: - destroyed 4537 4464 ; w3: link current coroutine 4538 4464 4538 4464 b.j5 w. 4539 4464 c102: am (b28) ; begin 4540 4464 rs w3 (0) ; current_coroutine.ic:= link; 4541 4464 am (b28) ; 4542 4464 rl w3 +a544 ; 4543 4464 sn w3 0 ; if testoutput active 4544 4464 jl. j0. ; then generate testoutput(testkind); 4545 4464 jl. w3 h4. ; 4546 4464 3<22+1<2 ; 4547 4464 j0: rl w2 (b28) ; 4548 4464 rl w1 x2+a710 ; result:= current_coroutine.result; 4549 4464 jl. w3 c100. ; start(current_coroutine,priority,result); 4550 4464 jl. h2. ; central wait; 4551 4464 e. ; end; 4552 4464 \f 4552 4464 4552 4464 ; procedure entry inspect(priority,result); 4553 4464 ; 4554 4464 ; schedules pending events and checks if the active queue contains 4555 4464 ; coroutines with priority higher than the call parameter 'priority'. in 4556 4464 ; this case 'result' returns true (1). 4557 4464 ; 4558 4464 ; call return 4559 4464 ; w0: priority result 4560 4464 ; w1: - destroyed 4561 4464 ; w2: - destroyed 4562 4464 ; w3: link current coroutine 4563 4464 4563 4464 b.j5 w. 4564 4464 c103: am (b28) ; begin 4565 4464 rs w3 (0) ; current_coroutine.ic:= link; 4566 4464 am (b28) ; 4567 4464 rl w3 +a544 ; 4568 4464 sn w3 0 ; if testoutput is active then 4569 4464 jl. j0. ; generate testoutput(1<3); 4570 4464 jl. w3 h4. ; 4571 4464 3<22+1<3 ; 4572 4464 j0: rs w0 (b27) ; ext1(0):= priority; 4573 4464 jl. w3 h6. ; check_event_queue; 4574 4464 rl w0 (b27) ; priority:= ext1(0); 4575 4464 rl w3 b28 ; 4576 4464 rl w3 x3+a546 ; corout:= first in active queue; 4577 4464 sl w0 (x3-4) ; 4578 4464 am -1 ; result:= corout.prio > priority; 4579 4464 al w0 1 ; 4580 4464 rl w3 (b28) ; 4581 4464 jl (x3) ; end; 4582 4464 e. 4583 4464 4583 4464 \f 4583 4464 ; procedure entry start(corout,priority,result); 4584 4464 ; 4585 4464 ; removes the coroutine from its queue (normally the timer queue) and 4586 4464 ; inserts it in active queue according to the call parameter 'priority'. 4587 4464 ; the call parameter 'result' is returned in w0 of 4588 4464 ; the coroutine which is activated. 4589 4464 ; 4590 4464 ; call return 4591 4464 ; w0: priority destroyed 4592 4464 ; w1: result destroyed 4593 4464 ; w2: corout corout 4594 4464 ; w3: link current coroutine 4595 4464 4595 4464 b.j5 4596 4464 w. 4597 4464 c100: rs w3 (b27) ; begin 4598 4464 am (b28) ; 4599 4464 rl w3 +a544 ; 4600 4464 sn w3 0 ; if testoutput is active then 4601 4464 jl. j0. ; generate testoutput(1<0); 4602 4464 jl. w3 h4. ; 4603 4464 3<22+1<0 ; 4604 4464 j0: rs w1 x2+a710 ; corout.result:= result; 4605 4464 rs w0 x2+a698 ; corout.priority:= priority; 4606 4464 al w2 x2+2 ; 4607 4464 jl. w3 h0. ; remove(corout); 4608 4464 rl w1 0 ; 4609 4464 al w0 x2 ; 4610 4464 rl w2 b28 ; worse:= rear of active queue; 4611 4464 al w3 x2+a546 ; while worse.prio > prio and 4612 4464 al w1 x1+1 ; worse <> active queue head do 4613 4464 j1: rl w3 x3+2 ; worse:= prev(worse); 4614 4464 sn w3 x2+a546 ; 4615 4464 jl. j2. ; 'insert corout in the rear of 4616 4464 sh w1 (x3-4) ; other coroutines of the same 4617 4464 jl. j1. ; priority' 4618 4464 j2: rl w1 x3 ; 4619 4464 rl w2 0 ; 4620 4464 jl. w3 h1. ; link(worse,corout); 4621 4464 al w2 x2-2 ; 4622 4464 4622 4464 rl w3 (b28) ; 4623 4464 am (b27) ; 4624 4464 jl (0) ; end; 4625 4464 e. 4626 4464 4626 4464 \f 4626 4464 ; procedure entry wait(timer,result); 4627 4464 ; 4628 4464 ; calling coroutine is suspended for max 'timer' seconds. 4629 4464 ; 'timer' = 0 indicates no timeout. the return parameter 'result' 4630 4464 ; indicates whether the coroutine was started by timeout or by 4631 4464 ; the arrival of an internal or external event. 4632 4464 ; 4633 4464 ; call return 4634 4464 ; w0: timer result 4635 4464 ; w1: - destroyed 4636 4464 ; w2: - - 4637 4464 ; w3 link current coroutine 4638 4464 4638 4464 b.j5 4639 4464 w. 4640 4464 c101: am (b28) ; begin 4641 4464 rs w3 (0 ) ; current coroutine.return:= link; 4642 4464 am (b28) ; 4643 4464 rl w3 +a544 ; 4644 4464 sn w3 0 ; if testoutput active then 4645 4464 jl. j0. ; generate testoutput(1<1); 4646 4464 jl. w3 h4. ; 4647 4464 3<22+1<1 ; 4648 4464 j0: rl w2 (b28) ; current coroutine.timer:= timer; 4649 4464 rs w0 x2+a706 ; 4650 4464 al w2 x2+2 ; 4651 4464 jl. w3 h0. ; remove(current coroutine); 4652 4464 rl w3 b28 ; 4653 4464 al w1 x3+a552 ; 4654 4464 jl. w3 h1. ; link(timer queue head,current coroutine); 4655 4464 jl. h2. ; central wait; 4656 4464 ; end; 4657 4464 e. 4658 4464 4658 4464 \f 4658 4464 ; procedure entry csendmessage(mess,name,buf); 4659 4464 ; 4660 4464 ; allocates a message buffer extension and prepares it for cwaitanswer. 4661 4464 ; then calls sendmessage. 4662 4464 ; 4663 4464 ; return parameter 'buf': 0 buffer claims exceeded 4664 4464 ; 1 no free extensions 4665 4464 ; >1 message buffer address 4666 4464 ; 4667 4464 ; call return 4668 4464 ; w0: - destroyed 4669 4464 ; w1: mess destroyed 4670 4464 ; w2: name buffer address (or 0 or 1) 4671 4464 ; w3: link current coroutine 4672 4464 4672 4464 b.j5,i5 w. 4673 4464 c104: am (b28) ; begin 4674 4464 rs w3 (0) ; current_coroutine.ic:= link; 4675 4464 am (b28) ; 4676 4464 rl w3 +a544 ; 4677 4464 sn w3 0 ; 4678 4464 jl. j0. ; if testoutput active 4679 4464 jl. w3 h4. ; then generate_testoutput(1<4); 4680 4464 3<22+1<4 ; 4681 4464 j0: ds w2 (b27) ; 4682 4464 jl. w3 h7. ; get_mess_ext(ref); 4683 4464 sn w2 0 ; if ref <> 0 <* extension available *> then 4684 4464 jl. j1. ; begin 4685 4464 rl. w0 i0. ; <* initialize answer descriptor *> 4686 4464 rs w0 x2 ; ref.open:= false; ref.proc:= 12; 4687 4464 rl w3 b27 ; 4688 4464 rs w2 x3+2 ; ext1(2):= ref; 4689 4464 rl w1 x3-2 ; 4690 4464 rl w3 x3 ; send message(mess,name,buf,ref); 4691 4464 jd 1<11+16 ; 4692 4464 se w2 0 ; if buffer claims exceeded 4693 4464 jl. j2. ; then release message buffer extension; 4694 4464 am (b27) ; 4695 4464 rl w1 (+2) ; 4696 4464 rl w3 b28 ; 4697 4464 al w0 x1-2 ; 4698 4464 rx w0 x3+a588 ; 4699 4464 rs w0 x1-2 ; 4700 4464 jl. j2. ; 4701 4464 j1: al w2 1 ; end 4702 4464 j2: rl w3 (b28) ; else buf:= 1; <* no free extensions *> 4703 4464 jl (x3) ; end; 4704 4464 4704 4464 i0: 0<12+12 ; answer descriptor init (open=false,proc='answer_arrived') 4705 4464 e. 4706 4464 4706 4464 \f 4706 4464 ; procedure entry cwaitanswer(buf,timer,result); 4707 4464 ; 4708 4464 ; prepares the message buffer extension for receiving the answer. if 4709 4464 ; the buffer has been answered, 'last_event' is reset as the buffer 4710 4464 ; may have been skipped during an earlier inspection of the event queue. 4711 4464 ; the coroutine waits for max. 'timer' seconds for the answer. when the 4712 4464 ; coroutine is restarted the action depends on 'result': 4713 4464 ; 4714 4464 ; result = timeout : the answer descriptor is closed 4715 4464 ; 4716 4464 ; result = answer arrived : the answer is received in the answer 4717 4464 ; area in process extension 2 and the message 4718 4464 ; buffer extension is released. 4719 4464 ; 4720 4464 ; call return 4721 4464 ; w0: timer result (timeout:0,wait_answer result:1,2,3,4,5) 4722 4464 ; w1: - answer area in ext2 if result <> timeout 4723 4464 ; w2: buf buf 4724 4464 ; w3: link current coroutine 4725 4464 4725 4464 b.j10 w. 4726 4464 c105: rs w3 (b27) ; begin 4727 4464 am (b28) ; 4728 4464 rl w3 +a544 ; 4729 4464 sn w3 0 ; 4730 4464 jl. j0. ; if testoutput active 4731 4464 jl. w3 h4. ; then generate_testoutput(1<5); 4732 4464 3<22+1<5 ; 4733 4464 j0: rl w3 (b28) ; 4734 4464 rl w1 (b27) ; current_coroutine.return:= link; 4735 4464 ds w2 x3+a724 ; current_coroutine.buf:= buf; 4736 4464 rs w0 (b27) ; ext1(0):= timer; 4737 4464 rl w1 x2-2 ; with buf.ref do 4738 4464 al w0 1 ; begin 4739 4464 hs w0 x1 ; open:= true; 4740 4464 rs w3 x1+2 ; corout:= current_coroutine; 4741 4464 ; end; 4742 4464 rl w0 x2+4 ; 4743 4464 sz w0 -8 ; if buf.state = answer pending 4744 4464 jl. j1. ; then last_event:= 0; <* inspect from start *> 4745 4464 al w0 0 ; 4746 4464 am (b28) ; 4747 4464 rs w0 +a582 ; 4748 4464 j1: rl w0 (b27) ; timer:= ext1(0); 4749 4464 jl. w3 c101. ; wait(timer,result); 4750 4464 rl w2 x3+a724 ; buf:= current_coroutine.buf; 4751 4464 rl w1 x2-2 ; ref:= buf.ref; 4752 4464 se w0 0 ; if result = timeout 4753 4464 jl. j2. ; then ref.open:= false 4754 4464 hs w0 x1 ; 4755 4464 jl. j4. ; else 4756 4464 j2: ; begin <* result = answer arrived *> 4757 4464 rl w3 b28 ; release message buffer extension; 4758 4464 al w0 x1-2 ; 4759 4464 rx w0 x3+a588 ; 4760 4464 rs w0 x1-2 ; 4761 4464 se w2 (x3+a582) ; 4762 4464 jl. j3. ; 4763 4464 al w0 0 ; if buf = last_event then last_event:= 0; 4764 4464 rs w0 x3+a582 ; 4765 4464 j3: al w1 x3+a590 ; 4766 4464 jd 1<11+18 ; wait answer(buf,cur.ext2.answer_area); 4767 4464 j4: rl w3 (b28) ; end; 4768 4464 jl (x3+a722) ; end; 4769 4464 e. ; end; 4770 4464 4770 4464 \f 4770 4464 ; procedure entry signal binary(sem); 4771 4464 ; procedure entry signal(sem); 4772 4464 ; 4773 4464 ; call return 4774 4464 ; w0: - destroyed 4775 4464 ; w1: - destroyed 4776 4464 ; w2: sem destroyed 4777 4464 ; w3: link current coroutine 4778 4464 4778 4464 b.j5 w. 4779 4464 c107: am 1 ; signal_binary: 4780 4464 c108: al w0 0 ; signal: 4781 4464 am (b28) ; begin 4782 4464 rs w3 (0) ; 4783 4464 am (b28) ; 4784 4464 rl w3 +a544 ; 4785 4464 sn w3 0 ; if testoutput active 4786 4464 jl. j0. ; then generate_testoutput(1<7); 4787 4464 jl. w3 h4. ; 4788 4464 3<22+1<7 ; 4789 4464 j0: rl w1 x2+4 ; with sem do 4790 4464 al w3 x1+1 ; begin 4791 4464 se w0 0 ; count:= count+1; 4792 4464 la w3 0 ; if binary 4793 4464 rs w3 x2+4 ; then count:= count and 1; 4794 4464 sl w1 0 ; if count <= 0 then 4795 4464 jl. j1. ; begin 4796 4464 rl w2 x2 ; corout:= next(sem); 4797 4464 jl. w3 h0. ; remove(corout); 4798 4464 al w2 x2+6 ; 4799 4464 rl w0 x2+a698 ; priority:= corout.prio; 4800 4464 al w1 1 ; result:= ok; 4801 4464 jl. w3 c100. ; start(corout,priority,result); 4802 4464 j1: rl w3 (b28) ; end; 4803 4464 jl (x3) ; end; 4804 4464 e. ; end; 4805 4464 4805 4464 \f 4805 4464 ; procedure entry wait_semaphore(sem); 4806 4464 ; 4807 4464 ; call return 4808 4464 ; w0: - destroyed 4809 4464 ; w1: - destroyed 4810 4464 ; w2: sem destroyed 4811 4464 ; w3: link current coroutine 4812 4464 4812 4464 b.j5 w. 4813 4464 c109: am (b28) ; begin 4814 4464 rs w3 (0) ; 4815 4464 am (b28) ; 4816 4464 rl w3 +a544 ; 4817 4464 sn w3 0 ; if testoutput active 4818 4464 jl. j0. ; then generate_testoutput(1<8); 4819 4464 jl. w3 h4. ; 4820 4464 3<22+1<8 ; 4821 4464 j0: rl w1 x2+4 ; with sem do 4822 4464 al w1 x1-1 ; begin 4823 4464 rs w1 x2+4 ; count:= count-1; 4824 4464 rl w3 (b28) ; 4825 4464 sl w1 0 ; if count < 0 then 4826 4464 jl (x3) ; begin 4827 4464 rl w1 x3 ; 4828 4464 rs w1 x3+a722 ; current_coroutine.return:= link; 4829 4464 al w1 x2 ; head:= sem.coroutine_queue_head; 4830 4464 al w2 x3-6 ; elem:= current_coroutine.sem_queue_elem; 4831 4464 jl. w3 h1. ; link(head,elem); 4832 4464 al w0 0 ; timer:= 0 <* no timeout *> 4833 4464 jl. w3 c101. ; wait(timer); 4834 4464 rl w3 (b28) ; end; 4835 4464 jl (x3+a722) ; end with; 4836 4464 e. ; end; 4837 4464 4837 4464 \f 4837 4464 ; procedure entry signal_chained(sem,oper); 4838 4464 ; 4839 4464 ; signals an operation to a chained semaphore. if the coroutine queue of 4840 4464 ; the semaphore contains a coroutine which is waiting for an operation 4841 4464 ; of this type,the coroutine is started. otherwise the operation is 4842 4464 ; queued to the semaphore. 4843 4464 ; 4844 4464 ; two reserved types exist: 4845 4464 ; 1<0: message 4846 4464 ; 1<1: answer 4847 4464 ; 4848 4464 ; call return 4849 4464 ; w0: - destroyed 4850 4464 ; w1: operation destroyed 4851 4464 ; w2: semaphore destroyed 4852 4464 ; w3: link current coroutine 4853 4464 4853 4464 b.j10 w. 4854 4464 c110: am (b27) ; begin 4855 4464 rs w3 -2 ; 4856 4464 am (b28) ; 4857 4464 rl w3 +a544 ; 4858 4464 sn w3 0 ; 4859 4464 jl. j0. ; if testoutput active 4860 4464 jl. w3 h4. ; then generate_testoutput(1<9); 4861 4464 3<22+1<9 ; 4862 4464 j0: rl w3 x2 ; head:= sem.coroutine_queue_head; 4863 4464 j1: sn w3 x2 ; corout:= next(head); found:= false; 4864 4464 jl. j4. ; while corout <> head and -, found do 4865 4464 rl w0 x3-a694+a708; if logand(corout.mask,oper.type) <> 0 then 4866 4464 la w0 x1+4 ; begin 4867 4464 se w0 0 ; 4868 4464 jl. j3. ; found:= true; 4869 4464 rl w3 x3 ; 4870 4464 jl. j1. ; 4871 4464 j3: rs w1 x3-a694+a724; corout.latop:= operation; 4872 4464 rl w0 x1+4 ; type:= oper.type; 4873 4464 al w2 x3 ; 4874 4464 jl. w3 h0. ; remove(corout); 4875 4464 al w2 x2-a694 ; 4876 4464 rl w1 0 ; result:= type; 4877 4464 rl w0 x2+a698 ; priority:= corout.prio; 4878 4464 jl. w3 c100. ; start(corout,priority,result); 4879 4464 jl. j5. ; end 4880 4464 ; else corout:= next(corout); 4881 4464 j4: rx w2 2 ; if -,found 4882 4464 al w1 x1+4 ; then link(sem.operation_queue,oper); 4883 4464 jl. w3 h1. ; 4884 4464 j5: rl w3 (b28) ; 4885 4464 am (b27) ; 4886 4464 jl (-2) ; end; 4887 4464 e. 4888 4464 4888 4464 \f 4888 4464 ; procedure entry inspect_chained(sem,mask,oper,result); 4889 4464 ; 4890 4464 ; checks if 'sem_operation_queue' contains an operation which matches 'mask'. 4891 4464 ; if no matching operation is found, 'oper' returns = 0, 4892 4464 ; otherwise 'oper' refers to the first matching operation. 4893 4464 ; 'result' returns 'true' (1) if the active queue contains coroutines of 4894 4464 ; priorities higher than the priority of calling coroutine. 4895 4464 ; 4896 4464 ; call return 4897 4464 ; w0: - (result= 0,1) 4898 4464 ; w1: mask oper or 0 4899 4464 ; w2: sem sem 4900 4464 ; w3: link current coroutine 4901 4464 4901 4464 b.j10 w. 4902 4464 c111: am (b28) ; begin 4903 4464 rs w3 (0) ; 4904 4464 am (b28) ; 4905 4464 rl w3 +a544 ; 4906 4464 sn w3 0 ; if testoutput active 4907 4464 jl. j0. ; then generate_testoutput(1<10); 4908 4464 jl. w3 h4. ; 4909 4464 3<22+1<10 ; 4910 4464 j0: am (b27) ; 4911 4464 rs w2 +12 ; save(sem); 4912 4464 al w0 x1 ; 4913 4464 rl w1 x2+4 ; head:= sem.operation_queue_head; 4914 4464 j1: ; oper:= next(head); found:= false; 4915 4464 sn w1 x2+4 ; while oper <> head and -,found do 4916 4464 jl. j3. ; if logand(oper.type,mask) <> 0 4917 4464 rl w3 x1+4 ; then found:= true 4918 4464 la w3 0 ; else oper:= next(oper); 4919 4464 se w3 0 ; 4920 4464 jl. j4. ; 4921 4464 rl w1 x1 ; 4922 4464 jl. j1. ; 4923 4464 j3: al w1 0 ; if -,found then oper:= 0; 4924 4464 j4: rl w3 (b28) ; 4925 4464 rl w0 x3+a698 ; priority:= current_coroutine.prio; 4926 4464 rl w2 b28 ; 4927 4464 rl w2 x2+a546 ; corout:= first in active queue; 4928 4464 sh w0 (x2-4) ; 4929 4464 am -1 ; 4930 4464 al w0 1 ; result:= corout.prio > priority; 4931 4464 am (b27) ; 4932 4464 rl w2 +12 ; 4933 4464 jl (x3) ; end; 4934 4464 e. 4935 4464 4935 4464 \f 4935 4464 ; procedure entry wait_chained(sem,mask,timer,oper); 4936 4464 ; 4937 4464 ; if 'sem.operation_queue' contains an operation 4938 4464 ; which matches 'mask', the operation is removed from the queue . a 'pass' 4939 4464 ; is executed if the active queue contains coroutines of priorities higher 4940 4464 ; than the priority of calling coroutine. if no matching operation is found 4941 4464 ; pending events are scheduled and the calling coroutine waits for max. 'timer' 4942 4464 ; seconds for an operation to arrive. 4943 4464 ; 4944 4464 ; if the operation contains a message or an answer ('oper.type' = 1<0 or 1<1 , 4945 4464 ; resp ) , the buffer contents is copied to the common message-answer area in 4946 4464 ; process extension 2. a buffer containing an answer is removed from the event 4947 4464 ; queue by 'waitanswer'. 4948 4464 ; 4949 4464 ; 4950 4464 ; call return 4951 4464 ; w0: timer result ( 0(timeout) or oper.type) 4952 4464 ; w1: mask oper (undefined if result = timeout) 4953 4464 ; w2: sem destr. 4954 4464 ; w3: link current_coroutine 4955 4464 4955 4464 b.j10 w. 4956 4464 c112: rs w3 (b27) ; begin 4957 4464 am (b28) ; 4958 4464 rl w3 +a544 ; 4959 4464 sn w3 0 ; if testoutput active 4960 4464 jl. j0. ; then generate_testoutput(1<11); 4961 4464 jl. w3 h4. ; 4962 4464 3<22+1<11 ; 4963 4464 j0: rx w1 (b27) ; 4964 4464 rl w3 (b28) ; 4965 4464 rs w1 x3+a722 ; current_coroutine.return:= link; 4966 4464 rx w1 (b27) ; current_coroutine.waitch_mask:= mask; 4967 4464 ds w1 x3+a708 ; current_coroutine.timer:= timer; 4968 4464 jl. w3 c111. ; inspect_chained(sem,mask,oper,result); 4969 4464 se w1 0 ; if oper = 0 then 4970 4464 jl. j1. ; begin <* wait in semaphore queue *> 4971 4464 al w1 x2 ; head:= sem.coroutine_queue_head; 4972 4464 al w2 x3+a694 ; elem:= current_coroutine.sem_queue_elem; 4973 4464 jl. w3 h1. ; link(head,elem); 4974 4464 rl w0 x2-a694+a706 ; timer:= current_coroutine.timer; 4975 4464 jl. w3 c101. ; wait(timer,result); 4976 4464 se w0 0 ; if result = timeout then 4977 4464 jl. j3. ; begin 4978 4464 rs w0 x3+a710 ; current_coroutine.result:= timeout; 4979 4464 al w2 x3+a694 ; elem:= current_coroutine.sem_queue_elem; 4980 4464 jl. w3 h0. ; remove(elem); 4981 4464 jl. j6. ; goto exit; 4982 4464 ; end; 4983 4464 ; end; 4984 4464 j1: rs w1 x3+a724 ; current_coroutine.latop:= oper; 4985 4464 rl w2 x1+4 ; 4986 4464 rs w2 x3+a710 ; current_coroutine.result:= oper.type; 4987 4464 al w2 x1 ; 4988 4464 jl. w3 h0. ; remove(oper); 4989 4464 rl w3 (b28) ; if waiting <* coroutines of higher 4990 4464 sn w0 0 ; priority in active queue *> then 4991 4464 jl. j2. ; begin 4992 4464 rl w0 x3+a698 ; priority:= current_coroutine.prio; 4993 4464 jl. w3 c102. ; pass(priority); 4994 4464 ; end; 4995 4464 j2: rl w0 x3+a710 ; 4996 4464 j3: sz w0 -4 ; if oper.type = message or answer then 4997 4464 jl. j6. ; begin 4998 4464 rl w2 x3+a724 ; oper:= current_coroutine.latop; 4999 4464 rl w3 b28 ; 5000 4464 rl w2 x2+8 ; buf:= oper.buf; 5001 4464 se w0 1<1 ; if oper.type = answer then 5002 4464 jl. j5. ; begin 5003 4464 se w2 (x3+a582) ; 5004 4464 jl. j4. ; if buf = last_event 5005 4464 al w0 0 ; then last_event:= 0; 5006 4464 rs w0 x3+a582 ; 5007 4464 j4: al w1 x3+a590 ; area:= common message-answer area; 5008 4464 jd 1<11+18 ; waitanswer(buf,area); 5009 4464 jl. j6. ; end 5010 4464 j5: al w1 x3+a590 ; else 5011 4464 dl w0 x2+10 ; begin <* message *> 5012 4464 ds w0 x1+2 ; 5013 4464 dl w0 x2+14 ; 5014 4464 ds w0 x1+6 ; 5015 4464 dl w0 x2+18 ; <* copy to common massage-answer area *> 5016 4464 ds w0 x1+10 ; 5017 4464 dl w0 x2+22 ; 5018 4464 ds w0 x1+14 ; end; 5019 4464 ; end; 5020 4464 j6: rl w3 (b28) ; exit: 5021 4464 rl w0 x3+a710 ; result:= current_coroutine.result; 5022 4464 rl w1 x3+a724 ; oper:= current_coroutine.latop; <* undef if timeout *> 5023 4464 jl (x3+a722) ; 5024 4464 e. ; end; 5025 4464 5025 4464 \f 5025 4464 ; procedure entry sem_sendmessage(name,message,oper,sem.result); 5026 4464 ; 5027 4464 ; sends a massage to the process given by 'name'. when the answer arrives 5028 4464 ; it is signalled to the chained semaphore 'sem'. the calling coroutine must 5029 4464 ; provide the operation 'oper' which is used as: 5030 4464 ; 5031 4464 ; 1) message_buffer_extension and 2) answer_operation(sem_answer_proc) 5032 4464 ; -6 (next operation) oper +0 next operation 5033 4464 ; -4 (prev operation) +2 prev operation 5034 4464 ; -2 (type) +4 type=answer(1<1) 5035 4464 ; ext. +0 open,'sem_answer_proc' +6 - 5036 4464 ; +2 answer_sem +8 buffer address 5037 4464 ; 5038 4464 ; 5039 4464 ; call return 5040 4464 ; w0: sem destr. 5041 4464 ; w1: params destr. 5042 4464 ; w2: oper buffer addres ( or 0 = claims exceeded ) 5043 4464 ; w3: link current coroutine 5044 4464 ; 5045 4464 ; 'params' points at a parameter area containing: 5046 4464 ; 5047 4464 ; params +0: name(1) 5048 4464 ; +2: name(2) 5049 4464 ; +4: name(3) 5050 4464 ; +6: name(4) 5051 4464 ; +8: name table address 5052 4464 ; +10: mess(1) 5053 4464 ; +12: mess(2) 5054 4464 ; etc. 5055 4464 5055 4464 b.j5,i5 w. 5056 4464 c113: am (b28) ; begin 5057 4464 rs w3 (0) ; 5058 4464 am (b28) ; 5059 4464 rl w3 +a544 ; 5060 4464 sn w3 0 ; if testoutput active 5061 4464 jl. j0. ; then generate_testoutput(1<12); 5062 4464 jl. w3 h4. ; 5063 4464 3<22+1<12 ; 5064 4464 j0: rs w0 (b27) ; with oper.answer_descriptor do 5065 4464 rl. w0 i0. ; begin 5066 4464 rs w0 x2+6 ; proc:= sem_answerproc; 5067 4464 rl w0 (b27) ; open:= true; 5068 4464 rs w0 x2+8 ; answer_sem:= sem; 5069 4464 al w3 x1 ; end; 5070 4464 al w1 x1+10 ; name_address:= params; 5071 4464 ; message_address:= params+10; 5072 4464 al w2 x2+6 ; ref:= oper.answer_descriptor; 5073 4464 jd 1<11+16 ; sendmessage(name_addres,message_address,ref,result); 5074 4464 rl w3 (b28) ; 5075 4464 jl (x3) ; end; 5076 4464 5076 4464 i0: 1<12+28 ; answer_descriptor init; 5077 4464 5077 4464 e. 5078 4464 5078 4464 \f 5078 4464 ; procedure sem_answer_proc(ref,buf); 5079 4464 ; 5080 4464 ; this procedure is called from procedure 'check_event_queue' when an 5081 4464 ; answer to a message, sent by 'sem_sendmessage, has arrived. 'ref' 5082 4464 ; contains the address of the answer_descriptor and 'buf' contains the 5083 4464 ; message buffer address. the answer is signalled to the chained semaphore 5084 4464 ; given in answer_descriptor. 5085 4464 ; 5086 4464 ; call return 5087 4464 ; w0: - destr. 5088 4464 ; w1: ref destr. 5089 4464 ; w2: buf buf 5090 4464 ; w3: link link 5091 4464 5091 4464 b.j5 w. 5092 4464 c114: am (b27) ; begin 5093 4464 ds w3 +6 ; 5094 4464 am (b28) ; 5095 4464 rl w3 +a544 ; 5096 4464 sn w3 0 ; if testoutput active 5097 4464 jl. j0. ; then generate_testoutput(1<13); 5098 4464 jl. w3 h4. ; 5099 4464 3<22+1<13 ; 5100 4464 j0: al w0 0 ; with ref do 5101 4464 hs w0 x1 ; begin 5102 4464 al w0 1<1 ; open:= false; 5103 4464 rs w0 x1-2 ; type:= answer; 5104 4464 rx w2 x1+2 ; sem:= answer_sem; 5105 4464 al w1 x1-6 ; buffer:= buf; 5106 4464 jl. w3 c110. ; signal_chained(sem,operation); 5107 4464 am (b27) ; end; 5108 4464 dl w3 +6 ; 5109 4464 jl x3 ; end; 5110 4464 e. 5111 4464 5111 4464 \f 5111 4464 ; procedure message_received(buf,ref); 5112 4464 ; 5113 4464 ; this procedure is called from 'check_event_queue' when a message is 5114 4464 ; received and mess_descr.proc = 'message_received'. the message descriptor 5115 4464 ; must contain an operation and the address of a chained semaphore. 5116 4464 ; 5117 4464 ; message_descriptor message_operation 5118 4464 ; -6: next operation - 5119 4464 ; -4: prev operation - 5120 4464 ; -2: type type = message (1<0) 5121 4464 ; mess_descr +0: open,'message_received' - 5122 4464 ; +2: semaphore address buffer address 5123 4464 ; 5124 4464 ; 5125 4464 ; call return 5126 4464 ; w0: - destr. 5127 4464 ; w1: ref destr. 5128 4464 ; w2: buf 0 (the message buffer is removed) 5129 4464 ; w3: link link 5130 4464 5130 4464 b.j5 w. 5131 4464 c115: am (b27) ; begin 5132 4464 rs w3 +6 ; 5133 4464 am (b28) ; 5134 4464 rl w3 +a544 ; 5135 4464 sn w3 0 ; if testoutput active 5136 4464 jl. j0. ; then generate_testoutput(1<14); 5137 4464 jl. w3 h4. ; 5138 4464 3<22+1<14 ; 5139 4464 j0: jd 1<11+26 ; getevent(buf); 5140 4464 al w0 0 ; with ref do 5141 4464 hs w0 x1 ; begin 5142 4464 al w0 1<0 ; open:= false; <* the message class must be 5143 4464 ; explicitly opened by a 5144 4464 ; receiving coroutine *> 5145 4464 rs w0 x1-2 ; oper.type:= message; 5146 4464 rx w2 x1+2 ; oper.buffer:= buf; 5147 4464 al w1 x1-6 ; sem:= message_sem; 5148 4464 jl. w3 c110. ; signal_chained(sem,oper); 5149 4464 am (b27) ; end; 5150 4464 rl w3 +6 ; 5151 4464 al w2 0 ; buf:= 0; <* has been removed *> 5152 4464 jl x3 ; end; 5153 4464 e. 5154 4464 5154 4464 \f 5154 4464 ; procedure entry timer_message; 5155 4464 ; 5156 4464 ; sends a delay-message to 'clock'. 5157 4464 ; 5158 4464 ; call return 5159 4464 ; w0: - unchanged 5160 4464 ; w1: - destr. 5161 4464 ; w2: - buf or 0 5162 4464 ; w3: link current_coroutine 5163 4464 5163 4464 b.j5 w. 5164 4464 c116: am (b27) ; begin 5165 4464 rs w3 +14 ; 5166 4464 am (b28) ; 5167 4464 rl w3 +a544 ; 5168 4464 sn w3 0 ; if testoutput active 5169 4464 jl. j0. ; then generate_testoutput(1<15); 5170 4464 jl. w3 h4. ; 5171 4464 3<22+1<15 ; 5172 4464 j0: rl w3 b28 ; 5173 4464 al w1 x3+a626 ; mess:= cur.ext2.delaymess; 5174 4464 al w2 x3+a630 ; ref:= cur.ext2.answer_descr; 5175 4464 al w3 x3+a616 ; name:= <:clock:>; 5176 4464 jd 1<11+16 ; sendmessage(name,mess,ref,result); 5177 4464 rl w3 (b28) ; 5178 4464 am (b27) ; 5179 4464 rl w1 +14 ; 5180 4464 jl x1 ; end; 5181 4464 e. 5182 4464 5182 4464 \f 5182 4464 ; procedure timerscan(ref,buf); 5183 4464 ; 5184 4464 ; this procedure is called from 'check_event_queue' when an answer arrives 5185 4464 ; from 'clock'. the timer queue is inspected and coroutines which time out 5186 4464 ; are started with result = timeout. after the inspection a delay-message is 5187 4464 ; sent to 'clock'. 5188 4464 ; 5189 4464 ; call return 5190 4464 ; w0: - destr. 5191 4464 ; w1: ref destr. 5192 4464 ; w2: buf 0 (the message buffer is removed) 5193 4464 ; w3: link link 5194 4464 5194 4464 b.j5,i5 w. 5195 4464 c117: am (b27) ; begin 5196 4464 rs w3 +16 ; ext1(16):= link; 5197 4464 am (b28) ; 5198 4464 rl w3 +a544 ; 5199 4464 sn w3 0 ; if testoutput active 5200 4464 jl. j0. ; then generate_test_output(1<16); 5201 4464 jl. w3 h4. ; 5202 4464 3<22+1<16 ; 5203 4464 j0: rl w3 b28 ; 5204 4464 al w1 x3+a566 ; <* release messagebuffer *> 5205 4464 jd 1<11+18 ; wait_answer(cur.ext2.test_mess_area,buf); 5206 4464 j4: ; 5207 4464 al w2 x3+a552 ; corout:= first in timer queue; 5208 4464 j1: rl w2 x2 ; while corout <> timer queue head do 5209 4464 j3: sn w2 x3+a552 ; begin 5210 4464 jl. j2. ; corout:= next(corout); 5211 4464 rl w1 x2+4 ; with corout do 5212 4464 sh w1 0 ; begin 5213 4464 jl. j1. ; if timer > 0 then 5214 4464 al w1 x1-1 ; begin 5215 4464 rs w1 x2+4 ; 5216 4464 se w1 0 ; timer:= timer-1; 5217 4464 jl. j1. ; if timer = 0 5218 4464 rl w0 x2 ; then start(corout,prio,timeout); 5219 4464 am (b27) ; 5220 4464 rs w0 +18 ; 5221 4464 al w2 x2-2 ; 5222 4464 rl w0 x2+a698 ; end; 5223 4464 al w1 0 ; end; 5224 4464 jl. w3 c100. ; 5225 4464 am (b27) ; 5226 4464 rl w2 +18 ; 5227 4464 rl w3 b28 ; 5228 4464 jl. j3. ; end while; 5229 4464 j2: jl. w3 c116. ; timer_message; 5230 4464 am (b27) ; 5231 4464 rl w3 +16 ; link:= ext1(16); 5232 4464 al w2 0 ; buf:= 0; <* has been removed *> 5233 4464 jl x3 ; end; 5234 4464 e. 5235 4464 5235 4464 \f 5235 4464 ; procedure entry cregretmessage(buf); 5236 4464 ; 5237 4464 ; this procedure is used to regret a message sent by csendmessage, i. e. the 5238 4464 ; monitor procedure 'regretmessage' is called and the corresponding message 5239 4464 ; buffer extension is released. 5240 4464 ; 5241 4464 ; call return 5242 4464 ; w0: - destr. 5243 4464 ; w1: - destr. 5244 4464 ; w2: buf buf 5245 4464 ; w3: link current_coroutine 5246 4464 5246 4464 b.j5 w. 5247 4464 c118: am (b28) ; begin 5248 4464 rs w3 (0) ; 5249 4464 am (b28) ; 5250 4464 rl w3 +a544 ; 5251 4464 sn w3 0 ; if testoutput active 5252 4464 jl. j0. ; then generate test_output(1<17); 5253 4464 jl. w3 h4. ; 5254 4464 3<22+1<17 ; 5255 4464 j0: jd 1<11+82 ; regretmessage(buf); 5256 4464 rl w1 x2-2 ; ref:= buf.ref; 5257 4464 rl w3 b28 ; ext:= next(message_buffer_ext_head); 5258 4464 al w0 x1-2 ; next(message_buffer_ext_head):= ref; 5259 4464 rx w0 x3+a588 ; next(ref):= ext; 5260 4464 rs w0 x1-2 ; 5261 4464 rl w3 (b28) ; 5262 4464 jl (x3) ; end; 5263 4464 e. 5264 4464 \f 5264 4464 5264 4464 5264 4464 ; procedure entry testout 5265 4464 ; 5266 4464 ; 5267 4464 ; this procedure creates a user test record defined by the registers 5268 4464 ; as follows: 5269 4464 ; 5270 4464 ; call return 5271 4464 ; w0: testrecord ident unch. 5272 4464 ; w1: start address unch. 5273 4464 ; w2: no_of_halfwords unch. 5274 4464 ; w3: link current coroutine 5275 4464 5275 4464 b.j5 w. 5276 4464 c119: am (b28) ; begin 5277 4464 rs w3 (0) ; 5278 4464 am (b28) ; if test output active then 5279 4464 rl w3 +a544 ; 5280 4464 sn w3 0 ; 5281 4464 jl. j0. ; 5282 4464 jl. w3 h4. ; generate testoutput(1<18) 5283 4464 3<22+1<18; 5284 4464 j0: rl w3 (b28) ; 5285 4464 jl (x3) ; end; 5286 4464 5286 4464 e. 5287 4464 \f 5287 4464 5287 4464 5287 4464 ; procedure generate testoutput(testkind); 5288 4464 ; 5289 4464 ; this procedure creates a testrecord or initiates the creation of a test 5290 4464 ; record as follows: 5291 4464 ; 5292 4464 ; 1) if word 128 in monitor table is set ( <> 0 ) a message defining the 5293 4464 ; test record is sent to the coroutine test output process. 5294 4464 ; 5295 4464 ; 2) otherwise a test record is written in the cyclical test output buffer. 5296 4464 ; formats in the cyclical buffer: 5297 4464 ; 5298 4464 ; user test record coroutine function (signal etc.) 5299 4464 ; +0 testkind testkind 5300 4464 ; +2 time1 time1 5301 4464 ; +4 time2 time2 5302 4464 ; +6 user_ident,length w0 5303 4464 ; +8 test information w1 5304 4464 ; +10 - " - w2 5305 4464 ; +12 - " - coroutine ident 5306 4464 ; +14 etc. address of current coroutine 5307 4464 5307 4464 ; 5308 4464 ; testkind values: 5309 4464 ; 1<0 : start 5310 4464 ; 1<1 : wait 5311 4464 ; 1<2 : pass 5312 4464 ; 1<3 ; inspect 5313 4464 ; 1<4 : csendmessage 5314 4464 ; 1<5 : cwaitanswer 5315 4464 ; 1<6 : answer_arrived 5316 4464 ; 1<7 : signal_sem-signal_binary 5317 4464 ; 1<8 : wait_semaphore 5318 4464 ; 1<9 : signal_chained 5319 4464 ; 1<10 : inspect_chained 5320 4464 ; 1<11 : wait_chained 5321 4464 ; 1<12 : sem_sendmessage 5322 4464 ; 1<13 : sem_answer_proc 5323 4464 ; 1<14 : message_received 5324 4464 ; 1<15 : timer_message 5325 4464 ; 1<16 : timer_scan 5326 4464 ; 1<17 : cregretmessage 5327 4464 ; 1<18 : user defined testrecord 5328 4464 ; 5329 4464 ; call return 5330 4464 ; w0: - unchanged 5331 4464 ; w1: - unchanged 5332 4464 ; w2: - unchanged 5333 4464 ; w3: link current coroutine 5334 4464 5334 4464 5334 4464 b.j10,i5 5335 4464 w. 5336 4464 h4: am (b27) ; begin 5337 4464 rs w3 +8 ; ext1(8):= link; 5338 4464 rl w3 b27 ; 5339 4464 ds w1 x3+22 ; save working registers 5340 4464 rs w2 x3+24 ; 5341 4464 rl w1 x3+8 ; 5342 4464 rl w3 (b28) ; 5343 4464 rl w0 x3+a716 ; if testkind is included in curr.corout.testm then 5344 4464 la w0 x1 ; begin 5345 4464 sn w0 0 ; 5346 4464 jl. j6. ; 5347 4464 rl w3 b141 ; if core(128) <> 0 then 5348 4464 sn w3 0 ; begin 5349 4464 jl. j1. ; 5350 4464 rl w3 b28 ; 5351 4464 al w1 x3+a566 ; 5352 4464 rs w0 x1 ; cur.ext2.testmess(1):= testkind; 5353 4464 al w3 x3+a556 ; 5354 4464 jd 1<11+16 ; send message(testmes,cmontest); 5355 4464 jd 1<11+18 ; wait answer; 5356 4464 jl. j6. ; else 5357 4464 j1: rl w3 b28 ; begin ! create record in cyclical buffer ! 5358 4464 am (b27) ; if testkind = user record 5359 4464 rl w1 +24 ; 5360 4464 se. w0 (i0.) ; then length:= length(user record) 5361 4464 al w1 8 ; else length:= 8; 5362 4464 rl w2 x3+a540 ; if (start(next record)+length+8) > 5363 4464 wa w1 x3+a540 ; top(test buffer) then 5364 4464 al w1 x1+8 ; begin 5365 4464 sh w1 (x3+a542) ; 5366 4464 jl. j2. ; 5367 4464 al w1 0 ; insert dummy end record 5368 4464 rs w1 x2 ; 5369 4464 rl w2 x3+a538 ; start(next record):= start(test buffer); 5370 4464 ; end; 5371 4464 j2: rs w0 x2 ; insert testkind in record 5372 4464 rl w3 0 ; 5373 4464 jd 1<11+36 ; get clock 5374 4464 ds w1 x2+4 ; insert time in test record 5375 4464 sn. w3 (i0.) ; if testkind = coroutine function then 5376 4464 jl. j3. ; begin 5377 4464 rl w3 (b28) ; 5378 4464 am (b27) ; 5379 4464 dl w1 +22 ; 5380 4464 ds w1 x2+8 ; insert w0,w1 5381 4464 am (b27) ; 5382 4464 rl w0 +24 ; 5383 4464 rs w0 x2+10 ; insert w2 5384 4464 rl w0 x3+a718 ; 5385 4464 ds w0 x2+14 ; insert coroutine_ident, addr. of curr,corout. 5386 4464 al w2 x2+14 ; 5387 4464 jl. j5. ; end 5388 4464 j3: rl w3 b27 ; else 5389 4464 dl w1 x3+22 ; begin <* user defined test record *> 5390 4464 rl w3 x3+24 ; 5391 4464 hs w0 x2+6 ; insert user identification 5392 4464 hs w3 x2+7 ; insert length 5393 4464 al w2 x2+8 ; 5394 4464 j4: rl w0 x1 ; transfer test information 5395 4464 rs w0 x2 ; 5396 4464 al w3 x3-2 ; 5397 4464 sh w3 0 ; 5398 4464 jl. j5. ; 5399 4464 al w2 x2+2 ; 5400 4464 al w1 x1+2 ; 5401 4464 jl. j4. ; end; 5402 4464 ; end; 5403 4464 j5: rl w3 b28 ; 5404 4464 al w2 x2+2 ; update start(next record) in procees ext2 5405 4464 rs w2 x3+a540 ; 5406 4464 j6: rl w3 b27 ; 5407 4464 dl w1 x3+22 ; load working registers 5408 4464 rl w2 x3+24 ; 5409 4464 rl w3 x3+8 ; return:=ext1(8); 5410 4464 jl x3+2 ; end; 5411 4464 5411 4464 i0: +1<18 ; testkind f. user test record 5412 4464 5412 4464 e. 5413 4464 e. 5414 4464 z. 5415 4464 5415 4464 5415 4464 5415 4464 5415 4464 ; procedure errorlog. 5416 4464 ; called from driver when a abnormal result is received, 5417 4464 ; or when a internal interupt is received. 5418 4464 ; if the external process errorlog has received a buffer this procedure 5419 4464 ; will produce a record. the format of the record depends on 5420 4464 ; the kind of error. 5421 4464 ; the procedure is called with w1 holding the process description of the failed 5422 4464 ; process e.g. the current internal process in case of a internal 5423 4464 ; interupt or the physical disc in case of a discerror. 5424 4464 ; 5425 4464 ; 5426 4464 ; 5427 4464 ; call return 5428 4464 ; w0 unchanged 5429 4464 ; w1 failed process unchanged 5430 4464 ; w2 link unchanged 5431 4464 ; w3 unchanged 5432 4464 5432 4464 5432 4464 b. i15 , j20 w. 5433 4464 g66 :ds. w1 i0. ; save all registers 5434 4466 ds. w3 i1. ; 5435 4468 dl w1 b19 ; save current buffer , current receiver 5436 4470 ds. w1 i3. ; 5437 4472 rl w1 b30 ; set current receiver := errorlog 5438 4474 rs w1 b19 ; 5439 4476 jl w3 g64 ; examine queue 5440 4478 jl. j15. ; +0 : queue empty ; return 5441 4480 rl w2 b30 ; +2 : mess in queue 5442 4482 al w2 x2+a70 ; c. w2= errorbuffer start 5443 4484 al w3 0 ; 5444 4486 rs w3 x2 ; 5445 4488 dl w1 b13+2 ; insert time in errorbuf 5446 4490 ds w1 x2+32 ; 5447 4492 rl. w1 i0. ; record type : goto case kind of 5448 4494 rl w0 x1+a10 ; 5449 4496 hs w0 x2+0 ; 5450 4498 sn w0 0 ; 5451 4500 jl. j0. ; internal interupts, monitor call break 5452 4502 sn w0 62 ; 5453 4504 jl. j1. ; discerror 5454 4506 se w0 86 ; 5455 4508 sn w0 88 ; 5456 4510 jl. j3. ; fpa transmission error 5457 4512 se w0 84 ; 5458 4514 sn w0 85 ; 5459 4516 jl. j5. ; subprocesserror 5460 4518 jl. j15. ; otherwise ... return 5461 4520 ; 5462 4520 ; before exit the registers contain 5463 4520 ; w0 : kind.failed process 5464 4520 ; w1 : process description of failed process 5465 4520 ; w2 : errorbuffer start 5466 4520 ; 5467 4520 ; 5468 4520 j0: dl w0 x1+a11+2 ; internal interupt . 5469 4522 ds w0 x2+4 ; move name.failed process 5470 4524 dl w0 x1+a11+6 ; 5471 4526 ds w0 x2+8 ; 5472 4528 al w2 x2+10 ; 5473 4530 al w0 8 ; copy from process descr. w0,w1 w2 w3 5474 4532 al w1 x1+a28 ; status ic(logical) cause sb 5475 4534 jl. w3 j9. ; 5476 4536 rl w3 x1-a28+a182; copy last two instructions 5477 4538 wa w3 x1-a28+a33 ; 5478 4540 dl w1 x3-2 ; 5479 4542 ds w1 x2-10+28 ; 5480 4544 al w3 32 ; save size-2 of record and 5481 4546 jl. j13. ; goto copy errorbuf 5482 4548 ; 5483 4548 ; 5484 4548 j1: rs w1 x2+28 ; discerror 5485 4550 rl w3 x1+a244 ; copy i-o result, rem char.std status 5486 4552 rl w0 x1+a231 ; 5487 4554 ds w0 x2+20 ; 5488 4556 dl w0 x1+100 ; status: sum of all statusbits 5489 4558 ds w0 x2+24 ; e.g. std. status "or" statusarea1 5490 4560 rl w3 x1+102 ; ( "or" statusarea2) 5491 4562 rs w3 x2+26 ; 5492 4564 rl. w1 i2. ; copy from "current" buffer 5493 4566 dl w0 x1+a151 ; mess(1) - mess(2) 5494 4568 ds w0 x2+12 ; mess(4) - mess(5) 5495 4570 dl w0 x1+a153+2 5496 4572 ds w0 x2+16 ; 5497 4574 rl w1 x1+a141 ; get process descr. rec 5498 4576 sh w1 (b3) ; if receiver defined then 5499 4578 jl. j2. ; 5500 4580 dl w0 x1+a11+2 ; 5501 4582 ds w0 x2+4 ; 5502 4584 dl w0 x1+a11+6 ; 5503 4586 ds w0 x2+8 ; 5504 4588 j2: al w3 32 ; save size-2 of record 5505 4590 jl. j13. ; goto copy errorbuf 5506 4592 ; 5507 4592 ; 5508 4592 j3: zl w0 x1+42 ; fpa transmission error 5509 4594 ls w0 12 ; 5510 4596 hl w0 x1+44 ; save 5511 4598 ds w1 x2+28 ; startbyte, statusbyte 5512 4600 dl w0 x1+a11+2 ; name 5513 4602 ds w0 x2+4 5514 4604 dl w0 x1+a11+6 ; 5515 4606 ds w0 x2+8 ; 5516 4608 dl w0 x1+a231 ; std status 5517 4610 ds w0 x2+12 ; 5518 4612 dl w0 x1+a233 ; 5519 4614 ds w0 x2+16 5520 4616 dl w0 x1+28 ; status from first sense 5521 4618 ds w0 x2+20 ; 5522 4620 dl w0 x1+32 ; 5523 4622 ds w0 x2+24 ; 5524 4624 dl w0 x1+36 ; copy status from second sense 5525 4626 ds w0 x2+36 ; 5526 4628 dl w0 x1+40 ; 5527 4630 ds w0 x2+40 ; 5528 4632 al w0 18 ; copy channelprogram 5529 4634 wa w1 x1+a226 ; 5530 4636 al w2 x2+42 ; 5531 4638 jl. w3 j9. ; 5532 4640 al w3 74 ; save size-2 of record 5533 4642 jl. j13. ; goto copy errorbuf 5534 4644 ; 5535 4644 ; 5536 4644 j5: rs w1 x2+28 ; subprocess error 5537 4646 hl w0 x1+36 ; copy from subprocess 5538 4648 hs w0 x2+1 ; subkind 5539 4650 dl w0 x1+a11+2 ; 5540 4652 ds w0 x2+4 ; name 5541 4654 dl w0 x1+a11+6 ; 5542 4656 ds w0 x2+8 5543 4658 dl w0 g29 ; copy first four words of mess from save area 5544 4660 ds w0 x2+12 ; 5545 4662 dl w0 g30 ; 5546 4664 ds w0 x2+16 ; 5547 4666 dl w0 g21 ; copy the answer from std answer area 5548 4668 ds w0 x2+20 ; 5549 4670 dl w0 g23 5550 4672 ds w0 x2+24 ; 5551 4674 rl w3 g24 ; 5552 4676 rs w3 x2+26 ; 5553 4678 al w3 32 ; save size-2 5554 4680 jl. j13. ; goto copy buf 5555 4682 ; 5556 4682 ; 5557 4682 ; 5558 4682 ; help procedure move doublewords. 5559 4682 ; move the specified number if words as doublewords. 5560 4682 ; odd number of words will cause one extra word to be moved. 5561 4682 ; call return 5562 4682 ; w0: no of words destroyed (zero) 5563 4682 ; w1: from adr unchanged 5564 4682 ; w2: to adr unchanged 5565 4682 ; w3: link unchanged 5566 4682 ; 5567 4682 ; 5568 4682 j9: ds.w2 i13. ; 5569 4684 ds. w0 i15. ; 5570 4686 j10: dl w0 x1+2 ; 5571 4688 ds w0 x2+2 ; 5572 4690 al w1 x1+4 ; 5573 4692 al w2 x2+4 ; 5574 4694 rl. w3 i15. ; decrease word count 5575 4696 al w3 x3-2 ; 5576 4698 rs. w3 i15. ; 5577 4700 5577 4700 sl w3 1 ; 5578 4702 jl. j10. ; 5579 4704 dl. w2 i13. ; restore registers 5580 4706 dl. w0 i15. ; 5581 4708 jl x3 ; 5582 4710 ; 5583 4710 ; 5584 4710 0 ; from adr 5585 4712 i13: 0 ; to adr 5586 4714 0 ; link 5587 4716 i15: 0 ; word count 5588 4718 ; 5589 4718 ; 5590 4718 j12: rl w1 4 ; copy direct: setup parameters to procedure move doublewors 5591 4720 rl. w2 i10. ; 5592 4722 rl w2 x2+a151 ; first adr in messbuf 5593 4724 wa. w2 i9. ; + no of hw already moved 5594 4726 al w0 34 ; record size: 34 hw 5595 4728 jl. w3 j9. ; 5596 4730 al w1 34 ; goto update no of hw moved 5597 4732 rl. w2 i10. ; 5598 4734 jl. j14. ; 5599 4736 ; 5600 4736 ; 5601 4736 j13: rl w2 b30 ; copy errorbuffer (general copy) 5602 4738 rl w1 x2+a54 ; check buffer. 5603 4740 al w0 0 ; if buffer<> last used buffer then 5604 4742 se. w1 (i10.) ; set bufferadr and clear relative adr. 5605 4744 ds. w1 i10. ; 5606 4746 rl w0 x1+a150 ; change operation to odd 5607 4748 wa. w0 i11. ; to use gen. copy 5608 4750 rs w0 x1+a150 ; 5609 4752 al w2 x2+a70 ; 5610 4754 zl w1 x2+0 ; if kind of record = internal then 5611 4756 sn w1 0 ; goto move direct. 5612 4758 jl. j12. ; (we are in monitor mode and cant use general copy) 5613 4760 wa w3 4 ; else store first and last adr 5614 4762 ds. w3 i8. ; 5615 4764 al. w1 i6. ; 5616 4766 rl. w2 i10. ; setup parameters and call 5617 4768 jd 1<11+84 ; general copy 5618 4770 se w0 0 ; if not ok then !!!!! 5619 4772 jl. j11. ; 5620 4774 j14: wa. w1 i9. ; (copy direct continues here. w1=no of hw moved 5621 4776 rs. w1 i9. ; w2= mess buf adr) 5622 4778 rl w0 x2+a150 ; change operation to even 5623 4780 ws. w0 i11. ; makes it possible to regret the mess. 5624 4782 rs w0 x2+a150 ; 5625 4784 wa w1 x2+a151 ; update relative adr and check restsize in buf 5626 4786 al w1 x1+74 ; 5627 4788 sh w1 (x2+a152) ; if restsize < max record size then 5628 4790 jl. j15. ; deliver answer else goto return 5629 4792 j11: al w0 1 ; deliver result 1 5630 4794 rl. w1 i9. ; 5631 4796 rl w3 b30 ; check kind.record 5632 4798 rl w3 x3+a70 ; if kind.record =internal then 5633 4800 se w3 0 ; deliver answer else 5634 4802 jl. j16. ; deliver result 5635 4804 rs w0 x2+a141 ; set result in buffer 5636 4806 ds w1 x2+a151 ; no of bytes =sum of bytes moved 5637 4808 jl w3 d15 ; deliver answer (continue with restore parameters ) 5638 4810 5638 4810 5638 4810 j17: al w0 0 ; reset special watched receiver 5639 4812 rs w0 b32 ; 5640 4814 jl w3 g64 ; if more messages in queue 5641 4816 jl. j15. ; then set next special watched receiver adr 5642 4818 rl w0 x2+a153 ; 5643 4820 rs w0 b32 ; (placed in connection to "deliver result" ) 5644 4822 5644 4822 j15: dl. w1 i3. ; return : restore all parameters 5645 4824 ds w1 b19 ; restore current receiver and buffer 5646 4826 dl. w1 i0. ; restore all registers 5647 4828 dl. w3 i1. ; 5648 4830 jl x2 ; 5649 4832 j16: ds w1 g21 ; deliver result 5650 4834 jl w3 g19 ; 5651 4836 jl. j17. ; restore parameters 5652 4838 ; 5653 4838 ; 5654 4838 ; parameter list : 5655 4838 ; 5656 4838 0 ; save w0: 5657 4840 i0: 0 ; save w1: pd.failed process 5658 4842 0 ; save w2: link 5659 4844 i1: 0 ; save w3: 5660 4846 i2: 0 ; save current buffer 5661 4848 i3: 0 ; save current receiver 5662 4850 5662 4850 5662 4850 i6: 2<1+1 ; parameters for general copy: funtion 5663 4852 i7: 0 ; first adr in errorbuf 5664 4854 i8: 0 ; last adr in errorbuf 5665 4856 i9: 0 ; relative start to mess buf adr (no of hw moved) 5666 4858 i10: 0 ; buffer adr 5667 4860 i11: 1<12 ; change op even-odd 5668 4862 e. ; end of errorlog entry 5669 4862 5669 4862 5669 4862 b.i0 ; begin 5670 4862 w.i0: al. w2 i0. ; make room: 5671 4864 jl x3+0 ; autoloader(end monitor procedures); 5672 4866 jl. i0. ; after loading: 5673 4868 j0=k - b127 + 2 5674 4868 k = i0 ; goto make room; 5675 4862 e. ; end 5676 4862 5676 4862 5676 4862 e. ; end of monitor segment 5677 4862 5677 4862 5677 4862 \f ▶EOF◀