1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 vm_vio: proc;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 Note
37
38 dcl (pvtx, a_pvtx) fixed bin,
39 (vtocx, a_vtocx, devx) fixed bin,
40 (code, a_code) fixed bin (35);
41
42 dcl rec_size fixed bin internal static options (constant) init (1024);
43 dcl n_rec_per_seg fixed bin internal static options (constant) init (64);
44
45 dcl segnos_initialized bit (1) internal static init ("0"b);
46
47 dcl s (0 : 4) fixed bin internal static;
48
49 dcl 1 seg_list (0 : 4) internal static,
50 2 basep ptr,
51 2 recno fixed bin,
52 2 perm bit (1) aligned,
53 2 used bit (1) aligned;
54
55 dcl i fixed bin;
56 dcl ptp pointer;
57
58 dcl dseg$ (0 : 1023) fixed bin (71) external static;
59 dcl pds$processid ext bit (36) aligned;
60 dcl pvt$n_entries fixed bin external;
61 dcl salv_abs_seg_00$ external;
62 dcl salv_data$vol_read_ahead fixed bin external;
63 dcl sst$astl bit (36) aligned external;
64 dcl sst$astsize fixed bin external;
65 dcl 1 sst$level (0 : 3) aligned external,
66 2 ausedp bit (18) unaligned,
67 2 no_aste bit (18) unaligned;
68 dcl sst$pts (0 : 3) fixed bin external;
69
70 dcl get_aste entry (fixed bin) returns (ptr);
71 dcl get_ptrs_$given_astep entry (ptr) returns (fixed bin (71) aligned);
72 dcl get_ptrs_$given_segno entry (fixed bin) returns (ptr);
73 dcl lock$lock_ast entry;
74 dcl lock$unlock_ast entry;
75 dcl page$cam entry;
76 dcl pc$cleanup entry (ptr);
77 dcl pc_wired$read entry (ptr, fixed bin, fixed bin);
78 dcl pc_wired$write entry (ptr, fixed bin, fixed bin);
79 dcl ptw_util_$make_disk entry (pointer, fixed bin (20));
80 dcl ptw_util_$make_null entry (pointer, bit (22) aligned);
81 dcl put_aste entry (pointer);
82 dcl syserr entry options (variable);
83 dcl thread$out entry (pointer, bit (18) unaligned);
84
85 dcl (addr, addrel, baseno, baseptr, bit, divide, hbound, mod, null, ptr, fixed) builtin;
86
87 dcl cleanup condition;
88
89
90
91 get_vtocep : entry (a_pvtx, a_vtocx) returns (ptr);
92
93 pvtx = a_pvtx;
94 vtocx = a_vtocx;
95 pvt_arrayp = addr (pvt$array);
96 devx = pvt_array (pvtx).device_type;
97 vtocep = GET_VTOCEP (pvtx, vtocx);
98
99 return (vtocep);
100
101
102
103
104
105
106 init : entry (a_pvtx, a_code) returns (ptr);
107
108 pvtx = a_pvtx;
109 code = 0;
110 pvt_arrayp = addr (pvt$array);
111 devx = pvt_array (pvtx).device_type;
112 on cleanup call CLEAN_UP;
113
114 call INIT (pvtx, code);
115
116 a_code = code;
117
118 if code ^= 0 then do; call CLEAN_UP; return (null); end;
119
120 return (seg_list (0).basep);
121
122
123
124
125
126 clean_up : entry (a_pvtx);
127
128 pvtx = a_pvtx;
129 pvt_arrayp = addr (pvt$array);
130 devx = pvt_array (pvtx).device_type;
131 call CLEAN_UP;
132
133 return;
134 ^L
135 GET_VTOCEP : procedure (pvtx, vtocx) returns (ptr);
136
137
138
139
140
141
142
143 dcl pvtx fixed bin,
144 vtocx fixed bin;
145
146 dcl recno fixed bin;
147 dcl compno fixed bin;
148 dcl segno fixed bin;
149 dcl word_number fixed bin;
150
151 dcl vtoce_size fixed bin;
152 dcl n_vtoce_per_rec fixed bin;
153
154 dcl vtoce_ptr ptr;
155
156 dcl k fixed bin;
157
158
159 if pvtx <= 0 | pvtx > pvt$n_entries then
160 do;
161 call syserr (ANNOUNCE, "vm_vio: get_vtocep: invalid pvtx: ^oo", pvtx);
162 return (null);
163 end;
164 devx = pvt_array (pvtx).device_type;
165
166
167
168
169
170
171
172
173 vtoce_size = sect_per_vtoc (devx) * words_per_sect (devx);
174 n_vtoce_per_rec = divide (rec_size, vtoce_size, 17, 0);
175 recno = divide (vtocx, n_vtoce_per_rec, 17, 0) + VTOC_ORIGIN;
176 compno = get_segno (recno);
177 segno = s (compno);
178
179 if vtocx < 0 | recno >= pvt_array (pvtx).vtoc_size then
180 do;
181 call syserr (ANNOUNCE, "vm_vio: get_vtocep: invalid vtocx ^oo on pvtx ^oo", vtocx, pvtx);
182 return (null);
183 end;
184
185 word_number = mod (recno, n_rec_per_seg) * rec_size
186 + mod (vtocx, n_vtoce_per_rec) * vtoce_size;
187
188 vtoce_ptr = ptr (baseptr (segno), word_number);
189
190 k = salv_data$vol_read_ahead;
191 if k > 0 then if mod (vtocx, n_vtoce_per_rec * k) = 0 then call READ_AHEAD ;
192
193 return (vtoce_ptr);
194
195 ^L
196 READ_AHEAD : proc ;
197
198
199
200 dcl (r, r1, r2) fixed bin;
201 dcl (j, n (0:1)) fixed bin;
202 dcl first (0:1) fixed bin;
203 dcl astep (0:1) ptr;
204 dcl index fixed bin;
205
206
207 r1 = recno + k;
208 r2 = r1 + k - 1;
209
210 n (0), n (1), j = 0;
211
212 do r = recno + 1 to r2 while (r < pvt_array (pvtx).vtoc_size);
213 if mod (r, n_rec_per_seg) = 0 then j = 1;
214 if r >= r1 then n (j) = n (j) + 1;
215 end;
216
217 do j = 0, 1;
218 if n (j) > 0 then
219 do;
220 if j = 0 then astep (0) = get_ptrs_$given_segno (s (compno));
221 else do;
222 index = get_segno (recno + n_rec_per_seg);
223 astep (j) = get_ptrs_$given_segno (s (index));
224 end;
225 if j = 0 then
226 first (j) = mod (r1, n_rec_per_seg); else first (j) = mod (r1 + n (0), n_rec_per_seg);
227 if astep (j) ^= null then call pc_wired$read (astep (j), first (j), n (j));
228 else call syserr (CRASH, "vm_vio: no AST pointer at readahead.");
229 end;
230 end;
231
232
233 index = mod (recno, n_rec_per_seg);
234 if index >= k then
235 do;
236 if n (0) = 0 then astep (0) = get_ptrs_$given_segno (s (compno));
237 if astep (0) ^= null then call pc_wired$write (astep (0), index - k, k);
238 end;
239
240 return;
241
242 end READ_AHEAD;
243 ^L
244
245 get_segno: proc (pageno) returns (fixed bin);
246
247 dcl pageno fixed bin;
248 dcl fbtemp fixed bin;
249
250 do i = 0 to hbound (s, 1);
251 if seg_list (i).used then if seg_list (i).recno <= pageno
252 then if pageno <= seg_list (i).recno +n_rec_per_seg -1 then return (i);
253 end;
254
255 fbtemp = 1;
256
257 do i = 1 to hbound (s, 1);
258 if seg_list (i).recno < seg_list (fbtemp).recno then fbtemp = i;
259 end;
260
261 call init_seg_list (fbtemp, pageno);
262 return (fbtemp);
263 end get_segno;
264
265 init_seg_list: proc (index, pageno);
266
267 dcl (index, pageno) fixed bin;
268 dcl start fixed bin;
269
270 astep = get_ptrs_$given_segno (s (index));
271 call pc_wired$write (astep, 0, -1);
272 call pc$cleanup (astep);
273
274 start = divide (pageno, n_rec_per_seg, 17, 0) * n_rec_per_seg;
275
276 ptp = addrel (astep, sst$astsize);
277 do i = 0 to n_rec_per_seg - 1;
278 call ptw_util_$make_disk (addrel (ptp, i), start + i);
279 end;
280
281 seg_list (index).recno = start;
282
283 end init_seg_list;
284 end GET_VTOCEP;
285 ^L
286 INIT : proc (pvtx, code);
287
288 dcl pvtx fixed bin;
289 dcl code fixed bin (35);
290
291 dcl vtoc_size fixed bin;
292 dcl start_recno fixed bin;
293
294
295 code = 0;
296
297 if ^ segnos_initialized then
298 do;
299 seg_list (0).basep = addr (salv_abs_seg_00$);
300 s (0) = fixed (baseno (seg_list (0).basep));
301 seg_list (0).used = "0"b;
302 seg_list (0).perm = "0"b;
303
304 do i = 1 to hbound (s, 1);
305 s (i) = s (0) + i;
306 seg_list (i).basep = baseptr (s (i));
307 seg_list (i).used = "0"b;
308 seg_list (i).perm = "0"b;
309 end;
310
311 segnos_initialized = "1"b;
312 end;
313
314 start_recno = 0;
315 call INIT_VTOC_SEG (s (0), pvtx, start_recno, n_rec_per_seg, code);
316 if code ^= 0 then return;
317
318 seg_list (0).used = "1"b;
319 seg_list (0).perm = "1"b;
320 seg_list (0).recno = 0;
321
322 labelp = ptr (baseptr (s (0)), LABEL_ADDR * rec_size);
323
324 vtoc_size = label.vtoc_size;
325
326 do i = 1 to hbound (s, 1);
327 start_recno = start_recno + n_rec_per_seg;
328 call INIT_VTOC_SEG (s (i), pvtx, start_recno, n_rec_per_seg, code);
329 if code ^= 0 then return;
330 seg_list (i).used = "1"b;
331 seg_list (i).perm = "0"b;
332 seg_list (i).recno = start_recno;
333 end;
334
335 pvt_array (pvtx).vtoc_size = vtoc_size;
336 return;
337
338 end INIT;
339 ^L
340 INIT_VTOC_SEG : proc (segno, pvtx, first_recno, n_records, code) ;
341
342
343 dcl segno fixed bin,
344 pvtx fixed bin,
345 first_recno fixed bin,
346 n_records fixed bin,
347 code fixed bin (35);
348
349 dcl (i, pts, ptsi) fixed bin;
350
351 dcl tsdw fixed bin (71);
352
353
354
355
356 code = 0;
357
358 call lock$lock_ast;
359
360 astep = get_aste (n_records);
361
362 ptsi = fixed (aste.ptsi);
363 pts = sst$pts (ptsi);
364
365
366
367
368 astep -> aste_part.two = "0"b;
369
370
371
372 ptp = addrel (astep, sst$astsize);
373
374 do i = 0 to n_records - 1;
375 call ptw_util_$make_disk (addrel (ptp, i), first_recno + i);
376 end;
377
378 do i = n_records to pts - 1;
379 call ptw_util_$make_null (addrel (ptp, i), fill_page_table_null_addr);
380 end;
381
382
383
384
385
386 astep -> aste.vtocx = -1;
387 astep -> aste.dnzp = "1"b;
388 astep -> aste.gtpd = "1"b;
389 astep -> aste.nqsw = "1"b;
390 astep -> aste.strp = bit (fixed (segno, 18), 18);
391 astep -> aste.csl = bit (fixed (n_records, 9), 9);
392 astep -> aste.msl = bit (fixed (n_records, 9), 9);
393 astep -> aste.records = bit (fixed (n_records, 9), 9);
394 astep -> aste.pvtx = pvtx;
395
396
397
398
399
400 tsdw = get_ptrs_$given_astep (astep);
401 dseg$ (segno) = tsdw;
402 call page$cam;
403
404 astep -> aste.usedf = "1"b;
405
406 call thread$out (astep, sst$level (ptsi).ausedp);
407
408 call lock$unlock_ast;
409
410 return;
411
412 end INIT_VTOC_SEG;
413 ^L
414 CLEAN_UP : proc;
415
416 dcl k fixed bin;
417
418
419 if ^ segnos_initialized then return;
420
421 if sst$astl ^= pds$processid then call lock$lock_ast;
422
423 do k = 0 to hbound (s, 1);;
424 if seg_list (k).used then do;
425 astep = get_ptrs_$given_segno (s (k));
426
427 if astep ^= null then
428 if fixed (aste.strp, 18) = s (k) then
429 do;
430 dseg$ (s (k)) = 0;
431 call page$cam;
432 call pc$cleanup (astep);
433 call put_aste (astep);
434 end;
435 seg_list (k).used = "0"b;
436 seg_list (k).perm = "0"b;
437 end;
438 end;
439
440 call lock$unlock_ast;
441
442 addr (pvt$array) -> pvt_array (pvtx).vtoc_size = 0;
443
444 return;
445
446 end CLEAN_UP;
447
448 %page; %include aste;
449 %page; %include disk_pack;
450 %page; %include fs_vol_label;
451 %page; %include null_addresses;
452 %page; %include pvte;
453 %page; %include vtoce;
454 %page; %include syserr_constants;
455 %page; %include fs_dev_types_sector;
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487 note
488
489
490
491
492
493
494
495
496
497
498
499
500
501 note
502
503
504
505 end vm_vio;