1
2
3
4
5
6
7
8
9
10
11 pc_deposit:
12 proc (Pvtx, Devadd, Vtocx, Pageno);
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 dcl Pvtx fixed bin parameter;
42 dcl Devadd bit (36) aligned parameter;
43 dcl Vtocx fixed bin;
44 dcl Pageno fixed bin;
45 dcl List_ptr ptr parameter;
46 dcl First fixed bin;
47 dcl Last fixed bin;
48 dcl Pageno_list_ptr ptr;
49
50
51
52 dcl check_scavenger bit (1) aligned;
53 dcl conflict bit (1) aligned;
54 dcl grabbed_vpage fixed bin;
55 dcl listx fixed bin;
56 dcl listx1 fixed bin;
57 dcl p99 pic "99";
58 dcl pageno fixed bin;
59 dcl pages fixed bin;
60 dcl pf_begin fixed bin (35);
61 dcl pf_end fixed bin (35);
62 dcl Single_addressp ptr;
63 dcl this_vpage fixed bin;
64 dcl vcpu_begin fixed bin (71);
65 dcl vcpu_end fixed bin (71);
66 dcl volmap_locked bit (1);
67 dcl vpage_found bit (1);
68 dcl vpage_list (256) fixed bin;
69 dcl vpage_no fixed bin;
70 dcl vpage_ptr ptr;
71 dcl vtoc_index fixed bin;
72
73
74
75 dcl NULL_SDW fixed bin (71) int static options (constant) init (0);
76 dcl RECORDS_PER_WORD fixed bin int static options (constant) init (32);
77
78
79
80 dcl 1 List (Last) aligned like Single_address based (List_ptr);
81 dcl Pageno_list (Last) fixed bin based (Pageno_list_ptr);
82 dcl 1 Single_address aligned based (Single_addressp),
83 2 Null_flag bit (1) unaligned,
84 2 Address fixed bin (17) unsigned unaligned,
85 2 Pad bit (18) unaligned;
86
87
88
89 dcl volmap_abs_seg$ external;
90
91
92
93 dcl page$grab_volmap_page_unwired
94 entry (ptr, fixed bin, ptr);
95 dcl page$lock_volmap entry (ptr);
96 dcl page$unlock_volmap entry (ptr);
97 dcl page$write_volmap_page_unwired
98 entry (ptr, fixed bin);
99 dcl pmut$swap_sdw entry (ptr, ptr);
100 dcl syserr entry options (variable);
101 dcl usage_values entry (fixed bin (35), fixed bin (71));
102
103
104
105 dcl cleanup condition;
106 dcl page_fault_error condition;
107
108
109
110 dcl addr builtin;
111 dcl convert builtin;
112 dcl divide builtin;
113 dcl mod builtin;
114 dcl null builtin;
115 dcl ptr builtin;
116 dcl stacq builtin;
117 dcl unspec builtin;
118 %page;
119
120
121 call usage_values (pf_begin, vcpu_begin);
122 pages = 1;
123
124 pvtep = addr (addr (pvt$array) -> pvt_array (Pvtx));
125 record_stockp = pvte.volmap_stock_ptr;
126 Single_addressp = addr (Devadd);
127 volmap_locked = "0"b;
128 grabbed_vpage = -1;
129
130 call CHECK_FOR_SCAVENGE;
131
132 vtoc_index = Vtocx;
133 pageno = Pageno;
134
135 call FIND_VOLMAP_PAGE (Single_addressp, vpage_no, pageno, conflict);
136 if conflict
137 then goto RETURN;
138
139 on cleanup call UNLOCK_RESET;
140
141 call LOCK_SETUP;
142
143 on page_fault_error
144 begin;
145 call IO_ERROR;
146 goto RETURN;
147 end;
148
149 call page$grab_volmap_page_unwired (pvtep, vpage_no - 1, vpage_ptr);
150 grabbed_vpage = vpage_no - 1;
151
152 call DEPOSIT_TO_PAGE ((Single_address.Address), vpage_no, vpage_ptr);
153
154 call page$write_volmap_page_unwired (pvtep, vpage_no - 1);
155 grabbed_vpage = -1;
156
157 RETURN:
158 revert page_fault_error;
159
160 call UNLOCK_RESET;
161
162 call METER;
163
164 return;
165 %page;
166
167
168
169
170
171
172 pc_deposit$deposit_list:
173 entry (Pvtx, List_ptr, First, Last, Vtocx, Pageno_list_ptr);
174
175 call usage_values (pf_begin, vcpu_begin);
176 pages = Last - First + 1;
177
178 pvtep = addr (addr (pvt$array) -> pvt_array (Pvtx));
179 record_stockp = pvte.volmap_stock_ptr;
180 volmap_locked = "0"b;
181 grabbed_vpage = -1;
182
183 call CHECK_FOR_SCAVENGE;
184
185 vtoc_index = Vtocx;
186
187 do listx = First to Last;
188 if Pageno_list_ptr = null ()
189 then pageno = -1;
190 else pageno = Pageno_list (listx);
191 call FIND_VOLMAP_PAGE (addr (List (listx)), vpage_list (listx), pageno, conflict);
192 if conflict
193 then vpage_list (listx) = -1;
194 end;
195
196 on cleanup call UNLOCK_RESET;
197
198 call LOCK_SETUP;
199
200 on page_fault_error
201 begin;
202 dcl pagex fixed bin;
203
204 if grabbed_vpage >= 0
205 then do;
206 do pagex = First to Last;
207 if vpage_list (pagex) = grabbed_vpage + 1
208 then vpage_list (pagex) = -1;
209 end;
210 call IO_ERROR;
211 end;
212 goto VPAGE_RETRY;
213 end;
214
215 VPAGE_RETRY:
216 vpage_found = "0"b;
217 do listx = First to Last;
218 if vpage_list (listx) > 0
219 then do;
220 vpage_found = "1"b;
221 this_vpage = vpage_list (listx);
222 call page$grab_volmap_page_unwired (pvtep, this_vpage - 1, vpage_ptr);
223 grabbed_vpage = this_vpage - 1;
224 do listx1 = listx to Last;
225 if vpage_list (listx1) = this_vpage
226 then do;
227 call DEPOSIT_TO_PAGE ((List (listx1).Address), this_vpage, vpage_ptr);
228 vpage_list (listx1) = -1;
229 end;
230 end;
231 call page$write_volmap_page_unwired (pvtep, grabbed_vpage);
232 grabbed_vpage = -1;
233 end;
234 end;
235
236 if vpage_found
237 then goto VPAGE_RETRY;
238
239 revert page_fault_error;
240
241 call UNLOCK_RESET;
242
243 call METER;
244
245 return;
246 %page;
247
248
249
250 FIND_VOLMAP_PAGE:
251 proc (Devaddp, Volmap_pageno, Page_no, Conflict);
252
253 dcl Devaddp ptr parameter;
254 dcl Volmap_pageno fixed bin parameter;
255 dcl Page_no fixed bin parameter;
256 dcl Conflict bit (1) aligned parameter;
257
258 dcl vpagex fixed bin;
259 dcl vpage_found bit (1);
260 dcl address fixed bin;
261
262 dcl 1 Devaddr aligned like Single_address based (Devaddp);
263
264 vpage_found = "0"b;
265 address = Devaddr.Address;
266 Conflict = "0"b;
267
268 if address < pvte.baseadd | address >= pvte.baseadd + pvte.totrec
269 then call syserr (CRASH, "pc_deposit: Address ^o out of paging region on ^a_^a^[^a^;^s^].", address, pvte.devname,
270 convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name);
271
272 do vpagex = record_stock.n_volmap_pages to 1 by -1 while (^vpage_found);
273 if address >= record_stock.volmap_page (vpagex).baseadd
274 then do;
275 vpage_found = "1"b;
276 Volmap_pageno = vpagex;
277 end;
278 end;
279
280 if ^vpage_found
281 then call syserr (CRASH, "pc_deposit: Invalid address ^o on ^a_^a^[^a^;^s^].", address, pvte.devname,
282 convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name);
283
284 if check_scavenger
285 then Conflict = CHECK_ADDRESS_FOR_SCAVENGER (address, Page_no);
286
287 return;
288
289
290 end FIND_VOLMAP_PAGE;
291 %page;
292
293
294 DEPOSIT_TO_PAGE:
295 proc (Record_address, Vpage_no, Vpage_ptr);
296
297 dcl Record_address fixed bin;
298 dcl Vpage_no fixed bin;
299 dcl Vpage_ptr ptr;
300
301 dcl bit_no fixed bin;
302 dcl word_no fixed bin;
303
304 dcl 1 Vm_page aligned based (Vpage_ptr),
305 2 Word (0:1023) aligned,
306 3 Pad1 bit (1) unaligned,
307 3 Bit (0:31) bit (1) unaligned,
308 3 Pad2 bit (3) unaligned;
309
310 word_no = divide (Record_address - record_stock.volmap_page (Vpage_no).baseadd, RECORDS_PER_WORD, 17);
311 if word_no < 0 | word_no > 1023 | (Vpage_no = 1 & word_no < 64)
312 then call syserr (CRASH, "pc_deposit: Invalid address ^o on ^a_^a^[^a^;^s^].", Record_address, pvte.devname,
313 convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name);
314
315 bit_no = mod (Record_address - record_stock.volmap_page (Vpage_no).baseadd, RECORDS_PER_WORD);
316
317 if Vm_page.Word (word_no).Bit (bit_no)
318 then do;
319 call syserr (ANNOUNCE, "pc_deposit: Deposit in-use address ^o on ^a_^a^[^a^;^s^].", Record_address,
320 pvte.devname, convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name);
321 pvte.vol_trouble_count = pvte.vol_trouble_count + 1;
322
323 end;
324 else do;
325 Vm_page.Word (word_no).Bit (bit_no) = "1"b;
326 pvte.nleft = pvte.nleft + 1;
327 record_stock.volmap_page (Vpage_no).n_free = record_stock.volmap_page (Vpage_no).n_free + 1;
328 end;
329
330 return;
331
332 end DEPOSIT_TO_PAGE;
333 %page;
334
335
336 IO_ERROR:
337 proc;
338
339 pvte.vol_trouble_count = pvte.vol_trouble_count + 1;
340 if grabbed_vpage >= 0
341 then if record_stock.volmap_page (grabbed_vpage + 1).n_free > 0
342 then do;
343 record_stock.volmap_page (grabbed_vpage + 1).n_free = 0;
344 call syserr (BEEP,
345 "pc_deposit: Unrecoverable I/O error on Volmap page ^d of ^a_^a^[^a^;^s^]. Addresses lost.",
346 grabbed_vpage, pvte.devname, convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name);
347 end;
348
349 end IO_ERROR;
350 %page;
351
352
353
354
355 CHECK_FOR_SCAVENGE:
356 proc;
357
358 check_scavenger = "0"b;
359
360 scavenger_blockp = null ();
361 scavenger_datap = addr (scavenger_data$);
362
363 if pvte.scavenger_block_rel ^= ""b
364 then if pvte.scav_check_address
365 then do;
366 check_scavenger = "1"b;
367 scavenger_blockp = ptr (scavenger_datap, pvte.scavenger_block_rel);
368 end;
369
370 end CHECK_FOR_SCAVENGE;
371 %page;
372
373
374
375
376
377
378 CHECK_ADDRESS_FOR_SCAVENGER:
379 proc (Record_address, Page_no) returns (bit (1) aligned);
380
381 dcl Record_address fixed bin parameter;
382 dcl Page_no fixed bin parameter;
383
384 dcl 1 A_record_block aligned like record_block;
385 dcl Ap ptr;
386 dcl conflict bit (1) aligned;
387 dcl locked bit (1) aligned;
388 dcl 1 Q_record_block aligned like record_block;
389 dcl Qp ptr;
390 dcl Wp ptr;
391
392 dcl A bit (36) aligned based (Ap);
393 dcl Q bit (36) aligned based (Qp);
394 dcl W bit (36) aligned based (Wp);
395
396
397 record_blockp = addr (scavenger_block.records (Record_address - pvte.baseadd + 1));
398
399 locked = "0"b;
400 Ap = addr (A_record_block);
401 Qp = addr (Q_record_block);
402 Wp = record_blockp;
403 do while (^locked);
404 unspec (Q_record_block) = unspec (record_block);
405 unspec (A_record_block) = unspec (Q_record_block);
406 if ^A_record_block.lock
407 then do;
408 A_record_block.lock = "1"b;
409 locked = stacq (W, A, Q);
410 end;
411 end;
412
413 if record_block.state = STATE_UNSEEN
414 then record_block.state = STATE_FREE;
415 else if record_block.state = STATE_FREE
416 then record_block.state = STATE_CONFLICT;
417 else if record_block.state = STATE_IN_USE
418 then do;
419 if Page_no >= 0 & vtoc_index >= 0 & record_block.vtocx = vtoc_index & record_block.pageno = Page_no
420 then do;
421 record_block.vtocx = 0;
422 record_block.pageno = 0;
423 record_block.state = STATE_FREE;
424 end;
425 else record_block.state = STATE_CONFLICT;
426 end;
427
428 if record_block.state = STATE_CONFLICT
429 then conflict = "1"b;
430 else conflict = "0"b;
431
432 record_block.lock = "0"b;
433
434 return (conflict);
435
436
437 end CHECK_ADDRESS_FOR_SCAVENGER;
438
439
440 %page;
441
442
443 LOCK_SETUP:
444 proc;
445
446 call page$lock_volmap (pvtep);
447 volmap_locked = "1"b;
448 call pmut$swap_sdw (addr (volmap_abs_seg$), addr (pvte.volmap_seg_sdw));
449
450 end LOCK_SETUP;
451 %page;
452
453
454 UNLOCK_RESET:
455 proc;
456
457 if grabbed_vpage ^= -1
458 then call page$write_volmap_page_unwired (pvtep, grabbed_vpage);
459 grabbed_vpage = -1;
460
461 call pmut$swap_sdw (addr (volmap_abs_seg$), addr (NULL_SDW));
462
463 if volmap_locked
464 then call page$unlock_volmap (pvtep);
465 volmap_locked = "0"b;
466
467 end UNLOCK_RESET;
468 %page;
469
470
471
472 METER:
473 proc;
474
475 stock_segp = addr (stock_seg$);
476 stock_seg.meters.pc_deposit_calls = stock_seg.meters.pc_deposit_calls + 1;
477 stock_seg.meters.pc_deposit_pages = stock_seg.meters.pc_deposit_pages + pages;
478 call usage_values (pf_end, vcpu_end);
479 stock_seg.meters.pc_deposit_time = stock_seg.meters.pc_deposit_time + vcpu_end - vcpu_begin;
480
481 end METER;
482
483 %page;
484 %include pvte;
485 %page;
486 %include scavenger_data;
487 %page;
488 %include stock_seg;
489 %page;
490 %include syserr_constants;
491 %page;
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552 end pc_deposit;