1
2
3
4
5
6
7
8
9
10
11
12 scavenger:
13 proc (Pvtx, Pvid, Scavenger_Optionsp, Sc_metersp, Code);
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 dcl Pvtx fixed bin;
41 dcl Pvid bit (36) aligned;
42 dcl Scavenger_Optionsp ptr;
43 dcl Sc_metersp ptr;
44 dcl Code fixed bin (35);
45
46
47
48 dcl begin_clock fixed bin (71);
49 dcl begin_pf fixed bin;
50 dcl begin_vcpu fixed bin (71);
51 dcl code fixed bin (35);
52 dcl end_pf fixed bin;
53 dcl end_vcpu fixed bin (71);
54 dcl i_am_wired bit (1) aligned;
55 dcl 1 local_sc_meters aligned like sc_meters;
56 dcl 1 local_scavenger_options
57 aligned like scavenger_options;
58 dcl p99 pic "99";
59 dcl old_mask fixed bin (71);
60 dcl process_tablex fixed bin;
61 dcl ptwp ptr;
62 dcl scavenger_data_astep
63 ptr;
64 dcl started bit (1) aligned;
65
66
67
68 dcl N_OVFL fixed bin int static options (constant) init (1023);
69
70
71
72
73 dcl 1 Sc_meters aligned like sc_meters based (Sc_metersp);
74 dcl 1 Scavenger_Options aligned like scavenger_options based (Scavenger_Optionsp);
75
76
77
78 dcl error_table_$pvid_not_found
79 fixed bin (35) external;
80 dcl error_table_$unexpected_condition
81 fixed bin (35) external;
82 dcl error_table_$scavenge_process_limit
83 fixed bin (35) external;
84 dcl error_table_$pv_no_scavenge
85 fixed bin (35) external;
86 dcl pds$process_group_id
87 char (32) aligned external;
88 dcl pds$processid bit (36) aligned external;
89 dcl sst$astl bit (36) aligned external;
90
91
92
93 dcl condition_ entry (char (*), entry);
94 dcl get_ptrs_$given_segno
95 entry (fixed bin) returns (ptr);
96 dcl lock$lock_ast entry;
97 dcl lock$lock_fast entry (ptr);
98 dcl lock$unlock_ast entry;
99 dcl lock$unlock_fast entry (ptr);
100 dcl pc_wired$wire_wait entry (ptr, fixed bin, fixed bin);
101 dcl pc_wired$unwire entry (ptr, fixed bin, fixed bin);
102 dcl pmut$lock_ptl entry (fixed bin (71), ptr);
103 dcl pmut$unlock_ptl entry (fixed bin (71), ptr);
104 dcl scavenge_volume entry (ptr, ptr, ptr, ptr, fixed bin (35));
105 dcl syserr entry options (variable);
106 dcl syserr$binary entry options (variable);
107 dcl syserr$error_code entry options (variable);
108 dcl usage_values entry (fixed bin, fixed bin (71));
109 dcl verify_lock$condition_nolog
110 entry (character (*), pointer);
111 dcl wire_proc$wire_me entry;
112 dcl wire_proc$unwire_me entry;
113
114
115
116 dcl addr builtin;
117 dcl addrel builtin;
118 dcl baseno builtin;
119 dcl bin builtin;
120 dcl clock builtin;
121 dcl convert builtin;
122 dcl divide builtin;
123 dcl float builtin;
124 dcl null builtin;
125 dcl rel builtin;
126 dcl size builtin;
127 dcl unspec builtin;
128 %page;
129 started = "0"b;
130 i_am_wired = "0"b;
131
132 unspec (local_sc_meters) = ""b;
133 unspec (local_scavenger_options) = unspec (Scavenger_Options);
134
135 call SETUP_LOCK (Code);
136 if Code ^= 0
137 then return;
138
139 call SETUP_PROCESS_TABLE (process_tablex, code);
140 if code ^= 0
141 then goto CLEANUP_RETURN;
142
143 call SETUP_BLOCK (process_tablex);
144
145 pvte.scavenger_block_rel = rel (scavenger_blockp);
146 call lock$unlock_fast (addr (scavenger_data.lock));
147
148 call usage_values (begin_pf, begin_vcpu);
149 begin_clock = clock ();
150
151 call condition_ ("any_other", PRINT_ERROR);
152
153 call syserr (ANNOUNCE, "scavenger: Begin scavenge of ^a_^a^[^a^;^1s^] by ^a", pvte.devname,
154 convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name, pds$process_group_id);
155 started = "1"b;
156 call wire_proc$wire_me;
157 i_am_wired = "1"b;
158 call scavenge_volume (pvtep, scavenger_blockp, addr (local_scavenger_options), addr (local_sc_meters), code);
159
160 LOCK_CLEANUP_RETURN:
161 call lock$lock_fast (addr (scavenger_data.lock));
162
163 CLEANUP_RETURN:
164 if i_am_wired
165 then call wire_proc$unwire_me;
166
167 if started & (code = 0)
168 then do;
169 call usage_values (end_pf, end_vcpu);
170 local_sc_meters.n_scavenge = 1;
171 local_sc_meters.pf = end_pf - begin_pf;
172 local_sc_meters.vcpu = end_vcpu - begin_vcpu;
173 local_sc_meters.clock_time = clock () - begin_clock;
174 if local_scavenger_options.print_meters
175 then call PRINT_METERS;
176 scavenger_data.meters = scavenger_data.meters + local_sc_meters;
177 end;
178
179 call lock$lock_ast;
180 call pmut$lock_ptl (old_mask, ptwp);
181 pvte.scavenger_block_rel = ""b;
182 pvte.scav_check_address = "0"b;
183 pvte.deposit_to_volmap = "0"b;
184 call pmut$unlock_ptl (old_mask, ptwp);
185 call lock$unlock_ast;
186
187 if scavenger_blockp ^= null ()
188 then call RETURN_BLOCK (process_tablex);
189 if sc_process_tablep ^= null ()
190 then call RETURN_PROCESS_TABLE (process_tablex);
191
192 call lock$unlock_fast (addr (scavenger_data.lock));
193
194 if started
195 then do;
196 if code = 0
197 then call syserr (ANNOUNCE, "scavenger: Scavenge of ^a_^a^[^a^;^1s^] by ^a completed.", pvte.devname,
198 convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name, pds$process_group_id);
199 else call syserr$error_code (ANNOUNCE, code,
200 "scavenger: Scavenge of ^a_^a^[^a^;^1s^] by ^a completed with error.", pvte.devname,
201 convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name, pds$process_group_id);
202 end;
203
204 if Sc_metersp ^= null ()
205 then unspec (Sc_meters) = unspec (local_sc_meters);
206
207 Code = code;
208 return;
209 %page;
210
211
212 shutdown:
213 entry;
214
215 scavenger_datap = addr (scavenger_data$);
216 sc_process_tablep = scavenger_data.process_table_ptr;
217
218 do process_tablex = 1 to sc_process_table.max_n_processes;
219 if sc_process_table.process (process_tablex).processid ^= ""b
220
221 then do;
222 pvtep = sc_process_table.process (process_tablex).pvtep;
223 pvte.deposit_to_volmap = "0"b;
224 pvte.scav_check_address = "0"b;
225 pvte.scavenger_block_rel = ""b;
226 call syserr (ANNOUNCE, "scavenger: Scavenge of ^a_^a^[^a^] stopped.", pvte.devname,
227 convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name);
228 end;
229 end;
230
231 return;
232
233
234 %page;
235
236
237 SETUP_LOCK:
238 proc (Code);
239
240 dcl Code fixed bin (35);
241
242 scavenger_datap = addr (scavenger_data$);
243 sc_process_tablep = null ();
244 scavenger_blockp = null ();
245 pvt_arrayp = addr (pvt$array);
246 pvtep = addr (pvt_array (Pvtx));
247 scavenger_data_astep = get_ptrs_$given_segno (bin (baseno (scavenger_datap)));
248 Code = 0;
249
250 if pvte.pvid ^= Pvid
251 then do;
252 Code = error_table_$pvid_not_found;
253 return;
254 end;
255 if ^pvte.used | ^pvte.storage_system | (pvte.scavenger_block_rel ^= ""b)
256 then do;
257 Code = error_table_$pv_no_scavenge;
258 return;
259 end;
260
261 call lock$lock_fast (addr (scavenger_data.lock));
262
263 end SETUP_LOCK;
264 %page;
265
266
267 SETUP_PROCESS_TABLE:
268 proc (Process_Index, Code);
269
270 dcl Process_Index fixed bin;
271 dcl Code fixed bin (35);
272
273 dcl n_header_pages fixed bin;
274 dcl procx fixed bin;
275
276 Process_Index = -1;
277 Code = 0;
278
279 sc_process_tablep = scavenger_data.process_table_ptr;
280 if sc_process_table.n_processes >= sc_process_table.max_n_processes
281 then do;
282 RETURN_ERROR:
283 sc_process_tablep = null ();
284 Code = error_table_$scavenge_process_limit;
285 return;
286 end;
287
288 do procx = 1 repeat procx + 1 while (procx <= sc_process_table.max_n_processes);
289 if sc_process_table.process (procx).processid = ""b
290 then goto FOUND_EMPTY;
291 end;
292 goto RETURN_ERROR;
293
294 FOUND_EMPTY:
295 Process_Index = procx;
296 sc_process_table.process (procx).processid = pds$processid;
297 sc_process_table.process (procx).pvtep = pvtep;
298
299 sc_process_table.n_processes = sc_process_table.n_processes + 1;
300 if sc_process_table.n_processes = 1
301 then do;
302 n_header_pages = divide (size (scavenger_data) + 1023, 1024, 17);
303 call pc_wired$wire_wait (scavenger_data_astep, 0, n_header_pages);
304 end;
305
306
307 end SETUP_PROCESS_TABLE;
308 %page;
309
310
311 SETUP_BLOCK:
312 proc (Process_Index);
313
314 dcl Process_Index fixed bin;
315
316 dcl first_page fixed bin;
317 dcl n_pages fixed bin;
318
319
320 scavenger_n_records = pvte.totrec;
321 scavenger_n_ovfl = N_OVFL;
322
323 first_page = sc_process_table.process (Process_Index).first_block_page;
324 n_pages = divide (size (scavenger_block) + 1023, 1024, 17);
325
326 scavenger_blockp = sc_process_table.process (process_tablex).blockp;
327
328 scavenger_block.n_records = scavenger_n_records;
329 scavenger_block.n_ovfl = scavenger_n_ovfl;
330 scavenger_block.ovfl_free_ix = 1;
331
332 unspec (scavenger_block.records) = ""b;
333 unspec (scavenger_block.overflow) = ""b;
334
335
336 call pc_wired$wire_wait (scavenger_data_astep, first_page, n_pages);
337
338 sc_process_table.process (Process_Index).n_block_pages = n_pages;
339
340 end SETUP_BLOCK;
341 %page;
342
343
344 RETURN_BLOCK:
345 proc (Process_Index);
346
347 dcl Process_Index fixed bin;
348
349 dcl first_page fixed bin;
350 dcl n_pages fixed bin;
351
352
353 if sc_process_table.process (Process_Index).processid ^= pds$processid
354 then call syserr (CRASH, "scavenger: Invalid block reset");
355
356 first_page = sc_process_table.process (Process_Index).first_block_page;
357 n_pages = sc_process_table.process (Process_Index).n_block_pages;
358 call pc_wired$unwire (scavenger_data_astep, first_page, n_pages);
359
360
361
362 end RETURN_BLOCK;
363 %page;
364
365
366 RETURN_PROCESS_TABLE:
367 proc (Process_Index);
368
369 dcl Process_Index fixed bin;
370 dcl n_header_pages fixed bin;
371
372 if sc_process_table.process (Process_Index).processid ^= pds$processid
373 then call syserr (CRASH, "scavenger: Process table entry not owned by this process.");
374
375 sc_process_table.process (Process_Index).processid = ""b;
376 sc_process_table.process (Process_Index).pvtep = null ();
377 sc_process_table.process (Process_Index).n_block_pages = 0;
378
379 sc_process_table.n_processes = sc_process_table.n_processes - 1;
380 if sc_process_table.n_processes = 0
381 then do;
382 n_header_pages = divide (size (scavenger_data) + 1023, 1024, 17);
383 call pc_wired$unwire (scavenger_data_astep, 0, n_header_pages);
384 end;
385
386
387 end RETURN_PROCESS_TABLE;
388 %page;
389
390
391
392 PRINT_ERROR:
393 proc (Mcptr, Condition, Coptr, Infoptr, Continue) options (non_quick);
394
395 dcl Mcptr ptr;
396 dcl Condition char (*);
397 dcl Coptr ptr;
398 dcl Infoptr ptr;
399 dcl Continue bit (1) aligned;
400
401 dcl 1 auto_fault_msg aligned like fault_msg;
402 dcl ssptr ptr;
403
404
405 if Mcptr ^= null ()
406 then do;
407 ssptr = addrel (Mcptr, -8);
408
409
410 unspec (auto_fault_msg.mach_cond) = unspec (ssptr -> signaller_stack.mach_cond);
411 auto_fault_msg.hist_reg = ssptr -> signaller_stack.history_registers;
412
413 call syserr$binary (scavenger_data.error_severity, Mcptr, SB_hw_fault, SBL_hw_fault,
414 "scavenger: ^a condition signalled during scavenge of ^a_^a^[^a^;^1s^] by ^a", Condition,
415 pvte.devname, convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name,
416 pds$process_group_id);
417 end;
418 else do;
419 call syserr (scavenger_data.error_severity,
420 "scavenger: ^a condition signalled during scavenge of ^a_^a^[^a^;^1s^] by ^a", Condition,
421 pvte.devname, convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name,
422 pds$process_group_id);
423 end;
424
425 if sst$astl = pds$processid
426 then call lock$unlock_ast;
427 call verify_lock$condition_nolog (Condition, Mcptr);
428
429
430 code = error_table_$unexpected_condition;
431
432 goto LOCK_CLEANUP_RETURN;
433
434 end PRINT_ERROR;
435 %page;
436
437
438 PRINT_METERS:
439 proc;
440
441 dcl clock_sec float;
442 dcl vcpu_sec float;
443
444 vcpu_sec = float (local_sc_meters.vcpu) / 1.0e6;
445 clock_sec = float (local_sc_meters.clock_time) / 1.0e6;
446
447 call syserr (LOG,
448 "scavenger: Meters from scavenge of ^a_^a^[^a^;^1s^]. Clock=^6.1f vcpu=^6.1f pf=^d^/VTOCES: Total=^d Damaged=^d Per-Proc=^d Per-Boot=^d FMDamaged=^d Freed=^d^/Records: Total=^d Pot conflict=^d FMD Conflict = ^d Conflict=^d Lost=^d",
449 pvte.devname, convert (p99, pvte.logical_area_number), pvte.is_sv, pvte.sv_name, clock_sec, vcpu_sec,
450 local_sc_meters.pf, local_sc_meters.n_vtoces, local_sc_meters.n_vtoces_damaged,
451 local_sc_meters.n_vtoces_per_proc, local_sc_meters.n_vtoces_per_boot, local_sc_meters.n_vtoces_fmd,
452 local_sc_meters.n_vtoces_freed, local_sc_meters.n_records, local_sc_meters.n_conflicts,
453 local_sc_meters.n_fmd_conflicts, local_sc_meters.n_real_conflicts, local_sc_meters.n_lost_records);
454
455 end PRINT_METERS;
456
457 %page;
458 %include pvte;
459 %page;
460 %include scavenger_data;
461 %page;
462 %include syserr_binary_def;
463 %page;
464 %include syserr_constants;
465 %page;
466 %include syserr_fault_msg;
467 %page;
468 %include mc;
469 %page;
470 %include signaller_stack;
471 %page;
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
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
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579 end scavenger;