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