1 /****^ ***********************************************************
2 * *
3 * Copyright, C Honeywell Bull Inc., 1987 *
4 * *
5 * Copyright, C Honeywell Information Systems Inc., 1982 *
6 * *
7 *********************************************************** */
8 /* format: style2,indcomtxt */
9 /* use: pl1_macro pc.pl1.pmac -target l68 */
10 pc:
11 procedure;
12
13 /* * PC -- the utility procedure of pl1 page control.
14 *
15 * Last modified date and reason:
16 *
17 * 1985-03-28, BIM: assume that all modified pages of synch segments
18 * are synch held until proven otherwise by page$pwrite.
19 * 841220 by Keith Loepere to count dirs pages against its own quota.
20 * 840623 by Keith Loepere for nullify entry for bce.
21 * 840417 E. A. Ranzenbach to correct page_read zero event problem that caused crashes in the segment mover.
22 * 84-01-19 BIM to remove unworkable synch segmove support.
23 * 84-01-03 BIM to finish segmove.
24 * 831219 by E. N. Kittlitz, for segmove
25 * 09/19/83 by E. N. Kittlitz, per UofC SGH, periodically unlock PTL during long flushes.
26 * 08/22/83 by E. N. Kittlitz, per UofC GM&SGH, don't hedge-write per-process pages.
27 * 10/27/82 by J. Bongiovanni to reset damaged, fm_damaged on truncate
28 * and for synchronized pages
29 * 08/17/82 by J. Bongiovanni for scavenger
30 * 06/09/82 by J. Bongiovanni to fix shutdown quota problem
31 * 03/07/82 by J. Bongiovanni for record stocks
32 * 01/23/82 by BIM for truncate_count
33 * 12/29/81 by C. Hornig to remove Page Multilevel and fix fencepost error in flush.
34 * 08/11/81 by W. Olin Sibert, to fix get_file_map to not report nulled addresses as modified.
35 * This fix actually provided by Steve Harris, University of Calgary
36 * 02/20/81 by W. Olin Sibert, to conditionalize page-multilevel phase one of ADP conversion
37 * 11/17/80 by ENK for new dtu/dtm calculation
38 * 11/06/80 by ENK for loop_up_fms honouring of aste.gtms.
39 * 03/16/78 by BSG for phm1, incore null non-reportage.
40 * 08/01/77 by Greenberg for badd_types, pc_recover_sst.
41 * 05/03/77 by BSG for page$pcleanup
42 * 01/27/77 by TVV for non-fatal unprotected addresses
43 * 11/01/76 by D. Vinograd to add entry for volume dumper which returns special null addresses
44 * and does not deposit.
45 * 10/31/76 by BSG for truncate_deposit_all entry
46 * 05/13/76 by BSG for seg-by-seg PD flush.
47 * 04/13/76 by REM for Cleanup Metering
48 * 10/11/75 by BSG for fault_time_withdraws
49 * 03/04/75 by BSG for new storage system incl. no pdht.
50 * 12/11/74 by BSG for new CME/PTW protocols and new core control.
51 * 06/19/74 by BSG for page$pwait and page$cam.
52 * 08/21/73 by RBS to put in checks for reused addresses.
53 * 08/03/73 by RBS to cause pc$flush to index thru cmes rather than follow threads.
54 * 08/10/73 by SHW to use 18 bit device addresses
55 * 07/15/73 by RBS to cause pages that are in core to be written to disk by pd_flush_all
56 * 10/04/72 by RBS to make page waits go to device control to accomodate bulk store logic
57 * 06/06/72 by RBS to modify for follow-on
58 * 10/26/71 by RHG to fix move_page_table for pages which are in core when moved
59 * 10/07/71 by SHW to add ptwp to pdme increase entry size to 3 words
60 * 10/05/71 by RHG to initialize pdmap and to skip the first sst.nrecs_pdmap entries in pd_flush_all
61 * 09/22/71 by RHG to make null devadds include a ptr for page
62 * 09/20/71 by RHG to fix bug in pc$get_file_map which lost all pages of file except first at deactivation
63 * 09/03/71 by Steve Webber to make calls to page$withdraw be fixed bin4, not bit4
64 * 08/10/71 by Richard H. Gumpertz to add code for page multi-level
65 */
66
67 dcl Astep ptr parameter;
68 dcl Copy_Astep ptr parameter;
69 dcl File_Mapp ptr parameter;
70 dcl Listp ptr parameter;
71 dcl Pageno_Listp ptr parameter;
72 dcl Deposit_Count fixed bin parameter;
73 dcl First_Page fixed bin parameter;
74 dcl Last_Page fixed bin parameter;
75 dcl N_Pages fixed bin parameter;
76 dcl N_In_Core fixed bin parameter;
77 dcl Records fixed bin parameter;
78 dcl Pvtx fixed bin parameter;
79 dcl Vtocx fixed bin parameter;
80 dcl Move_Astep pointer parameter;
81 dcl Old_Astep ptr parameter;
82 dcl New_Astep ptr parameter;
83 dcl Code fixed bin 35 parameter;
84 dcl New_Vtocx fixed bin 17 parameter;
85 dcl New_Pvtx fixed bin 17;
86
87 dcl records first_page last_page i
88 fixed bin;
89 dcl ind fixed bin 35;
90 dcl temp_ind fixed bin 35;
91 dcl pvtx fixed bin;
92 dcl dumper bit 1;
93 dcl return_pageno bit 1 aligned;
94 dcl add_to_dmpr_map bit 1;
95 dcl getfmap_csl getfmap_np getfmap_nrec
96 fixed bin 9;
97 dcl offed_sw bit 1;
98 dcl j fixed bin;
99 dcl segmove_records_used fixed bin;
100 dcl cmp ptwp ptr;
101 dcl curtime fixed bin 71;
102 dcl n_in_core fixed bin 18;
103 dcl n_io_started fixed bin;
104 dcl pageno fixed bin;
105 dcl from_core count bit 1;
106 dcl old_astep new_astep old_ptp new_ptp move_ptp
107 ptr;
108 dcl oldmask fixed bin 71;
109 dcl no_deposit_no_return bit 1 aligned;
110 dcl tr_count_sw bit 1 aligned;
111 dcl segmove_records_needed fixed bin;
112 dcl segmove_records_in_hand
113 fixed bin;
114 dcl segmove_total_records fixed bin;
115 dcl code fixed bin 35;
116 dcl new_pvtx fixed bin;
117 dcl new_vtocx fixed bin;
118 dcl move_tries fixed bin;
119
120 dcl 1 copy_aste like aste aligned;
121
122 dcl fword 0:99 fixed bin based;
123
124 dcl Address_Array 0:255 bit 22 aligned based Listp;
125 dcl deposit_list segmove_deposit_list
126 0:255 bit 22 aligned;
127 dcl rfm 0:255 bit 22 aligned;
128 dcl 1 Devadd_Array 0:255 aligned based Listp,
129 2 record_no bit 18 unaligned,
130 2 add_type bit 4 unaligned;
131 dcl Pageno_List 0:255 fixed bin aligned based Pageno_Listp;
132 dcl pageno_list 0:255 fixed bin aligned;
133
134 dcl devadd bit 22 unaligned;
135 dcl devadd_record_no bit 18 unaligned defined devadd;
136 dcl devadd_record_no_proper
137 bit 17 defined devadd pos 2;
138 dcl devadd_add_type bit 4 unaligned defined devadd position 19;
139 dcl devadd_null_flag bit 1 defined devadd position 1;
140
141
142 dcl 1 devadd_bits unal based addr devadd_add_type like badd_type;
143
144
145 dcl cleanup_start_time fixed bin 71; /* Cleanup Metering */
146
147 dcl error_table_$bad_arg fixed bin 35 ext static;
148 dcl error_table_$action_not_performed
149 fixed bin 35 ext static;
150 dcl error_table_$synch_seg_segmove
151 fixed bin 35 external static;
152 dcl dbm_man$set_incr entry fixed bin fixed bin fixed bin 35;
153 dcl
154 lock$lock_fast
155 lock$unlock_fast
156 entry pointer;
157 dcl page$cam ext entry;
158 dcl page$deposit_list entry fixed bin ptr fixed bin fixed bin fixed bin ptr;
159 dcl page$pcleanup entry ptr fixed bin;
160 dcl page$pread entry ptr fixed bin fixed bin 35;
161 dcl page$pwait ext entry fixed bin 35;
162 dcl page$pwrite ext entry ptr fixed bin;
163 dcl page$withdraw_list entry fixed bin ptr fixed bin fixed bin fixed bin 35 fixed bin 35;
164 dcl pmut$lock_ptl ext entry fixed bin 71 ptr;
165 dcl pmut$unlock_ptl ext entry fixed bin 71 ptr;
166 dcl pxss$notify ext entry fixed bin;
167 dcl pxss$relinquish_priority
168 ext entry;
169 dcl quotaw$cu_for_pc entry ptr fixed bin bit 1 aligned;
170 dcl syserr ext entry options variable;
171 dcl trace ext entry options variable;
172
173 dcl null_devadd_not_in_core
174 bit 36 aligned internal static options constant init "000000000001"b3;
175 dcl line_of_words char 23 internal static options constant init "^w ^w ^w ^w ^w ^w ^w ^w";
176 dcl half_line_of_words char 11 defined line_of_words;
177
178 dcl addr addrel addwordno bit clock divide fixed max min null ptr rel size unspec wordno
179 builtin;
180 %page;
181 cleanup:
182 entry Astep; /* Entry to get segment out of core. */
183 /* Caller guarantees no access to segment */
184
185 /* Note that synchronized pages which are modified and cannot be written yet
186 are left in memory. If this happens during shutdown, it is fine. Otherwise,
187 the caller must detect this situation and handle it appropriately. It
188 can be detected by checking that aste.np is non-zero. */
189
190 sstp = addr sst_seg$;
191 astep = Astep;
192 cmp = sst.cmp; /* get a pointer to the core map */
193 cleanup_start_time = clock ; /* Cleanup Metering */
194
195 sst.cleanup_count = sst.cleanup_count + 1; /* Cleanup Metering */
196 call pmut$lock_ptl oldmask ptwp; /* mask */
197 records = 0;
198 if pc_trace
199 then call trace "cleanup^-^-astep = ^p" astep;
200 loopc:
201 ptp = addrel astep sst.astsize; /* get a pointer to the page table */
202 ind = -1; /* index of page to wait on */
203 do i = 0 to sst.pts fixed aste.ptsi 2 - 1; /* loop over all pages in the segment */
204 if atptw.core
205 then do; /* In core, includes all O/S */
206
207 if ^ptw.os
208 then do; /* Not out of service */
209 if ^ptw.phm | ptw.phm1
210 then /* Attempt to clean up the page */
211 call page$pcleanup astep i;
212 /* Do it, cam the cache */
213 /* He turns off PTW access, SDW'S gone, so no race. */
214 else call page$pwrite astep i;
215 /* Start a write */
216 end;
217
218 if ptw.os
219 then ind = fixed rel ptp 18; /* Set wait event */
220
221 end;
222
223 ptp = addrel ptp size ptw; /* Next ptw, please */
224 end;
225
226 if ind > 0
227 then call wait_then_go_to loopc;
228
229 sst.cleanup_real_time = sst.cleanup_real_time /* Cleanup Metering */ + clock - cleanup_start_time;
230 /* Cleanup Metering */
231
232 quit:
233 call pmut$unlock_ptl oldmask ptwp; /* unlock and unmask */
234 return;
235 %page;
236 nullify:
237 entry Astep; /* Entry to nullify a bce/hardcore segment.
238 Part of disk optimization for bce. */
239
240 /* The idea is to mark the pages of the segment unmodified, clean them up
241 to disk and then mark the disk addresses as null. This is done just to
242 optimize the later filling in of this segment. We don't guarantee perfection
243 in this, but it doesn't matter. Anyone who calls this ensures that the
244 segment is not in use so we don't expect a problem with pages being
245 referenced between ptl lockings. */
246
247 /* First unmodify the pages. Note that os pages are not affected, but these
248 either aren't yet modified being read or will become unmodified after
249 write. */
250
251 sstp = addr sst_seg$;
252 astep = Astep;
253
254 call pmut$lock_ptl oldmask ptwp; /* mask */
255 ptp = addrel astep sst.astsize; /* get a pointer to the page table */
256 do i = 0 to sst.pts fixed aste.ptsi 2 - 1; /* loop over all pages in the segment */
257 if atptw.core
258 then /* In core, includes all O/S */
259 if ^ptw.os /* Not out of service */
260 then ptw.phm, ptw.phm1 = "0"b;
261
262 ptp = addrel ptp size ptw; /* Next ptw, please */
263 end;
264 call pmut$unlock_ptl oldmask ptwp; /* unlock and unmask */
265
266 call cleanup astep; /* free all memory frame; make into disk addresses */
267
268 call pmut$lock_ptl oldmask ptwp; /* mask */
269 ptp = addrel astep sst.astsize; /* get a pointer to the page table */
270 do i = 0 to sst.pts fixed aste.ptsi 2 - 1; /* loop over all pages in the segment */
271 if atptw.disk
272 then substr ptw.add 1 1 = "1"b; /* make null */
273
274 ptp = addrel ptp size ptw; /* Next ptw, please */
275 end;
276 call pmut$unlock_ptl oldmask ptwp; /* unlock and unmask */
277 return;
278 %page;
279 fill_page_table:
280 entry Astep File_Mapp N_Pages;
281
282
283 astep = Astep; /* Copy args */
284 fmp = File_Mapp;
285 pvtx = astep -> aste.pvtx;
286 last_page = N_Pages - 1; /* arg is csl */
287 sstp = addr sst_seg$;
288 records = 0;
289
290 ptp = addrel astep sstp -> sst.astsize;
291 do i = 0 to last_page;
292 devadd = file_map.fm i; /* No need to lock here */
293 if devadd_null_flag
294 then do; /* Outside world null address, */
295 devadd_null_flag = "0"b; /* This is not NULLED, but null. */
296 devadd_add_type = "0000"b; /* Internal null address representation */
297 end;
298 else do; /* real disk address */
299 devadd_add_type = add_type.disk; /* Assume protected. */
300 records = records + 1;
301 end;
302 ptp -> ptwa_bits i = devadd | null_devadd_not_in_core;
303 /* save final result in ptw */
304 end;
305
306
307 do i = last_page + 1 to sstp -> sst.pts fixed astep -> aste.ptsi 2 - 1;
308 /* Fill up rest of page table with nulls */
309 ptp -> ptwa_bits i = null_devadd_not_in_core;
310 ptp -> mptwa i.devadd = fill_page_table_null_addr;
311 end;
312 aste.records = bit fixed records 9 9;
313 if pc_trace
314 then do;
315 call trace "fill_page_table^-astep = ^p" astep;
316 if last_page <= 4
317 then call trace half_line_of_words ptp -> fword 0 ptp -> fword 1 ptp -> fword 2
318 ptp -> fword 3;
319 else do;
320 do i = 0 to last_page by 8;
321 call trace line_of_words ptp -> fword i ptp -> fword i + 1
322 ptp -> fword i + 2 ptp -> fword i + 3 ptp -> fword i + 4
323 ptp -> fword i + 5 ptp -> fword i + 6 ptp -> fword i + 7;
324 end;
325 end;
326 end;
327 return;
328 %page;
329 truncate:
330 entry Astep First_Page; /* entry to truncate a page table */
331
332
333 tr_count_sw = "0"b;
334 go to truncate_join;
335
336 truncate_count:
337 entry Astep First_Page N_In_Core;
338
339
340 tr_count_sw = "1"b;
341
342 truncate_join:
343 sstp = addr sst_seg$; /* get a pointer to the sst */
344
345 astep = Astep; /* copy args into wired down stack */
346 ptp = addrel astep sstp -> sst.astsize;
347 cmp = sstp -> sst.cmp; /* and core map pointer */
348 first_page = First_Page;
349 last_page = sstp -> sst.pts fixed astep -> aste.ptsi 3 - 1;
350 /* get pt end for last page */
351
352 records = 0;
353 if pc_trace
354 then call trace "truncate^-^-astep = ^p" astep;
355
356 /* the segment has an AST entry -- must clean up page tables and core map */
357
358 call pmut$lock_ptl oldmask ptwp; /* lock and mask */
359
360 if pc_trace
361 then do;
362 if last_page <= 4
363 then call trace half_line_of_words ptp -> fword 0 ptp -> fword 1 ptp -> fword 2
364 ptp -> fword 3;
365 else do;
366 do i = 0 to last_page by 8;
367 call trace line_of_words ptp -> fword i ptp -> fword i + 1
368 ptp -> fword i + 2 ptp -> fword i + 3 ptp -> fword i + 4
369 ptp -> fword i + 5 ptp -> fword i + 6 ptp -> fword i + 7;
370 end;
371 end;
372 end;
373 n_in_core = 0;
374 retry:
375 ind = 0;
376
377 do i = first_page to last_page; /* loop through all pages going */
378 if ptp -> ptwa i.os
379 then do; /* if out of service, must wait for io */
380 ind = fixed rel addr ptp -> ptwa i 18;
381 /* get event to wait on */
382 call wait_then_go_to retry; /* must go back to top after waiting */
383 end;
384 count = "0"b; /* Assume no truncation */
385
386 /* At this point, page is not o/s. If in core, devadd has core address. */
387
388 from_core = atptwa i.core; /* Remember in_coreness */
389 devadd = ptp -> mptwa i.devadd; /* pick up the device address */
390
391 /* At this point, devadd has disk or null address, unless in core */
392
393 if from_core
394 then do; /* Page is in core */
395 n_in_core = n_in_core + 1;
396 cmep = addr cmp -> cma ptp -> core_ptwa i.frame;
397 /* Get pointer to cme */
398 devadd = cmep -> cme.devadd; /* and get the devadd for cleanup */
399 if ptp -> ptwa i.wired
400 then sstp -> sst.wired = sstp -> sst.wired - 1;
401 call page$pcleanup astep i; /* Fix up data bases, count quota, csl */
402 count = "0"b; /* page$cleanup did all work */
403 end;
404
405
406 /* At this point, page is not in core. devadd has disk, null, or nulled */
407
408 if devadd_bits.disk
409 then if ^devadd_null_flag /* if nulling ... */
410 then do;
411 devadd_null_flag = "1"b; /* Null the address */
412 count = "1"b;
413 end;
414
415 ptp -> mptwa i.devadd = devadd; /* Insert right devadd in ptw */
416 if count
417 then records = records + 1;
418
419 end;
420 call loop_up_fms;
421 if records ^= 0
422 then do;
423 astep -> aste.fmchanged = "1"b; /* Make sure we get an update_vtoce */
424 if ^astep -> aste.nqsw
425 then if astep -> aste.dirsw
426 then call quotaw$cu_for_pc astep -records "1"b;
427 else if astep -> aste.par_astep
428 then call quotaw$cu_for_pc ptr astep astep -> aste.par_astep -records "0"b;
429 astep -> aste.records = bit fixed fixed astep -> aste.records 9 - records 9 9;
430 end;
431
432 /* Now update the current segment length */
433
434 do i = min first_page - 1 last_page to 0 by -1;/* min traps truncate to addr > aste size */
435 devadd = ptp -> mptwa i.devadd;
436 if ptp -> atptwa i.core
437 then goto update_csl;
438 if devadd_add_type & add_type.non_null
439 then if ^devadd_null_flag
440 then go to update_csl;
441 end;
442 update_csl:
443 astep -> aste.csl = bit fixed i + 1 9 9;
444
445 if first_page = 0
446 then do;
447 astep -> aste.damaged = "0"b; /* empty is undamaged */
448 astep -> aste.fm_damaged = "0"b;
449 end;
450
451 call page$cam; /* make sure our work takes */
452 call pmut$unlock_ptl oldmask ptwp; /* unlock and unmask */
453 if tr_count_sw
454 then N_In_Core = n_in_core; /* return for meter for callers that want. */
455 return;
456 %page;
457 dumper_get_file_map:
458 entry Astep Copy_Astep File_Mapp Deposit_Count Listp Pageno_Listp;
459 /* dumper entry for VTOCE update */
460
461 dumper = "1"b;
462 goto get_file_map_common;
463
464 get_file_map:
465 entry Astep Copy_Astep File_Mapp Deposit_Count Listp Pageno_Listp;
466 /* entry for VTOC update */
467
468
469 dumper = "0"b;
470 get_file_map_common:
471 astep = Astep; /* Copy astep */
472 add_to_dmpr_map = "0"b;
473 sstp = addr sst_seg$; /* get SST base ptr */
474 fmp = File_Mapp;
475 cmp = sstp -> sst.cmp; /* get core map ptr */
476 last_page = sstp -> sst.pts fixed astep -> aste.ptsi 2 - 1;
477 no_deposit_no_return = Listp = null | aste.ddnp;
478 getfmap_csl, getfmap_np, getfmap_nrec = 0; /* Init counters */
479 offed_sw = "0"b; /* Don't need cam */
480 return_pageno = Pageno_Listp ^= null ;
481
482 call pmut$lock_ptl oldmask ptwp; /* Lock the pagetable lock */
483
484 sstp = addr sst_seg$;
485 j = 0; /* Init deposit index */
486 do i = 0 to last_page; /* Walk the table */
487 ptp = addrel astep sstp -> sst.astsize + i;
488 /* Get one page tbl ptr */
489 devadd = ptp -> mptw.devadd; /* Get address from ptw */
490 if devadd_bits.disk
491 then do; /* Disk addr, could be nulled */
492 if devadd_null_flag & ^no_deposit_no_return
493 then do; /* put in deposit list */
494 devadd_null_flag = "0"b; /* zero the special internal flag */
495 deposit_list j = devadd;
496 /* set to give to outside world */
497 if return_pageno
498 then pageno_list j = i;
499
500 j = j + 1; /* one more depositable address processed */
501 devadd = get_file_map_vt_null_addr;
502 ptp -> mptw.devadd = devadd;
503 /* coded null to file map and page table */
504 end;
505 else if devadd_null_flag & dumper
506 then devadd = get_file_map_vt_null_addr;
507 end;
508 if devadd_bits.core
509 then do; /* A core address- move on up storage levels */
510 if ptw.phm
511 then do; /* Must off phm */
512 ptw.phm1 = "1"b; /* Mark mod status */
513 ptw.phm = "0"b; /* OFF PHM */
514 offed_sw = "1"b;
515 end;
516 cmep = addr cmp -> cma core_ptw.frame;
517 devadd = cmep -> cme.devadd; /* Reconsider this devadd */
518 if devadd_null_flag & ^ptw.phm1 & ^ptw.os & cme.io
519 then devadd = get_file_map_vt_null_addr;
520 /* This avoids damage to pure nulls incore */
521 end;
522 if devadd_null_flag
523 then if dumper
524 then devadd = get_file_map_dumper_non_null_addr;
525 else do;
526 devadd = get_file_map_vt_null_addr;
527 devadd_null_flag = "1"b;
528 end; /* if page is not on disk yet, or trunced,
529 we cannot fault in this page should we crash */
530 else devadd_null_flag = devadd_add_type = "0000"b;
531 /* Set outside-world null representation */
532
533 if ^devadd_null_flag
534 then do; /* Real page */
535 getfmap_nrec = getfmap_nrec + 1;
536 getfmap_csl = i + 1;
537 if atptw.core
538 then getfmap_np = getfmap_np + 1;
539 end;
540
541 rfm i = devadd; /* Send out agreed-upon devadd */
542 end;
543 curtime = clock ; /* loop_up_fms MAY do this, but we must be sure */
544 if offed_sw
545 then do;
546 call loop_up_fms; /* Pages were noted as modified. */
547 call page$cam; /* We turned off phm bits. */
548 end;
549
550 if aste.fms
551 then add_to_dmpr_map = "1"b;
552 if ^aste.gtus
553 then if aste.np | aste.infp
554 then /* have pages in, or subordinate astes */
555 aste.dtu = bit fixed curtime 52 52;
556 /* call it -in use- */
557 copy_aste = astep -> aste; /* Copy ASTE structure */
558
559 /* Update perishable items consistently to caller */
560
561 astep -> aste.fms = "0"b; /* copy_aste has old value - this
562 assignment constitutes segment control's
563 recognition of modification */
564 if ^dumper
565 then do;
566 astep -> aste.fmchanged1 = astep -> aste.fmchanged;
567 /* Dont' lose fmchanged until updatev
568 turns this off, but ... */
569 astep -> aste.fmchanged = "0"b; /* turn off p_c maintained bit. */
570 end;
571 call pmut$unlock_ptl oldmask ptwp; /* And unlock the pagetables */
572 /* Use following items to avoid damaging */
573 /* segments with incore nonmod nulls. */
574 /* Copy out data to caller */
575
576 copy_aste.np = bit fixed getfmap_np 9 9;
577 copy_aste.records = bit fixed getfmap_nrec 9 9;
578 copy_aste.csl = bit fixed getfmap_csl 9 9;
579
580 unspec Copy_Astep -> aste = unspec copy_aste; /* Copy the s into our callers copy */
581
582 do i = 0 to last_page;
583 fmp -> file_map.fm i = rfm i; /* Upper bits into file map */
584 end;
585
586 do i = 0 to j - 1; /* copy out depositable addresses */
587 Address_Array i = deposit_list i;
588 if return_pageno
589 then Pageno_List i = pageno_list i;
590 end;
591 Deposit_Count = j; /* deposit count */
592 if add_to_dmpr_map & ^aste.nid & ^aste.per_process & ^aste.hc_sdw
593 then call dbm_man$set_incr fixed aste.pvtx 17 fixed aste.vtocx 17 0;
594
595 if pc_trace
596 then do;
597 call trace "get_file_map^-astep = ^p fmp = ^p" astep fmp;
598 if last_page <= 4
599 then call trace half_line_of_words ptp -> fword 0 ptp -> fword 1 ptp -> fword 2
600 ptp -> fword 3;
601 else do;
602 do i = 0 to last_page by 8;
603 call trace line_of_words ptp -> fword i ptp -> fword i + 1
604 ptp -> fword i + 2 ptp -> fword i + 3 ptp -> fword i + 4
605 ptp -> fword i + 5 ptp -> fword i + 6 ptp -> fword i + 7;
606 end;
607 end;
608 end;
609 return;
610 %page;
611 updates:
612 entry Astep; /* Entry to set file modified switches. */
613
614 astep = Astep; /* Copy arg to avoid page fault. */
615 sstp = addr sst_seg$;
616 call pmut$lock_ptl oldmask ptwp; /* lock and mask */
617 call loop_up_fms;
618 go to quit;
619
620 update_incore_fms:
621 entry Astep; /* used to get fms as accurate as possible */
622
623
624 astep = Astep;
625 sstp = addr sst_seg$;
626 ptp = addrel astep sst.astsize;
627
628 if aste.np = "000"b3
629 then return;
630 offed_sw = "0"b;
631
632
633 do i = 0 to fixed aste.csl 9 - 1;
634 if ptwa i.phm
635 then do;
636 offed_sw = "1"b; /* remeber to cam */
637 ptwa i.phm1 = "1"b; /* Needed for real write */
638 ptwa i.phm = "0"b; /* This statement order is critical */
639 end;
640 end;
641
642 if offed_sw
643 then do;
644 call loop_up_fms;
645 call page$cam;
646 end;
647
648 return;
649
650 loop_up_fms:
651 proc; /* Set fms up tree for hierarchy dumper. */
652
653 dcl astep1 pointer;
654
655 if aste.gtms
656 then return;
657 curtime = clock ;
658 astep1 = astep;
659 do while rel astep1;
660 astep1 -> aste.fms = "1"b;
661 astep1 -> aste.dtm = bit fixed curtime 52 52;
662 astep1 = ptr astep1 astep1 -> aste.par_astep;
663 end;
664
665 end loop_up_fms;
666
667 /* You do not have to lock the page table or clear the AM for any of this. Phm1 will
668 always be taken as a signal to write, and page$pwrite will turn them both off when
669 camming. Once phm1 is on, failure to set phm, for not camming, is invisible. However, we
670 do cam at the end so that the next call to this will get phms. */
671 %page;
672 flush:
673 entry; /* here to write out all of core */
674
675 /* Synchronized pages are handled as follows:
676
677 flush_core - Page Control page$pwrite does the right thing, based on
678 the time stamp in the page.
679
680 flush - Modified synchronized pages are abandoned. This is safe, due to
681 Ring-2 Data Management protocols.
682
683 */
684
685 dcl flushing_for_pleasure bit 1;
686 dcl hedonism fixed bin;
687 dcl pleasure_flush_count fixed bin;
688
689 flushing_for_pleasure = "0"b;
690 go to flush_join;
691
692 flush_core:
693 entry; /* here to start writes for all core. */
694
695 flushing_for_pleasure = "1"b;
696
697 flush_join:
698 sstp = addr sst_seg$; /* get pointers, and lock */
699 pvt_arrayp = addr pvt$array;
700 cmp = sstp -> sst.cmp;
701 if flushing_for_pleasure
702 then hedonism = divide sst.write_limit 2 17 0;
703 pleasure_flush_count = 0;
704 call pmut$lock_ptl oldmask ptwp; /* lock and mask */
705 start_flush:
706 do i = sst.first_core_block to sst.last_core_block;
707 /* index thru all cmes */
708 ind = -1; /* no wait event */
709 cmep = addr cmp -> cma i;
710
711 if cme.ptwp ^= "000000"b3
712 then do; /* has real page */
713 ptp = ptr sstp cme.ptwp; /* get ptp */
714 astep = ptr sstp cme.astep; /* get astep */
715 if ^aste.hc_part
716 then do; /* Don't bother with HC part segs */
717 if ptw.os
718 then ind = fixed rel ptp 18;
719 /* if event, wait on it */
720 else do;
721 pageno =
722 fixed rel ptp 18 - fixed rel astep 18 - sstp -> sst.astsize;
723 devadd = cme.devadd;
724 if ptw.phm | ptw.phm1
725 then /* Needs writing */
726 if drive_ok aste.pvtx
727 then /* dont io bad disk */
728 if flushing_for_pleasure
729 then if cme.phm_hedge
730 then do;
731 call page$pwrite astep pageno;
732 sst.hedge_writes = sst.hedge_writes + 1;
733 pleasure_flush_count = pleasure_flush_count + 1;
734 end;
735 else cme.phm_hedge = ^aste.per_process;
736 /* change when we prevail across crashes */
737 /* if significant, write next time, if not written */
738 else do;
739 /* shutdown */
740 if aste.synchronized
741 then ptw.phm, ptw.phm1 = "0"b;
742 /* Abandon modified synch pages */
743 else call page$pwrite astep pageno;
744 end;
745 if ^flushing_for_pleasure
746 /* shutdown */
747 then if ^ptw.phm | ptw.phm1 | ptw.os
748 /* Unmodified */
749 then if devadd_null_flag
750 /* Null address */
751 then call page$pcleanup astep pageno;
752 /* Reflect quota */
753 if ptp -> ptw.os
754 then /* if still being written, wait for it */
755 ind = fixed cmp -> cma i.ptwp 18;
756 if sstp -> sst.wtct > sstp -> sst.write_limit
757 then /* if too many queued then */
758 if ind > 0 & ^flushing_for_pleasure
759 then call wait_then_go_to start_flush;
760 /* wait for one */
761 if pleasure_flush_count >= hedonism
762 then do; /* All done with PTW */
763 pleasure_flush_count = 0;
764 /* time for a nap */
765 call pmut$unlock_ptl oldmask ptwp;
766 if flushing_for_pleasure
767 then call pxss$relinquish_priority;
768 call pmut$lock_ptl oldmask ptwp;
769 end;
770 end;
771 end;
772 end;
773 end; /* end of cme array loop */
774
775 if ind > 0 & ^flushing_for_pleasure
776 then call wait_then_go_to start_flush; /* Wait if shutdown and there is stuff to wait for */
777 go to quit; /* done */
778 %page;
779 list_deposited_add:
780 entry Astep First_Page Last_Page Records Listp Pageno_Listp;
781 /* output deposits to seg ctl */
782
783
784 astep = Astep; /* copy params */
785 first_page = First_Page; /* place to start */
786 last_page = Last_Page; /* place to stop */
787 return_pageno = Pageno_Listp ^= null ;
788 sstp = addr sst_seg$; /* set up sstp */
789 ptp = addrel astep sstp -> sst.astsize;
790
791 records = 0; /* init count of depositable records */
792
793 call pmut$lock_ptl oldmask ptwp; /* lock the PTL for real work */
794
795 if last_page < 0 /* Scan whole page table */
796 then last_page = sst.pts fixed astep -> aste.ptsi 2 - 1;
797
798 do i = first_page to last_page; /* loop thru all ptws in ptl */
799
800 devadd = ptp -> mptwa i.devadd; /* assume devadd in ptw -- */
801
802 /* Any page in core or on the PD which has a nulled address
803 has a right to it: hence, we only list those in the PTW */
804
805 if devadd_bits.disk
806 then if devadd_null_flag
807 then do; /* a real deposited address */
808 deposit_list records = devadd;
809 /* move to output array */
810 if return_pageno
811 then pageno_list records = i;
812 records = records + 1; /* bump counter */
813 ptp -> mptwa i.devadd, devadd = list_deposit_null_addr;
814 end;
815 end;
816
817 call pmut$unlock_ptl oldmask ptwp; /* unlock the page tables */
818 do i = 0 to records - 1;
819 Address_Array i = deposit_list i; /* return to argument array */
820 if return_pageno
821 then Pageno_List i = pageno_list i;
822 end;
823
824 Records = records; /* return the count */
825 return;
826 %page;
827 deposit_list:
828 entry Pvtx Records Listp Vtocx Pageno_Listp; /* entry to deposit a list of addresses */
829
830
831 records = Records; /* number of records to be deposited */
832 pvtx = Pvtx; /* phys volume index */
833
834 /* The paged fsdct strategy states that the page table lock need
835 not be locked to deposit. Nobody can withdraw our bit unless we
836 have a problem, and if we find an unprotected address at
837 the time we deposit, this will be the case irrespective
838 of the page table lock. */
839
840 do i = 0 to records - 1;
841 Devadd_Array i.add_type = add_type.disk; /* Make up for sins of vtoc_man */
842 end;
843
844 call page$deposit_list pvtx Listp 1 records Vtocx Pageno_Listp;
845
846 return;
847
848
849 /* Auxiliary entry for truncation/deposition of vtoceless segs */
850
851 truncate_deposit_all:
852 entry Astep;
853
854
855 astep = Astep; /* Copy astep */
856
857 if aste.uid
858 then call syserr 1 "pc: truncate_deposit_all call on VTOCed seg at ^p" astep;
859 call truncate astep 0; /* Clean up w.r.t. pc */
860
861 if aste.hc_sdw
862 then return; /* Don't attempt semi-hc deposit */
863
864 call list_deposited_add astep 0 -1 records addr deposit_list null ;
865
866 call page$deposit_list aste.pvtx addr deposit_list 1 records -1 null ;
867
868 return;
869 %page;
870 move_page_table:
871 entry Old_Astep New_Astep;
872
873
874 sstp = addr sst_seg$;
875 cmp = sstp -> sst.cmp;
876 old_astep = Old_Astep;
877 new_astep = New_Astep;
878 call pmut$lock_ptl oldmask ptwp; /* lock and mask */
879
880 if pc_trace
881 then call trace "move_page_table^-old astep = ^p new astep = ^p" old_astep new_astep;
882
883 old_ptp = addrel old_astep sstp -> sst.astsize;/* get pointer to old page table */
884 new_ptp = addrel new_astep sstp -> sst.astsize;/* get pointer to new page table */
885 do i = 0 to sstp -> sst.pts fixed old_astep -> aste.ptsi 3 - 1;
886 new_ptp -> ptwa_bits i = old_ptp -> ptwa_bits i;
887 /* copy page table words */
888
889 old_ptp -> ptwa_bits i = null_devadd_not_in_core;
890 old_ptp -> mptwa i.devadd = pc_move_page_table_1_null_addr;
891 ptp = addr new_ptp -> ptwa i; /* point to specific ptw */
892 if atptw.core
893 then do; /* ptw describes core */
894 cmep = addr cmp -> cma core_ptw.frame;
895 /* address CME */
896 cme.ptwp = rel ptp; /* associate CME with new PTW */
897 cme.astep = rel new_astep; /* ditto ASTE */
898 devadd = cme.devadd; /* get devadd from cme if in core */
899 if cme.notify_requested /* if someone was waiting on old PTW event, then notify .. */
900 then call pxss$notify fixed rel addr old_ptp -> ptwa i 18;
901 /* him, causing him to rewait on new event */
902 end;
903 else devadd = mptw.devadd; /* get devadd out of ptw if not in core */
904 end;
905
906 do i = sstp -> sst.pts fixed old_astep -> aste.ptsi 3
907 to sstp -> sst.pts fixed new_astep -> aste.ptsi 3 - 1;
908
909 new_ptp -> ptwa_bits i = null_devadd_not_in_core;
910 new_ptp -> mptwa i.devadd = pc_move_page_table_2_null_addr;
911 end;
912
913 /* Now copy the old ASTE into the new ASTE, except fp, bp, ptsi and marker */
914
915 new_astep -> aste_part.two = old_astep -> aste_part.two;
916
917 go to quit;
918 %page;
919
920
921 segmove:
922 entry Move_Astep Old_Astep New_Astep New_Pvtx New_Vtocx Records Listp Pageno_Listp Code;
923
924 astep = Move_Astep; /* aste under segmove */
925 old_astep = Old_Astep; /* put old addresses here for pcrsst */
926 new_astep = New_Astep; /* put new addresses here for pcrsst or caller to deposit */
927 new_pvtx = New_Pvtx; /* we can reference them without the */
928 new_vtocx = New_Vtocx; /* AST lock */
929 sstp = addr sst_seg$;
930 cmp = sst.cmp;
931 new_ptp = addwordno new_astep sst.astsize; /* use that page table
932 to store up addresses on new volume */
933 old_ptp = addwordno old_astep sst.astsize; /* use that page table
934 to remember old addesses for the purposes of pcrsst */
935 move_ptp = addwordno astep sst.astsize; /* this is the page table of affliction. */
936
937 if astep -> aste.ptsi ^= new_astep -> aste.ptsi | new_astep -> aste.ptsi ^= old_astep -> aste.ptsi
938 then do;
939 Code = error_table_$bad_arg;
940 return;
941 end;
942
943 last_page = sst.pts fixed astep -> aste.ptsi 2 - 1;
944
945 call lock$lock_fast addr sst.segmove_lock; /* Only one at a time */
946 sst.segmove_new_addr_astep = new_astep; /* pc_check_tables_ should deposit anything in here
947 or at least bang on the pvte inconsistency count. */
948
949 call pmut$lock_ptl oldmask ptwp; /* will be unlocked if we have to wait */
950
951 /**** Note that deposit_list is declared 0:255 and page$deposit_list expects a
952 1:256 array. withdraw_list expects 0:255. Shouldn't be any trouble */
953
954 segmove_records_in_hand = 0;
955 segmove_total_records, /* This many is the grand total that we have accumulated */
956 segmove_records_needed /** This many are the number that we need to add to the record pile */
957 = fixed astep -> aste.records 9; /* This is the first guess as to the total number of records needed */
958 /* However, the guess may be too low since the PTL is unlocked. So */
959 /* even when we get records_in_hand up and records_needed to 0, we may */
960 /* have to add to total_records and reset records_needed to get the rest */
961
962
963 move_tries = 0;
964
965 augment_record_pile:
966 /**** + Debug
967 call syserr ANNOUNCE "pc: at ARP aste: np = ^d records = ^d csl = ^d" fixed aste.np fixed aste.records fixed aste.csl;
968 */
969 code = 0;
970 do while segmove_records_needed > 0 & code = 0; /* keep calling until free_store gives all we want */
971 call page$withdraw_list new_pvtx new_ptp segmove_records_in_hand segmove_records_needed ind code;
972 /* since parm3 is zero based, zero records_in_hand is interpreted */
973 /* as "put the next record in slot zero" which deposit addresses as */
974 /* slot one. */
975
976 if ind ^= 0
977 then /* wait for volmap */
978 call wait_then_go_to augment_record_pile;
979 end;
980 if code ^= 0
981 then do; /* out-of-volume */
982 Code = code;
983 go to SEGMOVE_ABORT_RETURN;
984 end;
985
986 /**** At this point, we own all the records we need. We can release the
987 PTL while we drag the segment into memory. */
988
989 /**** NOTE -- at this point new_ptp contains segmove_total_records records.
990 segmove_records_needed can be re-used.
991 if we find that we need more records, total_records will grow,
992 but in_hand will continue to be the number of addresses in new_addr_aste. */
993
994 move_retry:
995 segmove_records_needed = 0; /* re-count the number we need under the PTL */
996
997 /**** + Debug
998 call syserr ANNOUNCE "pc: at MRT aste: np = ^d records = ^d csl = ^d" fixed aste.np fixed aste.records fixed aste.csl;
999 */
1000
1001 move_tries = move_tries + 1;
1002 if move_tries > 1000
1003 then go to SEGMOVE_ABORT_RETURN;
1004
1005 n_io_started = 0;
1006 SEGMOVE_EXAMINE_PAGES:
1007 do i = 0 to last_page; /* get all pages into memory */
1008 RE_EXAMINE_PAGE:
1009 if move_ptp -> ptwa i.os
1010 then do; /* wait for i and also o quiesce */
1011
1012 ind = wordno addr move_ptp -> ptwa i;
1013 /* event to wait on */
1014 n_io_started = n_io_started + 1;
1015 if n_io_started > sst.segmove_io_limit
1016 then call wait_then_go_to move_retry;
1017 end;
1018 else if move_ptp -> atptwa i.disk
1019 then do;
1020 sst.segmove_n_reads = sst.segmove_n_reads + 1;
1021 call page$pread astep i temp_ind;
1022 /* put event into temporary... */
1023 if temp_ind ^= 0
1024 then do;
1025 ind = temp_ind; /* OK to mung it now... */
1026 n_io_started = n_io_started + 1;
1027 if n_io_started > sst.segmove_io_limit
1028 then call wait_then_go_to move_retry;
1029 end;
1030 else go to RE_EXAMINE_PAGE; /* ZERO! */
1031 end;
1032 else if move_ptp -> atptwa i.core
1033 then do; /* in memory - keep it there */
1034 segmove_records_needed = segmove_records_needed + 1;
1035 /* got another real one in memory */
1036 cmep = addr cmp -> cma move_ptp -> core_ptwa i.frame;
1037 cme.pin_counter = 1000;
1038 if astep -> aste.synchronized & move_ptp -> core_ptwa i.phm | move_ptp -> core_ptwa i.phm1
1039 /* any modified page of a synch segment is held until proven elsewise */
1040 then call segmove_synch_page astep cmep i;
1041 end;
1042 else if move_ptp -> ptwa i.add_type ^= "0000"b
1043 /* mysterious non-null */
1044 then /* but unknown! */
1045 call syserr CRASH "pc$segmove: unexpected address type ^4b" move_ptp -> ptwa i.add_type;
1046 end SEGMOVE_EXAMINE_PAGES;
1047
1048 /**** At arrival here, the PTL is locked nothing can be evicted
1049 and either all the pages are in memory, or we have some read-ahead
1050 activity. */
1051
1052 if n_io_started > 0
1053 then call wait_then_go_to move_retry; /* ind is last read ahead page */
1054
1055 sst.segmove_max_tries = max move_tries sst.segmove_max_tries;
1056
1057 /**** No read aheads. all pages found in core, PTL is locked.
1058 Start final countdown. Unless, somehow, the segment grew ... */
1059
1060 if segmove_records_needed > segmove_total_records
1061 then do; /* When we counted under the PTL and made them stand still, we found more of them. */
1062 segmove_total_records = segmove_records_needed;
1063 /* new count is the right count */
1064 segmove_records_needed = segmove_records_needed - segmove_records_in_hand;
1065 /* count of additional records required */
1066 go to augment_record_pile; /* get 'em */
1067
1068 end;
1069
1070 /**** We have an adequate supply of records on the new volume,
1071 and everything is in memory. Here we go... */
1072
1073 /**** Since the move segment page table is in its final state
1074 all addresses null or in core we can copy all the ptw's
1075 to the old_addr_aste. pcrsst will find them there and
1076 put them back. All the new addreses have been accumulated
1077 in the new_addr_aste, where shutdown can deposit them.
1078
1079 Thus the rules are: if new_addr_astep ^= null , deposit
1080 all the non-null addresses in its page table. pc_check_tables_
1081 does not currently concern itself with deposits, so these
1082 addresses are abandoned.
1083
1084 if the move_astep ^= null , then copy the page table
1085 from the old_addr_aste to the move_aste. The old_addr_astep
1086 is guaranteed to be non-null.
1087
1088 if the old_addr_astep ^= null, then zap all its ptw's
1089 to be null addresses. */
1090
1091 sst.segmove_old_addr_astep = old_astep; /* still full of nulls */
1092 /* now, pcrsst will zero all these ptw's */
1093
1094 begin; /* copy the page table wholesale from move to old astep */
1095 declare pt 0:last_page bit 36 aligned based;
1096 old_ptp -> pt = move_ptp -> pt;
1097 end; /* this can be copied back verbatim by pc_check_tables_
1098 since we are under the PTL and nothing can change. */
1099
1100 sst.segmove_pvtx = astep -> aste.pvtx;
1101 sst.segmove_vtocx = astep -> aste.vtocx;
1102 sst.segmove_astep = astep; /* now, pcrsst will copy all the devadds from old to here */
1103
1104 /**** Now it only takes one loop to put the new disk devadds into
1105 the move aste. */
1106
1107 segmove_records_used = 0;
1108
1109 if segmove_total_records < fixed aste.np
1110 then call syserr CRASH "pc$segmove: miscounted pages.";
1111
1112 do i = 0 to last_page; /* now swap addresses */
1113 devadd = move_ptp -> mptwa i.devadd; /* either core or null */
1114 /**** + Debug
1115 call syserr ANNOUNCE "sgm: page ^d ptw devadd ^.3b"
1116 i devadd;
1117 */
1118 if devadd_add_type & add_type.core ^= ""b /* core */
1119 then do;
1120 if segmove_records_used > segmove_records_in_hand
1121 then call syserr CRASH "pc$segmove: out of records during move";
1122 cmep = addr cmp -> cma move_ptp -> core_ptwa i.frame;
1123 move_ptp -> core_ptwa i.phm1 = "1"b;
1124 /* modify! */
1125 /* it will get hierarchy incrementalled, which is unfortunate */
1126 segmove_deposit_list segmove_records_used = cme.devadd;
1127 /**** + Debug
1128 call syserr ANNOUNCE "sgm: old cme devadd ^.3b" cme.devadd;
1129 */
1130 pageno_list segmove_records_used = i;
1131 devadd = new_ptp -> mptwa segmove_records_used.devadd;
1132 /* new record address + disk flag */
1133 /**** + Debug
1134 call syserr ANNOUNCE "sgm: new devadd ^.3b" devadd;
1135 */
1136 new_ptp -> mptwa segmove_records_used.devadd = segmove_new_addr_null_addr;
1137 /* order here is noncritical,
1138 pc check tables will zonk all of these anyway */
1139 devadd_null_flag = "1"b; /* you're not on disk yet, buddy! */
1140 cme.devadd = devadd;
1141 cme.phm_hedge = "1"b;
1142 /**** + Debug
1143 call syserr ANNOUNCE "sgm: new devadd in CME ^.3b" devadd;
1144 */
1145 cme.pin_counter = 0; /* don't hold page any longer */
1146 segmove_records_used = segmove_records_used + 1;
1147 end;
1148 end;
1149
1150 if sst.crash_test_segmove
1151 then call syserr CRASH "pc$segmove: crashing in segment mover.";
1152
1153 astep -> aste.pvtx = new_pvtx; /* finish the swap */
1154 astep -> aste.vtocx = new_vtocx; /* ... */
1155 astep -> aste.fmchanged = "1"b; /* ... */
1156
1157 sst.segmove_astep = null; /* dont fix addresses, pvtx, or vtocx.
1158 and dont copy page table from old_addr_aste */
1159 sst.segmove_pvtx = 0;
1160 sst.segmove_vtocx = 0;
1161
1162 /**** Now cleanup the old addresses, unbinding them from PTW's etc. */
1163
1164 begin;
1165 declare pt 0:last_page bit 36 based;
1166 declare px fixed bin;
1167
1168 declare 1 nptw aligned like l68_ptw;
1169 declare ptwp pointer;
1170
1171 unspec nptw = ""b;
1172 nptw.add = segmove_old_addr_null_addr; /* thats whats left */
1173 do px = 0 to last_page;
1174 ptwp = addr old_ptp -> pt px; /* all are core addresses, we are under PTL after verifying that */
1175 devadd = ptwp -> mptw.devadd;
1176 if devadd_add_type & add_type.non_null ^= ""b
1177 then do;
1178 if devadd_add_type & add_type.core = ""b
1179 then call syserr CRASH "pc$segmove: non-memory PTW in old_addr_aste.";
1180 old_ptp -> pt px = unspec nptw;
1181 end;
1182 end;
1183 end;
1184 sst.segmove_old_addr_astep = null ;
1185
1186 call pmut$unlock_ptl oldmask ptwp;
1187
1188 if segmove_records_in_hand > segmove_records_used
1189 then /* some records on new pvt left over */
1190 call page$deposit_list new_pvtx new_ptp segmove_records_used + 1
1191 segmove_records_in_hand - segmove_records_used -1 null ;
1192
1193 call lock$unlock_fast addr sst.segmove_lock;
1194
1195 Address_Array = segmove_deposit_list; /* out from under PTL */
1196 Pageno_List = pageno_list; /* so we can copy to unwired stack_0 */
1197 Records = segmove_records_used; /* starts at zero, used as index
1198 to zero-based array, then bumped. */
1199
1200 return;
1201
1202 SEGMOVE_ABORT_RETURN:
1203 call pmut$unlock_ptl oldmask ptwp;
1204 if segmove_records_in_hand > 0
1205 then call page$deposit_list new_pvtx new_ptp 1 segmove_records_in_hand -1 null ;
1206 /* Abandon all the records that we collected */
1207 if Code = 0
1208 then /** we may have a specific code */
1209 Code = error_table_$action_not_performed;
1210 call lock$unlock_fast addr sst.segmove_lock;
1211 return;
1212 ^L
1213
1214 segmove_synch_page:
1215 procedure astep cmep pagex;
1216
1217 declare astep cmep pointer;
1218 declare pagex fixed bin;
1219
1220
1221
1222 /**** Call page control to write the page itself. If the synch_hold
1223 is legit, then .synch_hold will still be on when pwrite returns.
1224 If .synch_hold is off, the page is no longer held. */
1225
1226 call page$pwrite astep pagex;
1227
1228 if ^cmep -> cme.synch_held
1229 then do;
1230 sst.segmove_synch_disappeared = sst.segmove_synch_disappeared + 1;
1231 return; /* page is fine, we can move it */
1232 end;
1233
1234 Code = error_table_$synch_seg_segmove;
1235 go to SEGMOVE_ABORT_RETURN;
1236 end segmove_synch_page;
1237
1238
1239 %page;
1240 drive_ok:
1241 proc pvtx returns bit 1 aligned; /* test drive state */
1242
1243 dcl pvtx fixed bin;
1244
1245 return ^pvt_array pvtx.device_inoperative;
1246
1247 end drive_ok;
1248 %page;
1249 wait_then_go_to:
1250 procedure lab; /* quick internal proc to trace and wait for
1251 page control events */
1252 dcl lab label local;
1253
1254 if ind = 0
1255 then call syserr CRASH "pc: waiting for zero event.";
1256
1257 if pc_trace
1258 then call trace "wait for i/o";
1259 call page$cam; /* make sure any work done so far gets done */
1260 call page$pwait ind; /* wait for event */
1261 go to lab;
1262
1263 end wait_then_go_to;
1264
1265 /* format: off */
1266 %page; %include sst;
1267 %page; %include pvte;
1268 %page; %include cmp;
1269 %page; %include aste;
1270 %page; %include fm;
1271 %page; %include null_addresses;
1272 %page; %include add_type;
1273 %page; %INCLUDE "ptw.macro";
1274 %page; %include syserr_constants;
1275 %page;
1276 /* BEGIN MESSAGE DOCUMENTATION
1277
1278 Message:
1279 pc: unprotected address DDDDD in DSKX_NN VTOCX
1280
1281 S: $info
1282
1283 T: $run
1284
1285 M: The disk address DDDDD
1286 is not marked as protected
1287 in the record usage map for the volume mounted on DSKX_NN.
1288 This condition has been discovered
1289 while activating the segment with VTOC index VTOCX.
1290 The segment's damaged switch is turned on, and a page of zeros will
1291 replace the bad address. This condition may be symptomatic of disk
1292 or other hardware failure.
1293
1294 A: $inform
1295
1296
1297 Message:
1298 pc: truncate_deposit_all call on VTOCed seg at ASTEP
1299
1300 S: $crash
1301
1302 T: $run
1303
1304 M: A call to pc$truncate_deposit_all
1305 has been made on a segment for which this operation is not allowed.
1306 The AST entry at ASTEP should have a zero unique ID
1307 but it does not.
1308 $err
1309 $crashes
1310
1311 A: $recover
1312
1313
1314 END MESSAGE DOCUMENTATION */
1315
1316 end pc;