1 " ***********************************************************
2 " * *
3 " * Copyright, C Honeywell Bull Inc., 1987 *
4 " * *
5 " * Copyright, C Honeywell Information Systems Inc., 1982 *
6 " * *
7 " ***********************************************************
8
9 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
10 "
11 " volmap_page
12 "
13 " Routines to act on single pages of a volume map
14 "
15 " Entries:
16 "
17 " grap_volmap_page_unwired - wires and reads in a volmap page
18 " deposits excess stock to volume map
19 "
20 " write_volmap_page_unwired - writes and unwires a volmap page
21 "
22 " start_async_read - starts an asynchronous read cycle to
23 " the volume map
24 "
25 " start_async_write - starts an asynchronous write cycle to
26 " the volume map
27 "
28 " post_io - posts a volume map i/o
29 "
30 " poll_io - polls for complete volume map i/os
31 "
32 " Written February 1982 by J. Bongiovanni
33 " Modified September 1982, J. Bongiovanni, not to do read on OS page
34 "
35 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
36
37 name volmap_page
38 segdef grab_volmap_page_unwired
39 segdef write_volmap_page_unwired
40 segdef start_async_read
41 segdef start_async_write
42 segdef post_io
43 segdef poll_io
44
45 link volmap_abs_seg_link,volmap_abs_seg$
46
47 even
48 pc_wired_arg_list:
49 vfd 18/6,18/4,36/0
50 pread_arg_list:
51 vfd 18/6,18/4,36/0
52 pwrite_arg_list:
53 vfd 18/4,18/4,36/0
54 notify_arg_list:
55 vfd 18/2,18/4,36/0
56
57 one: dec 1
58 "^L
59 include aste
60 "^L
61 include page_info
62 "^L
63 include ptw
64 "^L
65 include pvte
66 "^L
67 include pxss_page_stack
68 "^L
69 include stock_seg
70 "^L
71 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
72 "
73 " grab_volmap_page_unwired
74 "
75 " call page$grab_volmap_page_unwired pvtep page_no page_ptr
76 "
77 " pvtep = pointer to PVTE Input
78 " page_no = page number in volume map Input
79 " page_ptr = pointer to page in volume map Output
80 "
81 " The volume map must be locked to this process with asynchronous
82 " state of idle. volmap_abs_seg must be set to refer to this volume
83 " map.
84 "
85 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
86
87 grab_volmap_page_unwired:
88 push
89 tsx6 page_fault$init_savex " Recursive use of x7
90
91 eppbp ap|2,* " bp -> ptr -> PVTE
92 eppbp bp|0,* " bp -> PVTE
93 tsx6 check_valid_call " Check lock, async state, abs seg
94
95 lprpab bp|pvte.volmap_astep " ab -> ASTE for volume map
96 spriab arg+8
97 eppab arg+8
98 spriab arg+2
99 eppab ap|4,* " Page number
100 spriab arg+4
101 eppab one " Number of pages
102 spriab arg+6
103 ldaq pc_wired_arg_list
104 staq arg
105 call pc_wired$wire_waitarg
106
107 lda ap|4,* " Page number
108 als page_power " Offset in segment
109 eppab volmap_abs_seg$0,al " ab -> page
110 spriab ap|6,* " Return to caller
111
112 lprpbb bp|pvte.volmap_stock_ptr " bb -> record stock
113 lxl0 bb|record_stock.high_threshold " Above high threshold
114 cmpx0 bb|record_stock.n_free_in_stock
115 tpl grab_volmap_returns " No
116 epbpab bb|0 " ab -> base of stock_seg
117 eppab ab|stock_seg.meters " ab -> meters
118 aos ab|rsmeters.high_thresh_detected
119 lda ap|4,* " Page number
120 tsx7 volmap$deposit_to_volmap " Deposit excess for this page
121
122 grab_volmap_returns:
123 return
124 "^L
125
126 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
127 "
128 " write_volmap_page_unwired
129 "
130 " call page$write_volmap_page_unwired pvtep page_no
131 "
132 " pvtep = pointer to PVTE Input
133 " page_no = page number in volume map Input
134 "
135 " The volume map must be locked to this process with asynchronous
136 " state of idle. volmap_abs_seg must be set to refer to this volume
137 " map.
138 "
139 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
140
141 write_volmap_page_unwired:
142 push
143 eppbp ap|2,* " bp -> ptr -> PVTE
144 eppbp bp|0,* " bp -> PVTE
145 tsx6 check_valid_call " Check lock, async state, abs-seg
146
147 lprpab bp|pvte.volmap_astep " ab -> ASTE for volmap_seg
148 spriab arg+8
149 eppab arg+8
150 spriab arg+2
151 eppab ap|4,* " Page number
152 spriab arg+4
153 eppab one " One page
154 spriab arg+6
155 ldaq pc_wired_arg_list
156 staq arg
157 call pc_wired$unwire_write_waitarg
158
159 return
160 "^L
161 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
162 "
163 " start_async_read
164 "
165 " tsx7 volmap_page$start_async_read
166 " <return if page already in memory>
167 " <return if page not in memory>
168 "
169 " On entry,
170 " bp -> PVTE
171 " ab -> stock_seg.meters
172 " Areg = page number in volume map
173 " Volume map locked to this process, async state idle
174 " PTL locked to this process
175 "
176 " On exit,
177 " Async state is Read
178 "
179 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
180
181 start_async_read:
182 tsx6 page_fault$savex " Recursive use of x7
183
184 increment ab|rsmeters.async_read_calls
185
186 sta volmap_page_temp " Page number
187
188 lda pds$processid " Check PTL
189 cmpa sst$ptl
190 tnz page_error$ptl_not_locked
191 cmpa bp|pvte.volmap_lock " Volmap lock held
192 tnz page_error$volmap_page_invalid_call " No
193 ldx0 bp|pvte.volmap_async_state " State idle
194 cmpx0 VOLMAP_ASYNC_IDLE,du
195 tnz page_error$volmap_page_invalid_call " No
196 lda volmap_page_temp " Page number
197 ana -1,dl " Just to be sure
198 ora VOLMAP_ASYNC_READ,du " New async state
199 sta bp|pvte.volmap_async_state
200
201 lda volmap_page_temp " Page number
202 lprpap bp|pvte.volmap_astep " ap -> ASTE for volmap_seg
203 ldq ap|aste_size,al " PTW
204 canq ptw.valid,dl " In memory
205 tnz page_fault$unsavex " Yes
206 canq ptw.os,dl " I/O already in progress?
207 tnz page_fault$unsavex_1 " Yes - should never happen
208
209 increment ab|rsmeters.async_page_reads
210 increment sst$volmap_seg_page_faults
211 spriap arg+8
212 eppap arg+8
213 spriap arg+2
214 eppap volmap_page_temp " Page number
215 spriap arg+4
216 eppap arg+10
217 spriap arg+6
218 ldaq pread_arg_list
219 staq arg
220 call page_fault$preadarg
221
222 tsx7 post_io_pvtep " Check for screw case
223 tra page_fault$unsavex_1
224
225 "^L
226 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
227 "
228 " start_async_write
229 "
230 " tsx7 page_fault$start_async_write
231 " <return if page is in memory>
232 " <return if page in not in memory>
233 "
234 " On entry,
235 " bp -> PVTE
236 " Volmap async state is Read
237 " PTL locked to process
238 "
239 " On exit,
240 " Volmap async state is Write
241 "
242 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
243
244 start_async_write:
245 tsx6 page_fault$savex " Recursive use of x7
246
247 sta volmap_page_temp " Page number
248 lda pds$processid
249 cmpa sst$ptl " PTL held
250 tnz page_error$ptl_not_locked
251
252 ldx0 bp|pvte.volmap_async_state
253 cmpx0 VOLMAP_ASYNC_READ,du
254 tnz page_error$wrong_async_state
255
256 lda volmap_page_temp " Page number
257 ana -1,dl " Just in case
258 ora VOLMAP_ASYNC_WRITE,du " New state
259 sta bp|pvte.volmap_async_state
260
261 lda volmap_page_temp " Page number
262 lprpap bp|pvte.volmap_astep " ap -> ASTE for volmap_seg
263 ldq ap|aste_size,al " PTW
264 canq ptw.valid,dl " In memory
265 tze page_fault$unsavex_1 " No
266 canq ptw.os,dl " Someone else writing it?
267 tnz page_fault$unsavex " Yes - skip call to pwrite
268
269 spriap arg+6 " astep
270 eppap arg+6
271 spriap arg+2
272 eppap volmap_page_temp " Page number
273 spriap arg+4
274 ldaq pwrite_arg_list
275 staq arg
276 call page_fault$pwritearg
277
278 tsx7 post_io_pvtep " Check for screw case
279 tra page_fault$unsavex
280 "^L
281 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
282 "
283 " post_io
284 "
285 " tsx7 volmap_page$post_io
286 "
287 " On entry,
288 " Areg = pvtx
289 " PTL locked to process
290 "
291 " post_io_pvtep - internal procedure, registers already setup
292 "
293 " tsx7 post_io_pvtep
294 "
295 " On entry,
296 " bp -> PVTE
297 " PTL locked to process
298 "
299 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
300
301
302 post_io:
303 eax0 0 " Pvtx given
304 sta volmap_page_temp " pvtx
305 tra post_io_join
306
307 post_io_pvtep:
308 eax0 1 " Pvtep given
309
310 post_io_join:
311 read_clock
312 staq post_io_start_time " For metering
313
314 eax0 0,x0 " Pvtep given
315 tpnz post_got_pvtep " Yes
316 ldq pvte_size,dl " Compute pvtep
317 mpy volmap_page_temp " Offset in array, one too high
318 eppbp pvt$array
319 eppbp bp|-pvte_size,ql " bp -> PVTE
320
321 post_got_pvtep:
322 lda bp|pvte.volmap_async_state " State in AU, page in AL
323 tra post_io_state,au " Do what's appropriate
324 post_io_state:
325 tra 0,x7 " Idle
326 tra post_read " Read
327 tra post_write " Write
328
329 post_read:
330 tsx6 page_fault$savex " Recursive use of x7
331 lprpap bp|pvte.volmap_astep " ap -> ASTE for volmap_seg
332 ldq ap|aste_size,al " PTW
333 canq ptw.er,dl " I/O Error
334 tze post_read_noerr " No
335 tsx7 io_error " Yes - handle
336 tra post_idle " Set state to idle and notify
337 post_read_noerr:
338 canq ptw.valid,dl " In memory
339 tnz post_read_in_mem " Yes
340 canq ptw.os,dl " Did we lose the I/O?
341 tnz page_fault$unsavex " No
342 tra post_idle " Yes, reset it..time will cure all
343
344 post_read_in_mem:
345 ana -1,dl " Page number
346 lprpbb bp|pvte.volmap_stock_ptr " bb -> record stock
347 epbpab bb|0 " ab -> base of stock seg
348 eppab ab|stock_seg.meters " ab -> meters
349 tsx7 volmap$withdraw_from_volmap " Replenish stock
350
351 lda bp|pvte.volmap_async_page
352 ana -1,dl " Page number
353 tsx7 start_async_write " Write it back
354 tra post_meter_exit
355 tra page_error$volmap_page_async_error " Not in memory
356
357 post_write:
358 tsx6 page_fault$savex " Recursive use of x7
359 lprpap bp|pvte.volmap_astep " ap -> ASTE for volmap_seg
360 ldq ap|aste_size,al " PTW
361 canq ptw.er,dl " I/O Error
362 tze post_write_noerr " No
363 tsx7 io_error " Yes - handle
364 tra post_idle " Set state to idle and notify
365 post_write_noerr:
366 canq ptw.os,dl " I/O finished
367 tnz page_fault$unsavex " No
368
369 canq ptw.valid,dl " In memory
370 tze post_write_not_mod " No, write surely done
371 canq ptw.phm+ptw.phm1,dl " Page modified
372 tze post_write_not_mod " No, write completed
373
374 " Write posted but page modified. Possibly a race, although the locking
375 " strategy should prevent this. More likely, the disk went offline.
376 " In this case, the write is notified with no error by page control.
377 " We recover by re-issuing the I/O
378
379 spriap arg+6 " ptr -> ASTE of volmap_seg
380 eppap arg+6
381 spriap arg+2
382 lda bp|pvte.volmap_async_page " Page number in lower
383 ana -1,dl
384 sta arg+8
385 eppap arg+8
386 spriap arg+4
387 ldaq pwrite_arg_list
388 staq arg
389 call page_fault$pwritearg
390 tra page_fault$unsavex
391
392 post_write_not_mod:
393 lprpbb bp|pvte.volmap_stock_ptr " bb -> record stock
394 epbpab bb|0 " ab -> base of stock seg
395 eppab ab|stock_seg.meters " ab -> meters
396 tsx7 stock$reset_os " Write finished, OK to use addresses
397
398 post_idle:
399 stz bp|pvte.volmap_async_state " Idle
400 post_write_retry:
401 ldq bp|pvte.volmap_idle_notify_word " Anybody waiting for idle
402 lda bp|pvte.volmap_idle_notify_word
403 cana pvte.volmap_idle_notify,dl
404 tze post_meter_exit " No
405 era pvte.volmap_idle_notify,dl " Reset notify switch
406 stacq bp|pvte.volmap_idle_notify_word
407 tnz post_write_retry " Lost race
408
409 eaa bp|0 " AU = PVTE offset
410 arl 18 " AL = PVTE offset
411 ora pvt$volmap_idle_wait_constant " Areg = wait event
412 sta arg+4
413 eppap arg+4
414 spriap arg+2
415 ldaq notify_arg_list
416 staq arg
417 call pxss$notifyarg
418
419 post_meter_exit:
420 increment ab|rsmeters.async_post_io_calls
421 read_clock
422 sbaq post_io_start_time
423 adaq ab|rsmeters.async_post_io_time
424 staq ab|rsmeters.async_post_io_time
425 tra page_fault$unsavex
426
427 "^L
428 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
429 "
430 " poll_io
431 "
432 " call page$poll_volmap_io
433 "
434 " Called with no locks held, wired and masked
435 "
436 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
437
438 poll_io:
439 push
440 tsx6 page_fault$init_savex " Recursive use of x7
441
442 tsx7 page_fault$lock_ptl " Spin lock
443
444 ldq pvte_size,dl " Index to last PVTE
445 mpy pvt$n_entries
446 eax0 0,ql " x0 -> one beyond end
447 stx0 volmap_page_temp_1 " Save
448 poll_loop:
449 ldx0 volmap_page_temp_1 " Restore PVTE index
450 eax0 -pvte_size,x0 " One fewer to go
451 tmi poll_done
452 stx0 volmap_page_temp_1 " Save index to PVTE
453 eppbp pvt$array
454 eppbp bp|0,x0 " bp -> PVTE
455 ldq bp|pvte.used_word
456 canq pvte.used,dl " PVTE in use
457 tze poll_loop " No - skip
458 ldx1 bp|pvte.volmap_async_state " Asynchronous activity state
459 cmpx1 VOLMAP_ASYNC_IDLE,du " Idle
460 tze poll_loop " Yes - skip
461
462 sxl1 volmap_page_temp_1 " Save async state
463 tsx7 post_io_pvtep " Try to post the I/O
464 lxl1 volmap_page_temp_1 " Restore async state
465 cmpx1 bp|pvte.volmap_async_state " Did state change?
466 tze poll_loop " No
467 tsx7 page_error$poll_state_change " Yes - report it
468 tra poll_loop
469
470 poll_done:
471 eppbb sst$ " Needed by unlock_ptl
472 tsx7 page_fault$unlock_ptl
473 return
474
475
476 "^L
477 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
478 "
479 " io_error - internal procedure to handle unrecoverable I/O error
480 "
481 " tsx7 io_error
482 "
483 " On entry,
484 " bp -> PVTE
485 " Areg = page number in volmap_seg
486 "
487 " The strategy is to lose all free addresses on the page with the
488 " I/O error. Any OS pages are flushed from the stock, and the
489 " count of free addresses on that page is set to zero.
490 "
491 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
492
493 io_error:
494 tsx6 page_fault$savex " Recursive use of x7
495 sta volmap_page_temp
496 lprpbb bp|pvte.volmap_stock_ptr " bb -> Record stock
497 epbpab bb|0 " ab -> base of stock_seg
498 eppab ab|stock_seg.meters " ab -> stock_seg$meters
499
500 tsx7 stock$flush_os " Flush any out-of-service addresses
501
502 lda volmap_page_temp " Page number
503 ldx0 bp|pvte.nleft " Total number records left
504 sblx0 bb|record_stock.volmap_page,al " Minus number free this page
505 tpl io_error_nleft_ok " If positive
506 eax0 0
507 io_error_nleft_ok:
508 stx0 bp|pvte.nleft " Becomes new number left
509 eax0 0
510 stx0 bb|record_stock.volmap_page,al " Clear count of free this page
511 ldx0 bp|pvte.vol_trouble_count " Increment the trouble count
512 adlx0 1,du
513 stx0 bp|pvte.vol_trouble_count
514
515 tsx7 page_error$volmap_io_error " Tell the world
516 tra page_fault$unsavex " And return
517
518 "^L
519 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
520 "
521 " check_valid_call - internal procedure to validate that
522 " volume map is locked to this process, async state is idle,
523 " and volmap_abs_seg is setup.
524 "
525 " tsx6 check_valid_call
526 "
527 " On entry,
528 " bp -> PVTE
529 "
530 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
531
532 check_valid_call:
533 ldx0 lp|volmap_abs_seg_link " Segment number of volmap_abs_seg
534 adx0 lp|volmap_abs_seg_link " Offset of SDW in DSEG
535 ldaq dseg$0,x0 " SDW
536 cmpaq bp|pvte.volmap_seg_sdw " The right one
537 tnz page_error$volmap_page_invalid_call
538
539 lda pds$processid
540 cmpa bp|pvte.volmap_lock " Volmap lock held
541 tnz page_error$volmap_page_invalid_call
542
543 ldx0 bp|pvte.volmap_async_state " State idle
544 cmpx0 VOLMAP_ASYNC_IDLE,du
545 tnz page_error$volmap_page_invalid_call
546
547 tra 0,x6
548
549
550
551
552 end