|
|
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◀