1 " ***********************************************************
2 " * *
3 " * Copyright, C Honeywell Bull Inc., 1987 *
4 " * *
5 " * Copyright, C Honeywell Information Systems Inc., 1982 *
6 " * *
7 " ***********************************************************
8
9 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
10 "
11 " page_synch
12 "
13 " Module to manage Data Management synchronized pages for ALM
14 " Page Control.
15 "
16 " Entries:
17 "
18 " cleanup when a synch page is evicted, for housekeeping
19 " move when a synch page is moved from one frame to another
20 " write when Page Control wants to write a synch page, to see
21 " whether it can
22 " unlink_journal when a journal time stamp is changed, to unlink
23 " all held CMEs
24 "
25 " Written October 1982 by J. Bongiovanni
26 " Modified June 1983 by M. Pandolf to better meter invalid formats
27 " Modified May 1984 by Chris Jones to add move entry
28 "
29 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
30
31 name page_synch
32
33 segdef cleanup
34 segdef move
35 segdef write
36 segdef unlink_journal
37
38 minus_one:
39 dec -1
40
41 "^L
42 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
43 "
44 " cleanup
45 "
46 " Called when a synch page is evicted from memory, to do housekeeping
47 " and reset CME bits.
48 "
49 " tsx7 page_synch$cleanup
50 "
51 " On entry,
52 " x4 -> CME
53 "
54 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
55
56 cleanup:
57 spriap page_synch_temp " Save register
58 eppap dm_journal_seg_$
59
60 ldq page_fault$cme_flags,*x4 " CME flags
61 canq cme.synch_held,dl " Held page?
62 tze cleanup_not_held " No
63 tsx6 thread_out " Yes - thread out of per-journal list
64
65 cleanup_not_held:
66 lca cme.synch_held+1,dl " Reset held bit
67 ansa page_fault$cme_flags,*x4
68
69 tra ret_0
70 "^L
71 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
72 " move
73 "
74 " Called when a synch-held page is moved from one frame to another.
75 " Its entry in dm_journal_seg_ must be updated.
76 "
77 " tsx7 page_synch$move
78 "
79 " On entry,
80 " x4 -> new CME
81 " x5 -> old CME
82 "
83 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
84 move:
85 lda page_fault$cme_flags,*x5
86 ana cme.synch_held,dl
87 tze 0,x7 " not held, nothing to do
88 spriap page_synch_temp
89 orsa page_fault$cme_flags,*x4 " turn on synch_help in new
90 eaq 0,x5 " save this for a minute
91 lxl5 page_fault$cme_synch_page_entryp,*qu
92 sxl5 page_fault$cme_synch_page_entryp,*x4
93 eppap dm_journal_seg_$ " point to dm_page_entry
94 stx4 ap|dm_page_entry.cme_relp,x5
95 eax5 0,qu " copy it back
96 tra ret_0
97 "^L
98 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
99 " write
100 "
101 " Called when Page Control wants to write a synch page. If the page
102 " must be held, it is threaded to a per-journal list.
103 "
104 " tsx7 page_synch$write
105 " <return if page must be held>
106 " <return if OK to write>
107 "
108 " On entry,
109 " x4 -> CME
110 " bp -> PTW
111 " abs_seg1 -> memory frame for page
112 "
113 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
114
115 write:
116 spriap page_synch_temp " Save register
117 eppap dm_journal_seg_$
118 aos ap|dm_journal.synch_write_calls " Meter
119
120 tsx6 page_fault$savex " Recursive use of x7
121
122 lda page_fault$cme_flags,*x4
123 cana cme.synch_held,dl " Page already held?
124 tze write_not_held " No
125 tsx6 thread_out " Yes - thread out of list
126
127 write_not_held:
128 tsx6 check_page_hold " Should we hold?
129 tra invalid_format " Bogus synch page format
130 tra write_hold " Hold for sure
131
132 " Maybe not hold, but race exists since page is accessible to other
133 " CPUs. Remove access and check again
134
135 lca ptw.valid+1,dl
136 ansa bp|0 " Remove access in PTW
137 tsx6 page_fault$check_accessible " Is segment accessible?
138 tsx7 cam_cache$cam_cache " Yes, zap AMs
139
140 tsx6 check_page_hold " Check again for hold
141 tra invalid_format " Bogus format
142 tra write_hold " Hold
143 tra ret_unsavex_1 " Can write - done restores access
144
145 write_hold:
146 lda ptw.valid,dl " Restore access
147 orsa bp|0
148 lda ap|dm_journal.n_held_pages_mem " Check held against threshold
149 cmpa ap|dm_journal.max_held_pages_mem
150 tpl write_over_threshold " Exceeded
151 aos ap|dm_journal.synch_write_holds " Meter
152 tsx6 thread_in " Thread into list per-journal
153 tra ret_unsavex_0 " And return
154
155 invalid_format:
156 lda ptw.valid,dl " Restore access
157 orsa bp|0
158 tra ret_unsavex_1 " For now
159
160 write_over_threshold:
161 aos ap|dm_journal.synch_write_tosses " Meter
162 tra ret_unsavex_1 " And toss by allowing write
163 "^L
164 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
165 "
166 " unlink_journal
167 "
168 " Called when a journal time stamp is changed to unlink all CMEs,
169 " causing pages not to be held. Pages which should still be held
170 " will be detected when next we try to write them.
171 "
172 " call page_synch$unlink_journal Journal_Index
173 "
174 " Must be called with PTL held
175 "
176 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
177
178 unlink_journal:
179 push
180
181 ldq ap|2,* " Journal index
182 tmoz unlink_returns " Bogus
183 eppap dm_journal_seg_$
184 cmpq ap|dm_journal.n_journals " Valid index
185 tpnz unlink_returns " No
186 mpy dm_per_journal_size,dl
187 eaq ap|dm_journal.per_journal-dm_per_journal_size,ql " QU -> per journal entry
188 stq page_synch_temp
189 aos ap|dm_journal.unlink_calls " Meter
190
191 unlink_loop:
192 ldq page_synch_temp " QU -> per journal entry
193 ldx0 ap|dm_per_journal.entry_relp,qu " x0 -> page entry
194 tze unlink_returns " None left
195 aos ap|dm_journal.unlink_steps " Meter
196 ldx4 ap|dm_page_entry.cme_relp,x0 " x4 -> CME
197 tze page_error$dm_journal_seg_problem " Bad news, indeed
198 tsx6 thread_out " Unthread this entry
199 tra unlink_loop
200
201 unlink_returns:
202 return
203 "^L
204 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
205 "
206 " Return points - restore registers and return
207 "
208 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
209
210 ret_0:
211 lprpap page_synch_temp
212 tra 0,x7
213
214 ret_1:
215 lprpap page_synch_temp
216 tra 1,x7
217
218 ret_2:
219 lprpap page_synch_temp
220 tra 2,x7
221
222 ret_unsavex_0:
223 lprpap page_synch_temp
224 tra page_fault$unsavex
225
226 ret_unsavex_1:
227 lprpap page_synch_temp
228 tra page_fault$unsavex_1
229 "^L
230 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
231 "
232 " Internal procedure to check whether a page should be held, and
233 " not written.
234 "
235 " tsx6 check_page_hold
236 " <return if invalid synch page format>
237 " <return if should hold>
238 " <return if write OK>
239 "
240 " On entry,
241 " x4 -> CME
242 " abs_seg1 -> main memory for page
243 "
244 " On exit,
245 " ap -> dm_journal_seg_
246 "
247 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
248
249 check_page_hold:
250
251 eppap abs_seg1$ " ap -> page
252 ldaq ap|synch_page.version_word
253 tze null_version_word
254 lda ap|synch_page.version_word
255 ana synch_page.version,du
256 cmpa SYNCH_PAGE_VERSION_1,du " Good format for header
257 tnz invalid_version_number " No
258 lda ap|synch_page.journal_index_word
259 arl synch_page.journal_index_shift
260 ana synch_page.journal_index_mask,dl " Pick up journal index
261 tze invalid_journal_index " No good
262 sta page_synch_index " save
263 ldaq ap|synch_page.time_stamp_word
264 anaq synch_page.time_stamp_mask " Get time stamp
265 staq page_synch_time " And save
266 rccl sys_info$clock_,* " Check for reasonable value
267 cmpaq page_synch_time " Can't be later than clock
268 tmi invalid_time_stamp
269
270 eppap dm_journal_seg_$
271
272 ldq page_synch_index
273 cmpq ap|dm_journal.n_journals " Index valid
274 tpnz 0,x6 " No
275 mpy dm_per_journal_size,dl " Convert to offset
276 eax0 ap|dm_journal.per_journal-dm_per_journal_size,ql " x0 -> per_journal entry
277 szn ap|dm_per_journal.uid,x0 " In use?
278 tze 0,x6 " No - bogousity
279
280 ldaq page_synch_time
281 cmpaq ap|dm_per_journal.time_stamp,x0 " Hold page?
282 tmoz 2,x6 " No
283 tra 1,x6 " Yes
284
285 null_version_word:
286 eppap dm_journal_seg_$
287 aos ap|dm_journal.synch_write_no_stamp " Meter
288 tra 0,x6
289
290 invalid_version_number:
291 eppap dm_journal_seg_$
292 aos ap|dm_journal.synch_write_inv_vers " Meter
293 tra 0,x6
294
295 invalid_journal_index:
296 eppap dm_journal_seg_$
297 aos ap|dm_journal.synch_write_inv_ix " Meter
298 tra 0,x6
299
300 invalid_time_stamp:
301 eppap dm_journal_seg_$
302 aos ap|dm_journal.synch_write_inv_time " Meter
303 tra 0,x6
304
305 "^L
306 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
307 "
308 " Internal procedure to thread an entry into a per-journal list
309 "
310 " tsx6 thread_in
311 "
312 " On entry,
313 " ap -> dm_journal_seg_$
314 " x4 -> CME
315 " x0 -> per_journal entry
316 "
317 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
318
319 thread_in:
320 ldx1 ap|dm_journal.free_list_relp " Next free entry
321 tze page_error$no_free_dm_entries " None
322
323 ldq ap|0,x1 " QU -> next free
324 stq ap|dm_journal.free_list_relp
325
326 stx4 ap|dm_page_entry.cme_relp,x1
327
328 ldx5 ap|dm_per_journal.entry_relp,x0 " Entry in list
329 tnz thread_in_non_empty " List non-empty
330
331 stx1 ap|dm_per_journal.entry_relp,x0 " Save in list ptr
332 stx1 ap|dm_page_entry.fp,x1 " Entry threads to self
333 sxl1 ap|dm_page_entry.bp,x1
334 tra thread_in_done
335
336 thread_in_non_empty:
337 lda ap|dm_page_entry.fp,x5 " x5 -> an entry in the list
338 sxl1 ap|dm_page_entry.bp,x5 " entry -> back to new entry
339 stx5 ap|dm_page_entry.fp,x1 " new entry -> forward to entry
340 stx1 ap|dm_page_entry.fp,al " prev entry -> forward to new entry
341 eax5 0,al
342 sxl5 ap|dm_page_entry.bp,x1 " new entry -> back to prev entry
343
344 thread_in_done:
345 sxl0 ap|dm_page_entry.journal_relp,x1 " pointer to per_journal
346 sxl1 page_fault$cme_synch_page_entryp,*x4 " CME -> entry
347 lda cme.synch_held,dl
348 orsa page_fault$cme_flags,*x4 " Mark CME as held
349 aos ap|dm_per_journal.n_held,x0 " Bump count of held this journal
350 aos ap|dm_journal.n_held_pages_mem " And total held
351
352 tra 0,x6
353 "^L
354 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
355 "
356 " Internal procedure to thread an entry out of a per-journal list
357 "
358 " tsx6 thread_out
359 "
360 " On entry,
361 " ap -> dm_journal_seg_$
362 " x4 -> CME
363 "
364 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
365
366 thread_out:
367
368 lda cme.synch_held,dl
369 era minus_one
370 ansa page_fault$cme_flags,*x4 " Mark CME as not-held
371
372 lxl1 page_fault$cme_synch_page_entryp,*x4 " x1 -> entry
373 tze page_error$dm_journal_seg_problem
374 lda -1,du
375 ansa page_fault$cme_synch_page_entryp,*x4 " Reset CME pointer
376
377 lxl0 ap|dm_page_entry.journal_relp,x1 " x0 -> per-journal entry
378
379 lxl5 ap|dm_page_entry.bp,x1 " x5 -> prev entry
380 cmpx1 ap|dm_page_entry.fp,x1 " Thread to self?
381 tnz thread_out_non_empty " No - list won't be empty
382
383 stz ap|dm_per_journal.entry_relp,x0 " Mark list as empty
384 tra thread_out_done
385
386 thread_out_non_empty:
387 lda ap|dm_page_entry.fp,x1 " AU -> next entry
388 sxl5 ap|dm_page_entry.bp,au " next -> back to prev
389 eax5 0,au " x5 -> next entry
390 stx5 ap|dm_page_entry.fp,al " prev -> forward to next
391 stx5 ap|dm_per_journal.entry_relp,x0 " In case it pointed to this one
392
393 thread_out_done:
394 lda ap|dm_journal.free_list_relp " Thread entry into free list
395 sta ap|dm_page_entry.fp,x1
396 eaa 0,x1
397 sta ap|dm_journal.free_list_relp
398
399 lda ap|dm_per_journal.n_held,x0 " Decrement per-journal count
400 sbla 1,dl
401 sta ap|dm_per_journal.n_held,x0
402 lda ap|dm_journal.n_held_pages_mem " Decrement total count
403 sbla 1,dl
404 sta ap|dm_journal.n_held_pages_mem
405
406 tra 0,x6
407 "^L
408 include cmp
409 "^L
410 include dm_journal_seg_
411 "^L
412 include ptw
413 "^L
414 include pxss_page_stack
415 "^L
416 include synch_page
417
418
419 end