1 " ***********************************************************
   2 " *                                                         *
   3 " * Copyright, (C) Honeywell Bull Inc., 1987                *
   4 " *                                                         *
   5 " * Copyright, (C) Honeywell Information Systems Inc., 1983 *
   6 " *                                                         *
   7 " * Copyright (c) 1972 by Massachusetts Institute of        *
   8 " * Technology and Honeywell Information Systems, Inc.      *
   9 " *                                                         *
  10 " ***********************************************************
  11 
  12 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
  13 "
  14 "         pxss -- The Multics Traffic Controller (Scheduler)
  15 "
  16 "         Last Modified: (Date and Reason)
  17 "
  18 "         February 1985 by Keith Loepere to fix initialization disk polling.
  19 "         January 1985 by Keith Loepere to fix window in ips sending and oob in
  20 "                   set_work_class.
  21 "         December 1984 by Keith Loepere for page_pause and pause functions.
  22 "         84-11-21 by E. Swenson for IPC event channel validation.
  23 "         October 1984 by M. Pandolf for getwork suspension
  24 "         84-07-23 by E. Swenson to clean up ittes of dead processes
  25 "                   correctly.
  26 "         07/16/84 by R. Michael Tague:  Changed the $ips_wakeup and
  27 "                     $ips_wakeup_int entries to expect an ips bit mask
  28 "                     as an indicator of the signal to be sent instead
  29 "                     of a name.
  30 "         84-02 BIM for sst$ references instead of sst.
  31 "         October 1983 by Keith Loepere for disk polling during initialization.
  32 "         June 1983 by E. A. Ranzenbach for operator console polling.
  33 "         June 1983 by Chris Jones to call the new IOI entries.
  34 "         May 1983 by BIM for call-side pre-empt and stop.
  35 "         April 1983 by E. N. Kittlitz to DRL instead of 0,ic looping.
  36 "         February 1983 by E. N. Kittlitz for hex floating point.
  37 "         December 1982 by C. Hornig to punt NCP
  38 "         October 1982 by C. Hornig for no ITT message on fast channels.
  39 "         August 1982 by J. Bongiovanni for realtime_io priority,
  40 "                   relinquish_priority
  41 "         April 1982 by J. Bongiovanni to enhance governing
  42 "         February 1982 by J. Bongiovanni to fix masking bug
  43 "         September 1981 by J. Bongiovanni for procs_required, moving
  44 "                   code to tc_util
  45 "         June 1981 by J. Bongiovanni for governed work classes,
  46 "                   -tcpu, +pre_empt_sample_time
  47 "         May 1981 by J. Bongiovanni for response time metering
  48 "         03/01/81 by W. Olin Sibert, for Phase One of ADP conversion
  49 "         March 1981 by J. Bongiovanni for page pinning, saved stack_0's,
  50 "                   argument copying protocol, initialization NTO
  51 "         February 1981 by J. Bongiovanni for fast connect
  52 "         March 1981 by E. Donner for new ipc - include file for itt entry
  53 "         and to change check for fast channel
  54 "         February 1981 by J. Bongiovanni to fix set_proc_required
  55 "         January 1981 by J. Bongiovanni to fix ITT overflow, credit
  56 "                   clipping
  57 "         Spring 1979 by B. Greenberg for shared stack_0's.
  58 "         Fall 1978 RE Mullen for +ptl_NTO, +disable int_q, -XED's
  59 "         Winter 1977 RE Mullen for lockless (lockfull?) scheduler:
  60 "                   concurrent read_lock, ptlocking state, apte.lock,
  61 "                   unique_wakeup entry, tcpu_scheduling
  62 "         Spring 1976 by RE Mullen for deadline scheduler
  63 "         02/17/76 by S. Webber for new reconfiguration
  64 "         3/10/76 by B Greenberg for page table locking event
  65 "         Spring 1975 RE Mullen to implement priority scheduler and
  66 "                   delete loop_wait code.  Also fixed plm/lost_notify bug.
  67 "         Last modified on 02/11/75 at 19:49:10 by R F Mabee.  Fixed arg-copying & other bugs.
  68 "         12/10/74 by RE Mullen to add tforce, ocore, steh, tfmax & atws
  69 "              disciplines to insure response in spite of long quanta, and
  70 "              fix bugs in get_processor, set_newt, and loop_wait unthreading.
  71 "         12/6/74 by D. H. Hunt to add access isolation mechanism checks
  72 "         4/8/74 by S.H.Webber to merge privileged and unprivileged code.
  73 "                   and to add quit priority and fix lost notify bug
  74 "         5/1/74 by B. Greenberg to add cache code
  75 "         8/8/72 by R.B.Snyder for follow-on
  76 "         2/2/72 by R. J. Feiertag to a simulated alarm clock
  77 "         9/16/71 by Richard H. Gumpertz to add entry rws_notify
  78 "         7/**/69 by Steve H. Webber
  79 "
  80 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
  81 
  82 " HISTORY COMMENTS:
  83 "  1) change(1986-05-13,GJohnson), approve(1986-05-13,MCR7387),
  84 "     audit(1986-05-13,Martinson), install(1986-05-14,MR12.0-1056):
  85 "     Correct error message documentation.
  86 "  2) change(1986-08-09,Kissel), approve(1986-08-12,MCR7479),
  87 "     audit(1986-10-08,Fawcett), install(1986-11-03,MR12.0-1206):
  88 "     Changed to check the flags in an event channel name when sending a
  89 "     wakeup.  If the flags indicate that this is an asynchronous event
  90 "     channel, then send an IPS wkp_ signal in addition to the normal IPC
  91 "     wakeup.  This code uses an algorithm copied from ipc_validate_ to decode
  92 "     the event channel flags, hence, any changes must be reflected in both
  93 "     places.
  94 "  3) change(1988-09-16,Fawcett), approve(1988-10-06,MCR8004),
  95 "     audit(1988-10-06,Farley), install(1988-10-10,MR12.2-1156):
  96 "     Removed check in compute_virtual_clocks which was testing for a zero
  97 "     second word in prds$last_recorded_time to determine if it should be
  98 "     initialized.  The initialization is already done in init_processor.  All
  99 "     this check was doing was opening a timing hole for errors to occur (i.e.
 100 "     the last 36 bits of the clock roll over ~ every 19 hours).
 101 "  4) change(1988-10-05,Fawcett), approve(1988-10-05,MCR7999),
 102 "     audit(1988-10-06,Farley), install(1988-10-10,MR12.2-1156):
 103 "     Changed to always reset the number a pages in use  used before giving
 104 "     the processor the process. This enables a more acturate measure of
 105 "     memory units.
 106 "  5) change(2018-05-31,Anthony), approve(2018-05-31,MCR10050),
 107 "     audit(2019-05-11,Swenson), install(2019-05-11,MR12.6g-0017):
 108 "     Promote loop_lock_time to
 109 "     fixed bin (71).
 110 "  6) change(2019-05-19,Swenson), approve(2019-05-19,MCR10054),
 111 "     audit(2019-05-19,GDixon), install(2019-05-20,MR12.6g-0019):
 112 "     Fix for preempting for procs_required processes.
 113 "                                                      END HISTORY COMMENTS
 114 
 115           name      pxss
 116 
 117 
 118           iftarget  adp
 119             warn    (This has not been converted yet for the ADP. Beware.)
 120           ifend
 121 
 122 
 123           link      prds_link,prds$+0
 124 
 125           even
 126 channel_mask_set:
 127           oct       17,17
 128 
 129 null:     its       -1,1                null pointer
 130 
 131 null_epaq:
 132           vfd       3/0,15/-1,18/0,18/1,18/0
 133 
 134 ring0_timer_event:
 135           aci       "dlay"
 136           even
 137 "^L
 138 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 139 "
 140 "         Table of contents
 141 "
 142 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 143 
 144 
 145           entry     addevent
 146           entry     block
 147           entry     delevent
 148           entry     dvctl_retry_ptlwait
 149           entry     empty_t
 150           entry     fast_ipc_block
 151           entry     fast_ipc_get_event
 152           entry     force_stop
 153           entry     free_itt
 154           entry     get_entry
 155           entry     get_event
 156           entry     guaranteed_eligibility_off
 157           entry     guaranteed_eligibility_on
 158           entry     io_wakeup
 159           entry     ips_wakeup
 160           entry     ips_wakeup_int
 161           entry     lock_apt
 162           entry     lock_apte
 163           entry     notify
 164           entry     page_notify
 165           entry     page_pause
 166           entry     page_wait
 167           entry     pause
 168           entry     pre_empt
 169           entry     pre_empt_poll
 170           entry     ptl_notify
 171           entry     ptl_wait
 172           entry     relinquish_priority
 173           entry     ring_0_wakeup
 174           entry     set_cpu_timer
 175           entry     set_procs_required
 176           entry     set_timer
 177           entry     set_work_class
 178           entry     start
 179           entry     stop
 180           entry     stop_wakeup
 181           entry     suspend_getwork
 182           entry     thread_in_idle
 183           entry     unique_ring_0_wakeup
 184           entry     unlock_apt
 185           entry     unlock_apte
 186           entry     unthread_apte
 187           entry     usage_values
 188           entry     wait
 189           entry     waitp
 190           entry     wakeup
 191           entry     wakeup_int
 192 
 193 "^L
 194           include   apte
 195 "^L
 196           include   aste
 197 "^L
 198           include   drl_macros
 199 "^L
 200           include   event_channel_name
 201 "^L
 202           include   ips_mask_data
 203 "^L
 204           include   itt_entry
 205 "^L
 206           include   mc
 207 "^L
 208           include   mode_reg
 209 "^L
 210           include   ptw
 211 "^L
 212           include   pxss_page_stack
 213 "^L
 214           include   response_transitions
 215 "^L
 216           include   scs
 217 "^L
 218           include   stack_0_data
 219 "^L
 220           include   stack_frame
 221 "^L
 222           include   stack_header
 223 "^L
 224           include   state_equs
 225 "^L
 226           include   tc_meters
 227 "^L
 228           include   wcte
 229 "^L
 230 
 231           macro     read_clock
 232           rccl      sys_info$clock_,*
 233           &end
 234 
 235 "^L
 236 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 237 "
 238 "         BLOCK -- entry to block a process.
 239 "
 240 "         Call is
 241 "                   call pxss$block;
 242 "
 243 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 244 
 245 block:    eppbp     short_ret
 246           sprpbp    pds$ipc_block_return
 247 
 248           equ       ipcv.retsw,1
 249 
 250 fast_ipc_block:
 251           tsplb     setup_mask          mask, switch_stack
 252           aos       bb|te_block
 253           aos       bb|blocks
 254           lda       bp|apte.flags       check for wakeup waiting
 255           cana      apte.wakeup_waiting,du
 256           tnz       block_ez            able to avoid heavy lock!
 257           tsx7      update_te           update te in own APT entry
 258           tsx6      WRITE_LOCK          block locks
 259           tsx6      LOCK_bp             block locks
 260           lda       bp|apte.flags       check for wakeup waiting
 261           cana      apte.wakeup_waiting,du
 262           tnz       block_not           there is one, return
 263           ldq       BLOCK_PROCESS,dl
 264           tsx7      meter_response_time$tc        this is a response transition
 265           tsx7      unthread            thread out of ready list
 266           ldx0      blocked,du          set state to blocked
 267           tsx7      update_execution_state
 268           tsx7      revoke_elig         block
 269           tsx7      reschedule          block
 270           tsx7      purge_UNLOCK        block
 271           tsx7      getwork
 272           ldaq      bp|apte.virtual_cpu_time note vtime at gain elig
 273           staq      pds$virtual_time_at_eligibility
 274           tsx6      LOCK_bp
 275 block_returns:
 276           lcx0      apte.wakeup_waiting+1,du turn off wakeup waiting
 277           ansx0     bp|apte.flags
 278 return_event_messages:
 279           lda       bp|apte.flags       check for interrupts pending
 280           ana       apte.stop_pending,du look for stop connect
 281           ora       bp|apte.ips_message or ips signals
 282           tze       *+2                 if interrupt pending leave 1
 283           lda       1,dl                ..
 284           ldq       bp|apte.flags2      get special interrupts
 285           anq       apte.special_chans,dl ..
 286           ersq      bp|apte.flags2      turn off special chans
 287           qls       apte.chans_offset   ..
 288           lls       17                  put info together
 289           eax3      0,al                remember info
 290           eax4      0                   use to zero event thread
 291           ldx2      bp|apte.ipc_pointers return event thread
 292           stx4      bp|apte.ipc_pointers zero event thread in APT entry
 293           tsx6      UNLOCK_bp
 294           tsx7      switch_back_ret_pds
 295           stz       pds$itt_head
 296           stx2      pds$itt_head
 297           eaq       0,3                 get info
 298           lda       0,dl                zero a
 299           lls       1                   split info
 300           orsq      pds$events_pending  store special chans
 301           orsa      pds$ipc_vars+ipcv.retsw store return sw
 302           lprpbp    pds$ipc_block_return
 303           epbpsb    pds$stack_0_ptr,*   Load this up for fast_hc_ipc,
 304                                         "who can't do it himself.
 305           tra       bp|0
 306 
 307 "
 308 "here if find wakeup_waiting after full lock, to back off big lock
 309 "
 310 block_not:
 311           tsx6      UNLOCK              only need self locked
 312           tra       block_returns
 313 
 314 "
 315 "here if notice wakeup_waiting before locking anything
 316 "
 317 block_ez: tsx6      LOCK_bp             only need to lock self
 318           tra       block_returns
 319 
 320 " ^L
 321 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 322 "
 323 "         GET_EVENT -- procedure to return a process' event thread
 324 "
 325 "         Call is
 326 "                   call pxss$get_event(event)
 327 "
 328 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 329 
 330 get_event:
 331           eppbp     short_ret
 332           sprpbp    pds$ipc_block_return
 333 fast_ipc_get_event:
 334           tsplb     setup_mask
 335           tsx6      LOCK_bp
 336           tra       return_event_messages
 337 " ^L
 338 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 339 "
 340 "         WAKEUP
 341 "
 342 "         call pxss$wakeup(processid,event_channel,event_message,state)
 343 "
 344 "         entry to wake up a process given event channel and event message
 345 "
 346 "         The following entries have the same calling sequence:
 347 "
 348 "            wakeup - send wakeup, give interactive credit if blocked
 349 "                     more than priority_sched_inc
 350 "
 351 "            ring_0_wakeup - send wakeup, give interactive credit if blocked
 352 "
 353 "            unique_ring_0_wakeup - send wakeup only if this wakeup is unique
 354 "                      in ITT for this process, give interactive credit if
 355 "                      blocked.
 356 "
 357 "            io_wakeup - send wakeup, give interactive credit if blocked,
 358 "                      give realtime credit if blocked and tuning parameter
 359 "                      set.
 360 "
 361 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 362 
 363 ring_0_wakeup:
 364 wakeup_int:
 365           tsx6      setup_
 366           lca       1,dl                set flag saying ring_0_wakeup entry
 367           sta       pds$wakeup_flag     set flag saying ring_0_wakeup entry
 368           tra       wjoin
 369 unique_ring_0_wakeup:
 370           tsx6      setup_
 371           stz       pds$wakeup_flag     set flag for unique_ring_0_wakeup
 372           tra       wjoin
 373 io_wakeup:
 374           tsx6      setup_
 375           lca       2,dl                set flag for io_wakeup entry
 376           sta       pds$wakeup_flag     set flag for io_wakeup entry
 377           tra       wjoin
 378 
 379 wakeup:
 380           tsx6      setup_
 381           stc1      pds$wakeup_flag     set flag saying wakeup entry
 382 wjoin:
 383           lda       ap|2,*              get processid
 384           sta       pds$arg_1
 385           ldaq      ap|4,*              save event channel in pds$arg_2
 386           staq      pds$arg_2
 387           ldaq      ap|6,*              save event message in pds$arg_3
 388           staq      pds$arg_3
 389           tsplb     setup_check         switch stacks and lock
 390           arg       0,6
 391 
 392           szn       pds$wakeup_flag     see if ring_0_wakeup entry
 393           tmoz      w_rz                it is. do later code
 394           lda       pds$validation_level it isn't.
 395           sta       tmp_ring            get ready to make ITT message
 396           stz       dev_signal
 397           tra       copy_evs            skip code for ring_0_wakeup entry
 398 w_rz:     stz       tmp_ring
 399           lda       1,dl
 400           sta       dev_signal          must be a device signal
 401 copy_evs:
 402           ldaq      pds$arg_2           finish setup for make ITT message
 403           staq      tmp_ev_channel
 404           ldaq      pds$arg_3
 405           staq      tmp_ev_message
 406 
 407           ldx2      0,du                pre-set execution state to zero
 408           tsx6      WRITE_LOCK          Wakeup may need to thread in
 409           tsx7      hash_LOCK           wakeup finds and locks
 410           arg       wakeup_returns_nul  indirect if error
 411           lda       bp|apte.flags       see if this is idle process
 412           cana      apte.idle,du
 413           tnz       wakeup_returns      can't wakeup an idle process
 414           aos       bb|wakeups
 415           lxl0      bp|apte.state       check for stopped process
 416           cmpx0     stopped,du
 417           tze       wakeup_returns
 418 
 419           ldq       NON_TTY_WAKEUP,dl
 420           tsx7      meter_response_time$tc        response transition
 421 
 422           ldq       pds$wakeup_flag     should we give priority ?
 423           tpnz      non_ring_0          no,normal wakeup
 424           lxl0      bp|apte.state       recover process state
 425           cmpx0     blocked,du          no interaction credit unless blocked
 426           tnz       no_int_credit       ..at time of wakeup.
 427           lda       apte.interaction,du give priority ... turn on interaction sw.
 428           orsa      bp|apte.flags       in APT entry of process getting wakeup
 429           cmpq      =-2                 io_wakeup?
 430           tnz       no_int_credit       no
 431           szn       bb|realtime_io_priority_switch are we giving realtime priority?
 432           tze       no_int_credit       no
 433           lda       apte.realtime_burst,du
 434           orsa      bp|apte.flags       yes
 435 no_int_credit:
 436           tsx7      make_itt_message    wakeup adds itt_msg to process' queue
 437 
 438 "                                       See if we have to send an IPS wkp_ signal
 439 "                                       This algorithm is copied from ipc_validate_
 440 
 441           lda       pds$arg_2                     Get event_channel_name.encoded_idx
 442           arl       18                             in al
 443           sba       bp|apte.ipc_r_offset          Subtract the r_offset to get the decoded_index
 444           arl       decoded_index.flags_shift-18  Get the flag bits (we already shifted 18 above)
 445           ana       decoded_index.flags_mask,dl   For now there are only 2 possibilities
 446           tze       wakeup_wake         We have the normal flags
 447 "                                       We have to send an IPS wkp_ signal
 448 
 449           lda       sys_info$wkp_mask   We want to send a wkp_ signal
 450           tsx6      send_ips_wakeup     Do the real work, destroys pds$arg_3
 451 "                                       Next instruction may be skipped on return
 452 wakeup_wake:
 453           tsx7      wake                Go to common wakeup code
 454           lxl2      bp|apte.state       return arg in x2
 455           szn       errcode
 456           tze       *+2
 457           lxl2      errcode
 458 wakeup_returns:
 459           tsx6      UNLOCK_bp           Wakeup unlocks target apte
 460 wakeup_returns_nul:
 461           tsx6      UNLOCK              Wakeup unlocks
 462           tsx7      switch_back_ret     Exit from wakeup if pid invalid and no apte locked
 463           stz       ap|8,*              return execution state
 464           sxl2      ap|8,*
 465           short_return
 466 
 467 non_ring_0:
 468 "Here are the checks for the
 469 "Access Isolation Mechanism
 470 
 471           ldaq      bp|apte.access_authorization if target has ipc privilege
 472           orq       pds$access_authorization+1 or if sender has ipc privilege,
 473           canq      apte.no_ipc_check,dl
 474           tnz       no_int_credit       then it is OK to send the wakeup.
 475           ldx0      bp|apte.access_authorization+1 get level of target process
 476           cmpx0     pds$access_authorization+1 if it's less than sender's level,
 477           tmi       send_down           do not allow wakeup to be sent.
 478           ana       pds$access_authorization if the category set of the sender
 479           cmpa      pds$access_authorization is contained in (or equal to)
 480           tze       no_int_credit       the category set of the target,
 481 "then it is OK to send the wakeup.
 482 send_down:
 483           ldx2      100,du              this error code indicates
 484           tra       wakeup_returns      an IPC send-down attempt.
 485 
 486 " ^L
 487 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 488 "
 489 "         WAKE -- internal subroutine used to wake up a process
 490 "         and award it a processor if it is warrented.
 491 "
 492 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 493 
 494 wake:
 495           tsx6      subroutine_save
 496           szn       bp|apte.lock        ASSUME bp locked
 497           drlnz     (pxss: APTE not locked) ASSUME bp locked
 498           lda       apte.wakeup_waiting,du turn on wakeup waiting flag
 499           orsa      bp|apte.flags
 500           lxl0      bp|apte.state       make sure process is blocked
 501           cmpx0     blocked,du
 502           tnz       subroutine_unsave
 503           read_clock                    " check for long time block
 504           sbaq      bp|apte.state_change_time subtract out last state chage time
 505           cmpq      bb|priority_sched_inc see if process has been asleep too long
 506           tmi       short_time          just went blocked, no priority
 507           tsx0      setup_p_int         boost priority
 508 short_time:
 509           ldx0      ready,du            change state to ready
 510           tsx7      update_execution_state
 511           tsx7      sort_in             schedule and thread in
 512           eax2      bp|0                fp = entry waking up
 513           tsx7      get_processor       does he get a processor?
 514           tra       subroutine_unsave
 515 " ^L
 516 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 517 "
 518 "         FREE_ITT - entry to put a list of ITT entries into the list of free ITT
 519 "                   entries. It is always called after a process returns from block,
 520 "                   to release its event message queue.
 521 "
 522 "                   Nothing is locked when this code is entered.
 523 "                   Apte's are locked to validate that the processes exist.
 524 "                   If the pid has changed we know empty_t zeroed the counter.
 525 "                   Never looplock an APTE while holding the itt_free_list.
 526 "
 527 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 528 
 529 free_itt:
 530           tsx6      setup_
 531           lda       ap|2,*              pick up pointer to list to be freed
 532           sta       pds$arg_1
 533           tsplb     setup_check         switch stacks and lock
 534           arg       0,6
 535 
 536           ldx0      pds$arg_1           get head of process's itt queue
 537           tsx7      free_itt_           free them
 538           tra       switch_back         free_itt exits
 539 "^L
 540 
 541 free_itt_:
 542 "Come here to free X0->ITTE's
 543           eax5      0,0                 Remember newly freed head in X5
 544           tze       free_itt_exit       there is nothing to free
 545           epbpbb    tc_data$            get pointer to base of tc_data
 546           ldx4      -1,du               put all-seven into RX4
 547           eaa       0                   count num freed
 548 follow_itt_list:
 549           sxl4      bb|itt_entry.next_itt_relp,0  tag the discarded entry for debugging
 550           sba       1,dl                maintain counter
 551           ldx3      bb|itt_entry.origin,0 see if dev_signal
 552           tnz       fi_skip_sender      nz means dev_signal
 553           ldx3      bb|itt_entry.sender,0 was dev_signal
 554           tsx6      LOCK_x3             free_itt locks sender
 555           ldq       bb|apte.processid,3 if process still exists
 556           cmpq      bb|itt_entry.sender,0
 557           tnz       fi_sender_gone      processid has changed!
 558           lcq       1,dl                ok to decrement
 559           asq       bb|apte.ittes_sent,3
 560 fi_sender_gone:
 561           tsx6      UNLOCK_x3           free_itt unlocks sender
 562 fi_skip_sender:
 563 "                                       get following entry's forward pointer
 564           ldx2      bb|itt_entry.next_itt_relp,0
 565           tze       thread_in_itt_queue
 566           eax0      0,2                 put index 2 into XR0
 567           tra       follow_itt_list
 568 "
 569 "x5->first_freed, x0 ->last_freed, A has count
 570 thread_in_itt_queue:
 571           ldqc      bb|itt_free_list    free_itt LOCKS free list
 572           tnz       *+2
 573           tra       thread_in_itt_queue If zero somebody else has it
 574 
 575           eax1      0,qu
 576 "                                       make tail of new -> old head
 577           stx1      bb|itt_entry.next_itt_relp,0
 578           ldx3      bb|itt_entry.target_id,0 prepare to decrement target counter
 579           ldq       bb|itt_entry.target_id,0 get rcvr pid
 580           asa       bb|used_itt         use A-reg to decrement
 581           stx5      bb|itt_free_list    free_itt UNLOCKS free_list
 582           tsx6      LOCK_x3             free_itt locks target
 583           cmpq      bb|apte.processid,3 compare processid
 584           tnz       rcvr_gone           processid has changed!
 585           asa       bb|apte.ittes_got,3 use A-reg to decrement
 586 rcvr_gone:
 587           tsx6      UNLOCK_x3           free_itt unlocks target
 588 free_itt_exit:
 589           tra       0,7                 free_itt_  exits
 590 
 591 " ^L
 592 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 593 "
 594 "         PRE_EMPT
 595 "         TIMER_RUNOUT
 596 "
 597 "         This procedure is called at timer runout time and
 598 "         when a process gets pre-empted by a higher priority
 599 "         process. Pre-empt merely gives the processor away.
 600 "         Timer-runout gives up eligibility as well.
 601 "
 602 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 603 
 604 pre_empt_poll:
 605           tsplb     setup_mask
 606           tra       pre_empt.common
 607 
 608 pre_empt:
 609           stz       pds$pre_empt_poll_return
 610 
 611           tsx6      init_pxss_save_stack init x7 save stack
 612 pre_empt.common:
 613           tsx7      update_te
 614           aos       bb|te_pre_empt
 615           lda       bp|apte.flags
 616           cana      apte.idle,du        Idle suffers pre-empt not timer-runout
 617           tnz       pmt_idle
 618           lda       bp|apte.temax       See if time left in quantum
 619           cmpa      bp|apte.te
 620           tmi       tro_                None left give up elig
 621 
 622 pmt_:     tsx6      LOCK_bp             pre-empt changes state
 623           lcx0      apte.pre_empt_pending+1,du turn OFF flag
 624           ansx0     bp|apte.flags       ..
 625           ldx0      ready,du            set state to ready
 626           tsx7      update_execution_state
 627           tsx6      UNLOCK_bp           pre-empt unlocks before getwk
 628           tsx7      getwork
 629 pre_empt.return:
 630           szn       pds$pre_empt_poll_return      zero => this process entered pre-empt through connect fault
 631           tze       wired_fim$pre_empt_return     Return from connect
 632 
 633 " Switch back by hand, since the circumstances are peculiar.
 634 " Code adapted from switch_back.
 635 
 636           ldaq      prds$+stack_header.stack_begin_ptr restore stack end ptr
 637           staq      prds$+stack_header.stack_end_ptr ..
 638 
 639           ldaq      pds$tc_mask         restore previous mask
 640           oraq      channel_mask_set
 641           anaq      scs$open_level
 642           lxl1      prds$processor_tag
 643           lprpab    scs$mask_ptr,1      get set for masking
 644           xec       scs$set_mask,1
 645 
 646           eppsp     pds$pre_empt_poll_return,*    Adopt outer ring stack frame
 647           stz       pds$pre_empt_poll_return      Au resevoir
 648           epbpsb    pds$stack_0_ptr,*             So we can get to operators
 649           short_return                            and return to caller of gate
 650 
 651 
 652 
 653 pmt_idle: szn       bb|wait_enable      If idle make sure not shutting down
 654           tnz       pmt_                Idle pmt ok if multiprog
 655           szn       bb|system_shutdown
 656           tze       pmt_                Idle pmt ok if not shutdown
 657                                              " Idles never get ring alarms
 658           tra       wired_fim$pre_empt_return Must not do getwork!
 659 
 660 
 661 tro_:     tsx6      WRITE_LOCK          tro_ unthreads
 662           tsx6      LOCK_bp             tro_ locks apte
 663           lcx0      apte.pre_empt_pending+1,du
 664           ansx0     bp|apte.flags
 665           tsx7      unthread            tro_
 666           ldx0      ready,du            tro_
 667           tsx7      update_execution_state tro_
 668           tsx7      revoke_elig         tro_
 669           tsx7      reschedule          tro_
 670           tsx7      sort_in             tro_
 671           tsx7      purge_UNLOCK        tro_
 672           tsx7      getwork             tro_
 673           ldaq      bp|apte.virtual_cpu_time note vtime at gain elig
 674           staq      pds$virtual_time_at_eligibility
 675           tra       pre_empt.return
 676 
 677 " ^L
 678 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 679 "
 680 "         stop       - called by hcs_$stop_proc to stop a process
 681 "                   stop is unusual in that it is a call side
 682 "                   operation which must unthread and sort_in
 683 "                   a ready non-eligible process
 684 "
 685 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 686 
 687 stop_wakeup:
 688 stop:
 689           tsx6      setup_
 690           lda       ap|2,*              get processid
 691           sta       pds$arg_1
 692           tsplb     setup_check         switch stacks and lock
 693           arg       0,6
 694           tsx6      WRITE_LOCK          stop may need rethread
 695 
 696           lda       pds$validation_level get caller's ring number
 697           sta       tmp_ring
 698 
 699           ldx2      0,du                pre-set execution state to zero
 700           tsx7      hash_LOCK           stop finds and locks target
 701           arg       stop_returns_nul    indirect if error
 702 
 703           lda       bb|default_procs_required     set  process to default
 704           ana       apte.procs_required_mask,du   just in case
 705           drlze     (pxss: APTE disdains all processors) should never happen
 706           era       bp|apte.procs_required
 707           ersa      bp|apte.procs_required
 708           ldx2      apte.default_procs_required,du set default flag
 709           orsx2     bp|apte.flags
 710 
 711           lxl2      bp|apte.state       target's state to x2
 712           cmpx2     stopped,du          Compare to the stopped state
 713           tze       stop_returns        If equal, target already stopped
 714           stz       dev_signal          count it as dev_signal
 715           aos       dev_signal          count it as dev_signal
 716           lda       =aquit              put recognizable pattern in message
 717           ldq       =astop              ... namely "quitstop"
 718           staq      tmp_ev_channel
 719           staq      tmp_ev_message      pattern into channel & message
 720           stc1      pds$wakeup_flag     not require unique message
 721           tsx7      make_itt_message    now go make "quitstop" message
 722 
 723           tsx0      setup_p_int         boost priority
 724           lxl0      bp|apte.state
 725           cmpx0     blocked,du          Blocked?
 726           tze       st_wake             Yes, wake him.
 727 
 728           ldx0      bp|apte.flags       Eligible?
 729           canx0     apte.eligible,du
 730           tnz       st_wake             Yes, don't unthread
 731           tsx7      unthread            No, move up in queue
 732           tsx7      sort_in_before
 733 
 734 st_wake:  tsx7      wake                Awaken blocked target
 735           lda       apte.stop_pending,du turn on stop pending
 736           orsa      bp|apte.flags
 737           tsx7      send_connect        send connect if processor running
 738           lxl2      bp|apte.state       return state to caller
 739 stop_returns:
 740           tsx6      UNLOCK_bp
 741 stop_returns_nul:
 742           tsx6      UNLOCK              stop is done
 743           tsx7      switch_back_ret
 744           stz       ap|4,*              return execution state
 745           sxl2      ap|4,*
 746           short_return
 747 " ^L
 748 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 749 "
 750 "         start      - called by hcs_$start_proc to start a process
 751 "
 752 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 753 
 754 start:
 755           tsx6      setup_
 756           lda       ap|2,*              get processid
 757           sta       pds$arg_1
 758           tsplb     setup_check         switch stacks and lock
 759           arg       0,6
 760 
 761           tsx6      WRITE_LOCK          start must protect pid, rethreads
 762           ldx2      0,du                pre-set state to zero
 763           tsx7      hash_LOCK           Get pointer to apt entry
 764           arg       stop_returns_nul    start: indirect if error
 765           lcx0      apte.stop_pending+1,du turn off stop pending
 766           ansx0     bp|apte.flags
 767 "         lxl0      bp|state            pick up target's state
 768 "         cmpx0     stopped,du          Compare it to stopped state
 769 "         tnz       stop_returns        If not equal, return
 770           ldx0      blocked,du          Otherwise redefine target state
 771           tsx7      update_execution_state
 772           tsx7      wake                And awaken target
 773           lxl2      bp|apte.state       return target's state
 774           tra       stop_returns        return
 775 " ^L
 776 
 777 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 778 "
 779 " FORCE_STOP -- called to make the current process stop itself.
 780 "                   sometimes known as I_stop.
 781 "
 782 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 783 
 784 force_stop:
 785           getlp
 786           tsplb     setup_mask
 787           aos       bb|te_i_stop
 788           tsx7      update_te
 789           tsx6      WRITE_LOCK          I_stop unthreads
 790           tsx6      LOCK_bp
 791           lda       bp|apte.flags
 792           cana      apte.stop_pending,du check for stop pending
 793           tze       force_stop_not      no, return
 794           szn       bp|apte.term_processid  Is there a buzzard for this process?
 795           drlze     (pxss: No term_processid) NO - CRASH
 796           ldaq      bp|apte.alarm_time  check for alarm pending
 797           tze       force_stop_getwork  no alarm pending
 798 
 799           eax0      bp|0                thread out of alarm list
 800           cmpx0     bb|alarm_timer_list see if first on list
 801           tnz       is_scan
 802 
 803           ldx2      bp|apte.alarm_time  if so thread out
 804           stx2      bb|alarm_timer_list
 805           tra       force_stop_getwork
 806 
 807 is_scan:  ldx2      bb|alarm_timer_list search list for entry
 808 is_loop:  cmpx0     bb|apte.alarm_time,2
 809           tze       is_done
 810           ldx2      bb|apte.alarm_time,2
 811           tra       is_loop
 812 is_done:  ldx0      bp|apte.alarm_time  thread out of list
 813           stx0      bb|apte.alarm_time,2
 814 
 815 force_stop_getwork:
 816           tsx7      unthread            istop
 817           ldx0      stopped,du          set state to stopped
 818           tsx7      update_execution_state
 819           tsx7      revoke_elig         istop
 820           tsx7      reschedule          istop
 821           tsx7      purge_UNLOCK        istop
 822           eax4      0
 823           ldx0      bp|apte.ipc_pointers
 824           stx4      bp|apte.ipc_pointers
 825           tsx7      free_itt_
 826           tsx7      getwork
 827           drltra    (pxss: Stop returned from getwork) should never get here, nohow
 828 
 829 
 830 stop_return:
 831           short_return
 832 
 833 force_stop_not:
 834 UNLOCK2_switch_back:
 835           tsx6      UNLOCK_bp           force_stop done
 836           tsx6      UNLOCK              force_stop done
 837           tra       switch_back
 838 "^L
 839 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 840 "
 841 "         set_procs_required - entry to set and reset the
 842 "                   group of CPUs on which this process can run.
 843 "
 844 "         call pxss$set_procs_required (cpu_set, code)
 845 "                   cpu_set = bit (8) aligned CPU mask
 846 "                             ("0"b => set to system default)
 847 "                   code    = non-standard error code
 848 "                             0 => group set and now running in group
 849 "                             ^0 => no member of group online
 850 "
 851 "
 852 "         system default is a CPU mask stored in tc_data$default_procs_required
 853 "         It is used for processes which have not requested explicitly
 854 "         CPUs required, and for those which have reset to the default.
 855 "         To avoid various races (with reconfiguration, default changing, etc.),
 856 "         this cell should not be used or set without the global APT lock held
 857 "
 858 "         THIS ENTRY MUST NOT BE CALLED ON THE PRDS
 859 "
 860 "         It may, however, be called from a wired environment
 861 "         (the reason for non-standard error codes)
 862 "
 863 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 864 
 865 set_procs_required:
 866           ldx0      lp|prds_link        check whether we're on the prds
 867           cmpx0     sb|stack_header.stack_begin_ptr      already
 868           drlze     (pxss: sprq already on prds) invalid call--can't do much else
 869 
 870           tsx6      setup_
 871           ldq       ap|2,*              save argument in pds
 872           stq       pds$arg_1
 873           stz       ap|4,*              clear error code
 874           tsplb     setup_check         switch stacks and lock
 875           arg       0,6
 876           tsx6      WRITE_LOCK          sprq locks out getwork and reset_proc_req
 877 
 878           eax2      0                   assume set_procs (to non-default)
 879           ldq       pds$arg_1           refetch the argument
 880           anq       apte.procs_required_mask,du   strip out garbage
 881           tnz       pr_set              set
 882           ldq       bb|default_procs_required     system default
 883           anq       apte.procs_required_mask,du   shouldn't be garbage, but ...
 884           drlze     (pxss: APTE disdains all processors) we do this, nobody's running anyway
 885           eax2      1                   reset (to default)
 886 pr_set:
 887           canq      scs$processor       is any CPU in the set online
 888           tze       UNLOCK_sprq_error   yes--don't set, return error code
 889           eaa       0,qu                save group mask for check
 890           tsx6      LOCK_me_bp          sprq
 891           erq       bp|apte.procs_required        set into APTE
 892           anq       apte.procs_required_mask,du
 893           ersq      bp|apte.procs_required
 894 
 895           eax2      0,2                 set to default
 896           tnz       set_default_flag    yes
 897           lcx0      apte.default_procs_required+1,du
 898           ansx0     bp|apte.flags
 899           tra       set_reset_done
 900 set_default_flag:
 901           ldx0      apte.default_procs_required,du
 902           orsx0     bp|apte.flags
 903 set_reset_done:
 904 
 905 "
 906 "         Now check to see if we're on a CPU in the group. If not
 907 "         go thru getwork (which won't run us unless we're on such a CPU).
 908 "
 909           cana      prds$processor_pattern
 910           tnz       UNLOCK2_switch_back already on one, unlock everything and return
 911 
 912           call      page$cam            clear all caches if wrong cpu
 913           tsx7      update_te           get set for getwork
 914           ldx0      ready,du
 915           tsx7      update_execution_state
 916           tsx6      UNLOCK_bp           sprq unlock for getwk
 917           tsx6      UNLOCK              sprq unlocks before getwork
 918           tsx7      getwork
 919           eax7      0                   short_return after switch back
 920           tra       switch_back_ret_pds
 921 
 922 UNLOCK_sprq_error:
 923           tsx6      UNLOCK
 924           tsx7      switch_back_ret_pds
 925           stc1      ap|4,*              error code
 926           short_return
 927 
 928 " ^L
 929 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 930 "
 931 "         EMPTY_T  --  procedure to thread an APT entry into the APT
 932 "         free list.
 933 "
 934 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 935 
 936 empty_t:
 937           tsx6      setup_
 938           ldaq      ap|2,*              save input apt pointer
 939           staq      pds$arg_1
 940           tsplb     setup_check         switch stacks and lock
 941           arg       0,6
 942           tsx6      WRITE_LOCK          emtpty_t rethreads
 943           eppbp     pds$arg_1,*         get pointer to desired APT entry
 944           tsx6      LOCK_bp             empty_t changes state
 945           lxl0      bp|apte.state       Check state first
 946           cmpx0     empty,du            Already empty OK
 947           tze       et_1
 948           cmpx0     stopped,du          Also stopped OK
 949           drlnz     (pxss: empty_t APTE not stopped or empty)
 950           ldx0      empty,du
 951           tsx7      update_execution_state Changed stopped to empty.
 952 et_1:
 953           eax7      0
 954           ldx5      bp|apte.ipc_pointers claim ITTE's while locked, free later
 955           stx7      bp|apte.ipc_pointers
 956           stz       bp|apte.ittes_sent            safe to zero these since piud=0
 957           stz       bp|apte.ittes_got
 958 
 959 "         Return any stack_0 owned by the defunct process
 960 
 961           lda       bp|apte.flags
 962           cana      apte.shared_stack_0,du        Is there as stack_0 to return?
 963           tze       check_stack_0_none            No
 964 
 965           tsx6      lock_stack_queue
 966           eaa       bp|0                au = apte offset
 967           arl       18                  al = apte offset
 968           ldq       -1,du               comparison mask
 969           lxl0      ab|sdt.num_stacks   number of stack_0's
 970           eax4      0                   index into sdt
 971 check_stack_0_loop:
 972           cmk       ab|sdt.aptep,4      this stack_0 belong to deadproc
 973           tnz       bump_next_stack_0   no
 974           tsx6      free_stack_0        yes--give it up
 975           ldx0      1,du
 976           asx0      bb|max_max_eligible number available stack_0's
 977           lca       1,dl
 978           asa       bb|stopped_stack_0  count of suspended stack_0's
 979           tra       check_stack_0_done
 980 bump_next_stack_0:
 981           eax4      sdte_size,4         bump sdt index
 982           eax0      -1,0                one less sdte
 983           tpnz      check_stack_0_loop  transfer if more to go
 984 check_stack_0_done:
 985           tsx6      unlock_stack_queue
 986 
 987 check_stack_0_none:
 988           tsx6      UNLOCK_bp
 989           ldx4      bb|empty_q          thread into free list
 990           stx4      bp|apte.thread      singly threaded
 991           eax4      bp|0                get pointer to this entry
 992           stx4      bb|empty_q          to update into empty_q
 993           tsx6      UNLOCK              empty_t uses  lock to protect empty_q
 994           eax4      0
 995           stx4      bp|apte.ipc_pointers  zero itt thread in apte
 996           eax0      0,5                 restore old itt thread
 997           tsx7      free_itt_
 998           tra       switch_back
 999 " ^L
1000 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1001 "
1002 "         UPDATE_EXECUTION_STATE -- subroutine to store the execution
1003 "         state passed in x0 into the APTE pointed to by bp. The
1004 "         appropriate counters in tc_data are also updated.
1005 "
1006 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1007 
1008 update_execution_state:
1009           szn       bp|apte.lock        ASSUME bp locked
1010           drlnz     (pxss: APTE not locked) ASSUME bp locked
1011           lda       bp|apte.flags       dont change meters for idle
1012           cana      apte.idle,du
1013           tnz       update_exec_ret
1014           lxl4      bp|apte.state       get previous (old) state
1015           lca       1,dl
1016           asa       bb|statistics,4
1017           aos       bb|statistics,0
1018 "old_assume_state_change_ok
1019 update_exec_ret:
1020           sxl0      bp|apte.state
1021           read_clock                    " read the clock
1022           staq      bp|apte.state_change_time for state change time
1023           tra       0,7
1024 
1025 
1026 
1027 " ^L
1028 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1029 "
1030 "         UNTHREAD -- procedure to thread the APT entry pointed to by
1031 "         bp out of the list it is in.
1032 "
1033 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1034 
1035 unthread:
1036           szn       tc_data$apt_lock    ASSUME write locked
1037           drlmi     (pxss: APT not locked) ASSUME write locked
1038           szn       bp|apte.thread      check if not in a list
1039           tze       0,7                 return if not in a list
1040           lxl4      bp|apte.thread      x4 -> previous entry in list
1041           drlze     (pxss: unthread null back ptr) ASSUME cur.bp nonzero
1042           eax0      bp|0                ASSUME prev.fp -> cur
1043           cmpx0     bb|apte.thread,4    ASSUME prev.fp -> cur
1044           drlnz     (pxss: unthread prev.fp ^= cur) ASSUME prev.fp -> cur
1045           ldx0      bp|apte.thread      x0 -> next entry in list
1046           drlze     (pxss: unthread null cur.fp) ASSUME cur.fp nonzero
1047           stx0      bb|apte.thread,4    store old forward in previous
1048           sxl4      bb|apte.thread,0    store old back in next
1049           stz       bp|apte.thread      zero thread pointers
1050           tra       0,7
1051 " ^L
1052 
1053 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1054 "
1055 "         GET_ENTRY  -  returns pointer to empty entry
1056 "
1057 "         On return, apte is unthreaded, unlocked, and procs_required
1058 "         is set to the system default. Other fields are cleared.
1059 "
1060 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1061 
1062 get_entry:
1063           tsplb     setup_mask
1064           tsx6      WRITE_LOCK          get_entry unthreads
1065           ldx0      bb|empty_q          x0 points to first entry on list
1066           tnz       available_entries   ok if non-zero
1067           eppbp     null,*              None available
1068           tra       get_entry_returns   So return
1069 available_entries:
1070           lca       1,dl                Decrement count of free APTE's
1071           asa       bb|statistics+empty Caller must AOS new state
1072           ldx1      bb|apte.thread,0    thread entry out of free list
1073           stx1      bb|empty_q
1074           eppbp     bb|0,0
1075           tsx6      LOCK_bp             get_entry locks before zeroing
1076           mlr       (),(pr),fill(0)     Zero out APTE
1077           desc9a    0,0
1078           desc9a    bp|0,size_of_apt_entry*4
1079           ldx0      apte.default_procs_required,du  system default
1080           orsx0     bp|apte.flags
1081           lda       bb|default_procs_required
1082           ana       apte.procs_required_mask,du
1083           drlze     (pxss: APTE disdains all processors) never happen
1084           sta       bp|apte.procs_required
1085           tsx6      UNLOCK_bp           get_entry makes apte lockable
1086 get_entry_returns:
1087           tsx6      UNLOCK              get_entry done
1088           tsx7      switch_back_ret
1089           spribp    ap|2,*              return pointer to new APT entry
1090           short_return
1091 
1092 
1093 "^L
1094 
1095 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1096 "
1097 "         SET_WORK_CLASS -- entry to move a process from one work_class to
1098 "         another.  Call is:
1099 "                   call pxss$set_work_class (processid, new_wc, old_wc, code)
1100 "
1101 "         processid -bit (36) aligned specifies process (INPUT)
1102 "         new_wc    -fixed bin specifies new work class (INPUT)
1103 "         old_wc    -fixed bin previous value of work_class (OUTPUT)
1104 "         code      -fixed bin. 0=>OK, 1=>bad_processid, 2=>bad_work_class (OUTPUT)
1105 "
1106 "         The steps are:
1107 "         1. Find apte given processid.
1108 "         2. Compute old_wc from apte.wct_index.
1109 "         3. Compute new wct_index from new_wc.
1110 "         4. If ready & not eligible move to new queue.
1111 "
1112 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1113 
1114 set_work_class:
1115           tsx6      setup_
1116           lda       ap|2,*              get processid
1117           sta       pds$arg_1
1118           lda       ap|4,*              get new_wc
1119           sta       pds$arg_2           into wired storage.
1120 
1121           tsplb     setup_check         switch stacks and lock
1122           arg       0,6
1123           tsx6      WRITE_LOCK          set_work_class rethreads, protects pid
1124           stz       pds$arg_3           Clear old_wc now.
1125           lda       1,dl                Assume processid bad,
1126           sta       pds$arg_4           set code to 1.
1127           tsx7      hash_LOCK
1128           arg       swc_ret_nul         indirect if error
1129           lda       bp|apte.flags       If process is idle
1130           cana      apte.idle,du        skip craziness.
1131           tnz       swc_ret             Return code = 1.
1132 
1133           aos       pds$arg_4           Preset code to 2, bad new_wc
1134           ldq       bp|apte.wct_index   Pick up old index into WCT.
1135           eax1      0,qu                oldwc in X1
1136           sbq       bb|min_wct_index    Convert it to a number.
1137           div       size_of_wct_entry,du The first wc_num is zero.
1138           stq       pds$arg_3           Reurn old_wc.
1139 
1140           ldq       pds$arg_2           Pick up new wc number.
1141           tmi       swc_ret             Return code = 2, bad new_wc.
1142           mpy       size_of_wct_entry,du Convert number to index.
1143           adlq      bb|min_wct_index
1144           tmi       swc_ret             user gave us very big wc
1145           cmpq      bb|max_wct_index    Make sure not oob on WCT
1146           tpnz      swc_ret             Return code = 2, bad new_wc.
1147           lda       bb|wcte.flags,qu    Make sure this wc is defined.
1148           cana      wcte.defined,du
1149           tze       swc_ret             Return code = 2, bad new_wc.
1150           stbq      bp|apte.wct_index,60 OK- set new value.
1151           stz       pds$arg_4           Clear code now.
1152 
1153           szn       bp|apte.thread      Threaded in some queue?
1154           tze       swc_ret             No. All done.
1155           lda       bp|apte.flags       Yes.
1156           cana      apte.eligible,du    In the eligible queue?
1157           tnz       swc_elig            Yes. Don't mess around.
1158           tsx7      unthread            Not eligible, remove from curr rdyq.
1159           lda       bp|apte.ts          If ts is non-zero then sort in before
1160           sta       before              but if ts is zero, sort in after.
1161           lda       bp|apte.ti          Prepare to jump into sort subr
1162           tsx7      sort_in_again       which requires ti in the A.
1163 swc_ret:
1164           tsx6      UNLOCK_bp           set_wc unlocks APTE
1165 swc_ret_nul:
1166           tsx6      UNLOCK              set_wc unlocks
1167           lxl2      pds$arg_4           Get pseudo errcode
1168           tsx7      switch_back_ret
1169           lda       pds$arg_3           Return output args to caller.
1170           sta       ap|6,*
1171           xec       swc_code_table,2    Load A with real errcode
1172           sta       ap|8,*
1173 
1174           short_return
1175 
1176 swc_elig:
1177           lca       1,dl
1178           asa       bb|wcte.nel,1       Reduce former wc
1179           aos       bb|wcte.nel,qu      Increm new
1180           tra       swc_ret
1181 "
1182 "Table to map err = 0|1|2 to real (but unwired) error_code
1183 swc_code_table:
1184           eaa       0                   No error
1185           lda       error_table_$bad_processid
1186           lda       error_table_$bad_work_class
1187 
1188 
1189 
1190 "^L
1191 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1192 "
1193 "         GUARANTEED_ELIGIBILITY_ON - this primitive guarantees that this
1194 "         process has at least a certain minimum amount of time left in its
1195 "         eligibility quantum. The primitive does not return until the process will
1196 "         retain eligibility for the specified minimum time. Also if the process
1197 "         loses its eligibility it is given a higher priority scheduling quaranteeing
1198 "         the process some fixed percentage of an eligibility slot. The high priority
1199 "         scheduling is in effect until turned off.
1200 "
1201 "         GUARANTEED_ELIGIBILITY_OFF - this primitive turns off the high
1202 "         priority scheduling granted by guarranteed_eligibility_on.
1203 "
1204 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1205 
1206 guaranteed_eligibility_on:
1207           eppbp     pds$apt_ptr,*       set bp-> own apte
1208           lda       apte.prior_sched,dl Turn on high priority mode
1209           orsa      bp|apte.flags2
1210           lda       4,du                Boost time slice
1211           asa       bp|apte.temax
1212           short_return
1213 
1214 guaranteed_eligibility_off:
1215           eppbp     pds$apt_ptr,*       set bp-> own apte
1216           lca       apte.prior_sched+1,dl turn off priority scheduling
1217           ansa      bp|apte.flags2      ..
1218           lda       bp|apte.temax       Reduce time slice if need be
1219           tmi       ge_off_ret
1220           sba       4,du
1221           tpl       *+2                 Leave positive, tho ..
1222           lda       1000,dl
1223           sta       bp|apte.temax
1224 ge_off_ret:
1225           short_return
1226 "^L
1227 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1228 "
1229 "         RELINQUISH_PRIORITY
1230 "
1231 "         This primitive lowers the traffic control priority of the
1232 "         invoking process by moving it to the tail of the eligible queue.
1233 "         This is intended for long-running ring-0 functions which operate
1234 "         as background (e.g., the scavenger). A long-running ring-0
1235 "         function migrates to the head of the eligible queue and thereby
1236 "         gains a high priority.
1237 "
1238 "         call pxss$relinquish_priority
1239 "
1240 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1241 
1242 relinquish_priority:
1243           tsplb     setup_mask                    " Switch stacks and mask
1244           tsx6      WRITE_LOCK                    " We rethread
1245           tsx6      LOCK_bp                       " And change state
1246 
1247           tsx7      unthread                      " Remove from eligible queue
1248           ldx0      ready,du
1249           tsx7      update_execution_state        " Change state from running
1250           eax1      bb|eligible_q_tail            " Thread to end of eligible queue
1251           tsx7      thread_him_in
1252 
1253           tsx6      UNLOCK_bp
1254           tsx6      UNLOCK
1255           aos       bb|relinquishes               " Meter
1256           tsx7      getwork
1257           tra       switch_back_pds
1258 
1259 "^L
1260 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1261 "
1262 "         SET_TIMER  -- entry to set the per-process cpu timer.
1263 "         Call is:
1264 "                   call pxss$set_timer(delta_t, ev_channel)
1265 "
1266 "         dcl delta_t fixed bin (35),   /* time to be added to current time.
1267 "             ev_channel fixed bin (71)
1268 "
1269 "         If ev_channel is zero an IPS signal will be sent rather than
1270 "         a wakeup.
1271 "         Nothing need be locked for setting timer, provided the
1272 "         time_out cell is cleared while operating.  This is so getwork
1273 "         will ignore the timer channel if we happen through getwork.
1274 "
1275 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1276 
1277 set_timer:
1278           eppbp     pds$apt_ptr,*       Get ptr to own apte
1279           fld       0,dl                Put zero in AQ
1280           staq      pds$timer_time_out  Cancel any timer
1281           ldaq      ap|4,*              Now safe to set channel
1282           staq      pds$timer_channel
1283 
1284           fld       0,dl                Want two words but given one
1285           ldq       ap|2,*              Pick up delta_t
1286           tmoz      zero_chan           if delta_t <= 0 then reset
1287           tra       rel_time            else set relative timer
1288 
1289 set_cpu_timer:
1290           eppbp     pds$apt_ptr,*       Get ptr to own apte
1291           fld       0,dl                Cancel any timer
1292           staq      pds$timer_time_out  Now if we getwork we will not have timer go off
1293           ldaq      ap|6,*              safe to set channel now
1294           staq      pds$timer_channel
1295 
1296           ldaq      ap|2,*              Put time arg in AQ
1297 
1298           lxl0      ap|4,*              pick up timesw arg
1299           cmpx0     2,du                Absolute timer?
1300           tze       abs_time            If so go do it
1301           cmpx0     1,du                Relative timer?
1302           tze       rel_time            If so then relative
1303 
1304 zero_chan:
1305           fld       0,dl                resetting--timeout already zero
1306           staq      pds$timer_channel
1307           short_return
1308 
1309 rel_time: adaq      bp|apte.virtual_cpu_time
1310 abs_time: staq      pds$timer_time_out  Now safe to set timeout
1311           short_return
1312 " ^L
1313 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1314 "
1315 "         PXSS$LOCK_APT                 PXSS$UNLOCK_APT
1316 "
1317 "         Externally available entries to manipulate
1318 "         apt lock.  Caller must be wired and masked.
1319 "
1320 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1321 
1322 lock_apt: push
1323           tsx6      WRITE_LOCK          Give caller protection.
1324           return
1325 
1326 
1327 unlock_apt:
1328           push
1329           tsx6      UNLOCK
1330           return
1331 
1332 "^L
1333 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1334 "
1335 "         PXSS$LOCK_APTE
1336 "
1337 "         Externally available routine to lock an APTE
1338 "
1339 "         call pxss$lock_apte (processid, aptep, code)
1340 "
1341 "         processid  is Input
1342 "         aptep is set on return (null if APTE) not locked
1343 "         code = 0 => APTE locked
1344 "              ^=0 => processid invalid
1345 "
1346 "         Caller must be wired and masked and real careful
1347 "
1348 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1349 
1350 lock_apte:
1351           push
1352           eppbb     tc_data$
1353           lda       ap|2,*              processid
1354           sta       pds$arg_1           for hash_LOCK
1355           stc1      ap|6,*              non-zero return code
1356           tsx7      hash_LOCK           Try to lock APTE
1357           arg       lock_apte_null      Fail
1358           stz       ap|6,*              Succeed - zero return code
1359 lock_apte_null:
1360           spribp    ap|4,*              aptep
1361           return
1362 
1363 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1364 "
1365 "         PXSS$UNLOCK_APTE
1366 "
1367 "         Externally available entry to unlock an APTE
1368 "
1369 "         call pxss$unlock_apte (aptep)
1370 "
1371 "         aptep is a pointer to the APTE to unlock
1372 "         caller should still be masked and wired
1373 "
1374 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1375 
1376 unlock_apte:
1377           push
1378           eppbp     ap|2,*              ptr to aptep
1379           eppbp     bp|0,*              aptep
1380           epbpbb    bp|0                tc_data
1381           tsx6      UNLOCK_bp           Unlock APTE
1382           return
1383 "^L
1384 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1385 "
1386 "         Subroutines to lock and unlock the APT
1387 "         Meaning of lock values is
1388 "         +N        APT is locked for single writer with caller||cpu_tag
1389 "         0         lock is busy/hidden/out_to_lunch
1390 "         -1        APT is unlocked
1391 "         -(N+1)    APT is locked for N readers
1392 "
1393 "         Note that the lock value is claimed by a
1394 "         primitive LDAC and restored by a primitive STA.
1395 "         Note that lock_loops take special care not to
1396 "         keep lock in busy state (~anti-hog hardware)
1397 "
1398 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1399 
1400 READ_LOCK:
1401           read_clock                    " setup for metering looplocks
1402           staq      temp
1403           eax5      0                   but assume no need to meter looplocks
1404 read_:
1405           ldac      tc_data$apt_lock
1406           tpnz      r_put               was write locked
1407           tze       read_               was busy try again
1408           sba       1,dl                was unlocked or read locked
1409           sta       tc_data$apt_lock    one more reader
1410 rw_ret:   eax5      0,5                 See if looplock metering needed
1411           tze       0,6
1412           read_clock
1413           sbaq      temp
1414           adaq      tc_data$loop_lock_time
1415           staq      tc_data$loop_lock_time
1416           aos       tc_data$loop_locks
1417           tra       0,6
1418 
1419 r_put:    sta       tc_data$apt_lock    restor locks state
1420 r_wait:   szn       tc_data$apt_lock    loop till unlocked or readlocked
1421           tmi       read_               was unlocked or read locked
1422           eax5      1                   force looplock metering
1423           tra       r_wait              was busy or write locked
1424 
1425 
1426 WRITE_LOCK:
1427           read_clock
1428           staq      temp
1429           eax5      0
1430 write_:
1431           ldac      tc_data$apt_lock
1432           cmpa      unlocked_APT
1433           tnz       w_fail              busy or lockd for read or write
1434           eaa       0,6                 lock with caller||cpunum
1435           ada       prds$processor_tag
1436           sta       tc_data$apt_lock
1437           tra       rw_ret              join looplock meter code
1438 w_fail:   cmpa      0,dl                if was not busy
1439           tze       w_wait
1440           sta       tc_data$apt_lock    then restor lock value
1441 w_wait:   lda       unlocked_APT        loop till unlocked
1442           cmpa      tc_data$apt_lock
1443           tze       write_
1444           eax5      1                   force looplock metering/
1445           tra       w_wait
1446 
1447 
1448 UNLOCK:   ldac      tc_data$apt_lock
1449           tmi       unread
1450           tze       UNLOCK              busy so retry
1451           lda       unlocked_APT        was write locked so now unlock
1452           tra       unlock_
1453 unread:   ada       1,dl                one less reader
1454           drlze     (pxss: unlock apt read lock bad count) DEBUG somebody lostcount
1455 unlock_:  sta       tc_data$apt_lock
1456           tra       0,6
1457 
1458 
1459 WRITE_TO_READ:
1460           ldac      tc_data$apt_lock
1461           tpnz      w_to_r              got lock
1462           tze       WRITE_TO_READ
1463           drltra    (pxss: write_to_read bad lock count) somebody lost count
1464 w_to_r:
1465           cmpa      tc_data$apt_lock    DEBUG
1466           drlze     (pxss: write_to_read ldac failed) DEBUG ldac must have failed to clear
1467           lca       2,dl                set lock value to one reader
1468           sta       tc_data$apt_lock
1469           tra       0,6
1470 
1471 unlocked_APT:
1472           dec       -1
1473 
1474 "^L
1475 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1476 "
1477 "         APTE LOCKING PROCEDURES
1478 "         apte is locked if apte.lock = 0
1479 "         apte is unlocked if apte.lock ^= 0
1480 "         Note that address of caller of unlock is saved in apte.lock
1481 "
1482 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1483 
1484 LOCK_me_bp:
1485           eppbp     pds$apt_ptr,*       get ptr to own apte
1486           epbpbb    bp|0                get ptr to base of tcdata
1487 LOCK_bp:
1488           sznc      bp|apte.lock
1489           tnz       0,6
1490           tra       LOCK_bp
1491 
1492 UNLOCK_bp:
1493           szn       bp|apte.lock        DEBUG
1494           drlnz     (pxss: UNLOCK_bp not locked) DEBUG
1495           stx6      bp|apte.lock        Remember last unlocker
1496           tra       0,6
1497 
1498 LOCK_x2:
1499           sznc      bb|apte.lock,2
1500           tnz       0,6
1501           tra       LOCK_x2
1502 
1503 UNLOCK_x2:
1504           szn       bb|apte.lock,2      DEBUG
1505           drlnz     (pxss: UNLOCK_X2 not locked) DEBUG
1506           stx6      bb|apte.lock,2      Remember last unlocker
1507           tra       0,6
1508 
1509 LOCK_x3:
1510           sznc      bb|apte.lock,3
1511           tnz       0,6
1512           tra       LOCK_x3
1513 
1514 UNLOCK_x3:
1515           szn       bb|apte.lock,3      DEBUG
1516           drlnz     (pxss: UNLOCK_x3 not locked) DEBUG
1517           stx6      bb|apte.lock,3      Remember last unlocker
1518           tra       0,6
1519 
1520 "^L
1521 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1522 "
1523 "         stack switching subroutines
1524 "
1525 "         A routine which holds the global traffic control lock or an
1526 "         APTE lock cannot be interrupted in a way which would cause
1527 "         reinvocation of pxss.  For this reason, pxss must run on the
1528 "         PRDS.  However, most of its entries may be called from an
1529 "         unwired environment.  To accomplish this, arguments to pxss
1530 "         are copied into wired storage in the PDS prior to any stack
1531 "         switching.  This copying may result in loss of control of
1532 "         a CPU and reinvocation of pxss (e.g., because of a page
1533 "         fault), and overwriting of the PDS cells used for argument
1534 "         storage.  To avoid this interference, all entries of pxss
1535 "         which can be called from an unwired environment adhere to
1536 "         following protocol:
1537 "
1538 "         tsx6      setup_
1539 "
1540 "           (Copy arguments to PDS and set any flags used as temporaries
1541 "            in the PDS - x6 and pr0 must be preserved in this code)
1542 "
1543 "         tsplb     setup_check
1544 "         arg       0,6
1545 "           (Next Instruction)
1546 "
1547 "         On return to (Next Instruction), we are running on the PRDS
1548 "         with interrupts masked, and the values of all temporaries in
1549 "         the PDS are guaranteed to be those set between the call to
1550 "         setup_ and the call to setup_check.  These values are
1551 "         guaranteed to be safe until either getwork is called or one of
1552 "         the routines to switch stacks back is called.
1553 "
1554 "         Routines which can be called only from a wired environment
1555 "         must set the cell pds$pxss_args_invalid to non-zero if they
1556 "         use ANY temporaries in the PDS.
1557 "
1558 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1559 "^L
1560 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1561 "
1562 "         setup_
1563 "
1564 "         subroutine to mark begin of argument copy to PDS
1565 "
1566 "         tsx6      setup_
1567 "
1568 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1569 
1570 setup_:   stz       pds$pxss_args_invalid         clear interference flag
1571           tra       0,6                           return to next instruction
1572 
1573 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1574 "
1575 "         setup_check
1576 "
1577 "         subroutine to check for successful copy of temporaries
1578 "
1579 "         tsplb     setup_check
1580 "         arg       <return if args must be re-copied>
1581 "         <return if args copied successfully, wired and masked>
1582 "
1583 "         On successful return, bp -> apte for this process
1584 "                               bb -> base of tc_data
1585 "                               ap has been saved in pds$tc_argp
1586 "
1587 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1588 
1589           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+><+><+><+><+><+><+>
1590 setup_check:
1591           sznc      pds$pxss_args_invalid Did we get overwritten?
1592           tnz       lb|0,*              Cause err exit, get args copied again.
1593           epplb     lb|1                Fix return address.
1594 
1595 "         Fall through to setup_mask
1596 
1597 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1598 "
1599 "         setup_mask
1600 "
1601 "         mask to sys_level, save current mask in pds$tc_mask (unless on PRDS) and
1602 "         switch stacks to PRDS (by invoking setup)
1603 "
1604 "         tsplb     setup_mask
1605 "
1606 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1607 
1608 setup_mask:
1609           spriap    pds$tc_argp
1610           eppab     sp|0
1611           ldx0      lp|prds_link        are we on the PRDS
1612           cmpx0     sb|stack_header.stack_begin_ptr
1613           tze       easy                yes - already masked - fall thru
1614           lxl1      prds$processor_tag
1615           lprpab    scs$mask_ptr,1      get set for masking
1616           xec       scs$read_mask,1
1617           staq      pds$tc_mask         THIS MUST BE WIRED!
1618           ldaq      scs$sys_level
1619           xec       scs$set_mask,1
1620 
1621 "         Fall through to setup
1622 "^L
1623 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1624 "
1625 "         setup
1626 "
1627 "         switch stacks to PRDS.  If stacks are indeed
1628 "         switched (not running on PRDS already), the current stack
1629 "         pointer is saved in pds$last_sp
1630 "
1631 "         setup is intended to be called directly only by page control
1632 "         "side doors", where it is known that we are running on
1633 "         the PRDS.  These "side doors" must not call any switch_back_xxx
1634 "         routines, as this would re-load an interrupt mask saved elsewhere.
1635 "
1636 "         tsplb     setup
1637 "
1638 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1639 
1640 setup:
1641           eppab     sp|0                save stack pointer
1642           ldx0      lp|prds_link        are we on prds ?
1643           cmpx0     sb|stack_header.stack_begin_ptr
1644           tze       easy                yes, easy save
1645 
1646           sprisp    pds$last_sp         save pointer to previous stack frame
1647           eppsp     prds$+stack_header.stack_begin_ptr,* get ptr to new frame
1648           epbpsb    sp|0                get stack base ptr
1649 easy:     push
1650           spriab    sp|stack_frame.prev_sp save prev sp
1651           eppbp     pds$apt_ptr,*       get own apt pointer
1652           epbpbb    bp|0                set bb to point at base of tc_data
1653           tsx6      init_pxss_save_stack
1654           tra       lb|0                return
1655 
1656 "^L
1657 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1658 "
1659 "         routines to switch back to calling environment
1660 "
1661 "         These routines all restore the interrupt mask to the value
1662 "         saved in pds$tc_mask and the value of ap to the value
1663 "         saved in pds$tc_argp
1664 "
1665 "         tsx7      switch_back_xxx
1666 "         (Next Instruction)
1667 "
1668 "         switch_back_pds - return to caller of pxss on unwired stack
1669 "
1670 "         switch_back - pop a stack frame, switching stacks if necessary,
1671 "                   return to caller of pxss
1672 "
1673 "         switch_back_ret - pop a stack frame, switching stacks if necessary,
1674 "                   return to (Next Instruction)
1675 "
1676 "         switch_back_ret_pds - switch to unwired stack, return to
1677 "                   (Next Instruction)
1678 "
1679 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1680 
1681 switch_back_pds:                        "return uncond. to pds history
1682           eax7      0
1683           tra       restore_sp
1684 
1685 switch_back:
1686           eax7      0                   flag to distinguish from switch_back_ret
1687 switch_back_ret:
1688           ldx0      lp|prds_link        do we have to switch stacks
1689           cmpx0     sp|stack_frame.prev_sp ..
1690           tnz       restore_sp          yes, skip simple switch
1691           eppsp     sp|stack_frame.prev_sp,* go back one frame
1692           tra       no_change_mask      and keep masked
1693 restore_sp:
1694 switch_back_ret_pds:
1695           eppsp     pds$last_sp,*       switch to other stack
1696           ldaq      prds$+stack_header.stack_begin_ptr restore stack end ptr
1697           staq      prds$+stack_header.stack_end_ptr ..
1698 
1699           epbpsb    sp|0
1700           ldaq      pds$tc_mask         restore previous mask
1701           oraq      channel_mask_set
1702           anaq      scs$open_level
1703           lxl1      prds$processor_tag
1704           lprpab    scs$mask_ptr,1      get set for masking
1705           xec       scs$set_mask,1
1706 no_change_mask:
1707           stc1      pds$pxss_args_invalid Signal possible mutual interference.
1708           eax7      0,7                 check who made call
1709           tze       short_ret
1710           eppap     pds$tc_argp,*       Get pxss arg list
1711           tra       0,7
1712 
1713           inhibit   off                 <-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><->
1714 
1715 init_pxss_save_stack:
1716           eaa       pxss_save_stack     get address of save stack base
1717           ora       pxss_stack_size*64,dl set up a tally word for storing into pxss_save_stack
1718           sta       pxss_stackp         stash this away
1719           tra       0,6                 return to caller
1720 
1721 
1722 subroutine_save:
1723           stx7      pxss_stackp,id      store x7 in save stack using tally word
1724           ttf       0,6                 return to the caller if tally not runout
1725           drltra    (pxss: subroutine_save stack overflow) die - we have run off the save stack
1726 
1727 subroutine_unsave:
1728           ldx7      pxss_stackp,di      pop value of x7 (also updating tally word properly)
1729           tra       0,7
1730 
1731 send_connect:
1732           ldq       bp|apte.flags       see if processor to be stopped is running
1733           canq      apte.dbr_loaded,du  by checking the dbr-loaded flag
1734           tze       0,7                 not running, return
1735 
1736           eax0      bp|0                APTE offset in X0
1737           cmpx0     pds$apt_ptr+1       is this process target of connect?
1738           tze       delay_connect       if so, just set ring alarm for now
1739 
1740           ldq       bp|apte.flags2      is running- must send cpu stop connect
1741           anq       apte.pr_tag_mask,dl leave only processor tag
1742           cioc      scs$cow_ptrs,ql*    zap the processor
1743           tra       0,7                 return to caller
1744 
1745 delay_connect:
1746           lda       1,dl                set ring alarm register
1747           sta       pds$alarm_ring      ..
1748           lra       pds$alarm_ring      ..
1749           tra       0,7                 and return to caller
1750 
1751 " ^L
1752 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1753 "
1754 "         MAKE_ITT_MESSAGE
1755 "
1756 "         subroutine to make a wakeup-associated message,
1757 "         allocate an entry for it in the ITT, and add this entry
1758 "         to the tail of this process' event queue in the APT.
1759 "
1760 "         Caller must set pds$wakeup_flag to control whether non-unique
1761 "         messages will be sent.
1762 "
1763 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1764 
1765 make_itt_message:
1766 " bp points to process' APT entry and must not be changed
1767 
1768           bool      event_channel_type_mask,040000
1769 
1770           szn       bp|apte.lock        ASSUME bp locked
1771           drlnz     (pxss: APTE not locked) ASSUME bp locked
1772           stz       errcode             we have run into no problem yet
1773 
1774           lda       tmp_ev_channel+1    check for special channel
1775           ana       event_channel_type_mask,du mask everything but type
1776           tnz       mimj2               if not, continue
1777 
1778           lxl0      tmp_ev_channel+1    get special channel index
1779           lda       =o400000,du         get wakeup bit
1780           arl       apte.chans_offset-1,0 move to correct cell
1781           ana       apte.special_chans,dl change only special channels
1782           orsa      bp|apte.flags2      put in APT
1783           tra       0,x7                " return
1784 
1785 mimj2:
1786           ldac      bb|itt_free_list    Grab head
1787           tmi       itt_overflows       there are no more entries available
1788           tze       *-2
1789 
1790           eax1      0,au                move head to X1
1791 "                                       XR0 contains forward thread
1792           ldx0      bb|itt_entry.next_itt_relp,1
1793           stx0      bb|itt_free_list    restor free-list-head
1794 
1795           aos       bb|used_itt         count ITT entry usage
1796           lda       tmp_ring            get caller's validation ring
1797           sta       bb|itt_entry.origin,1 put ring number in ITT message
1798           lda       pds$processid       get this process (sender's) ID
1799           sta       bb|itt_entry.sender,1 put sender ID in ITT message
1800           eax3      0,au                X3 -> sender
1801           lxl0      dev_signal          get origin flag(1=dev-signal)
1802           tnz       *+2                 if not dev_signal
1803           aos       bb|apte.ittes_sent,3 charge sender
1804           stx0      bb|itt_entry.origin,1 store in origin LHE
1805           aos       bp|apte.ittes_got   charge rcvr
1806           lda       pds$arg_1           get processid of target
1807           sta       bb|itt_entry.target_id,1 store target process' ID in ITT message
1808           ldaq      tmp_ev_message      get event message
1809           staq      bb|itt_entry.message,1 put event message in ITT entry
1810           ldaq      tmp_ev_channel      get target event channel's name
1811           staq      bb|itt_entry.channel_id,1 put channel name in ITT message, and AQ-reg
1812 "                                       zero thread this entry will be the last
1813           stz       bb|itt_entry.next_itt_relp,1
1814 
1815 "
1816 "Check situation and counts to see if we allow usage of itte.
1817           stz       count               if count is zero there is no per channel limit
1818           eax5      0
1819           lda       bb|used_itt         if U < C/4 then no checks
1820           cmpa      bb|cid4
1821           tmi       mim_check_done
1822           lda       bb|initializer_id   load A-reg for mi_iz_xxx
1823           ldx0      bb|itt_entry.origin,1 dev_signals are different
1824           tnz       mim_check_ds        nz means dev_signal
1825 "Checks for non-dev_signal
1826           ldq       bb|cid2
1827           tsx6      mm_iz_either        D = C/2 or 0
1828           adq       bb|cid3
1829           cmpq      bb|apte.ittes_sent,3
1830           tmi       unmake_message      if sent > D + C/3 then REJECT
1831           cmpq      bp|apte.ittes_got
1832           tmi       unmake_message      if got > D + C/3 then REJECT
1833 
1834           sbq       bb|cid3
1835           adq       bb|cid2
1836           sbq       bb|apte.ittes_sent,3
1837           sbq       bp|apte.ittes_got
1838           tmi       unmake_message      if sent+got > D + C/2 then REJECT
1839 
1840           ldq       bb|itt_size
1841           sbq       bb|used_itt
1842           sbq       bb|apt_size
1843           tmi       unmake_message      if U > C then REJECT
1844           tra       mim_check_done
1845 
1846 "Checks for dev_signals
1847 mim_check_ds:
1848           ldq       bb|cid4
1849           cmpq      bp|apte.ittes_got   if got <  C/4 then OK
1850           tpl       mim_check_done
1851           qls       18                  else chan_limit =  C/4
1852           stq       count
1853 mim_check_done:
1854 " append this message to the tail of the process' event queue
1855           ldx0      bp|apte.ipc_pointers get head of process' event message queue
1856           tnz       find_queue_end      go follow queue to end
1857           eax0      0,1                 load XR0 from XRR1
1858           stx0      bp|apte.ipc_pointers this entry is first in q
1859           tra       0,7                 end of event message production
1860 find_queue_end:
1861           ldaq      tmp_ev_channel      event channel for compare
1862           szn       pds$wakeup_flag     should we insure uniqueness?
1863           tze       mumloop             yes - go to that loop
1864           szn       count               must we count wkups on chan?
1865           tnz       mumloop             yes - go to that loop
1866 
1867 mimloop:
1868 "                                       get forward thread from next entry
1869           ldx4      bb|itt_entry.next_itt_relp,0
1870           tze       append_itt_message  it is the end of the queue
1871           eax0      0,4                 XR0 points to next entry
1872           tra       mimloop
1873 
1874 mumloop:  cmpaq     bb|itt_entry.channel_id,0 this chan = new?
1875           tze       mum_ck
1876 mum_ok:   ldx4      bb|itt_entry.next_itt_relp,0
1877           tze       maybe_append_itt_message x0 -> last itte
1878           eax0      0,4
1879           tra       mumloop
1880 
1881 mum_ck:
1882           eax5      1,5                 Another itte for this channel
1883           szn       pds$wakeup_flag
1884           tnz       mum_ok              not unique entry, just counting
1885           ldaq      tmp_ev_message      is msg = new?
1886           cmpaq     bb|itt_entry.message,0
1887           tnz       mum_ck_ret          not same - go fix AQ then loop more
1888           ldaq      bb|itt_entry.origin,1 test origin,ring,target
1889           cmpaq     bb|itt_entry.origin,0
1890           tze       unmake_message      everthing same=> dont need itte
1891 mum_ck_ret:
1892           ldaq      tmp_ev_channel      restor chan to AQ for compare
1893           tra       mum_ok
1894 
1895 
1896 maybe_append_itt_message:
1897           szn       count
1898           tze       append_itt_message
1899           cmpx5     count
1900           tpnz      unmake_message      too many for this chan
1901 append_itt_message:
1902 "                                       thread new entry to end of queue
1903           stx1      bb|itt_entry.next_itt_relp,0
1904           tra       0,7
1905 
1906 unmake_message:
1907           lca       1,dl                meter ITTE non-usage
1908           ldx4      bb|itt_entry.origin,1
1909           tnz       um_is_ds
1910           asa       bb|apte.ittes_sent,3
1911 um_is_ds: asa       bp|apte.ittes_got
1912           asa       bb|used_itt
1913           lda       200,dl
1914           sta       errcode             200 means wakeup not sent (itt_ovfl)
1915 
1916           ldac      bb|itt_free_list    give back itt_entry
1917           tnz       *+2                 ok -free list locked
1918           tra       *-2                 loop on itt_free_list lock
1919           eax0      0,au                x0 -> former top free itte
1920 "                                       put that relp in returned itte
1921           stx0      bb|itt_entry.next_itt_relp,1
1922           stx1      bb|itt_free_list
1923           tra       0,7
1924 itt_overflows:
1925           drltra    (pxss: ITT overflows) error condition
1926 " at this point something must be done to decongest the ITT
1927           tra       0,7
1928 "
1929 "Subr called via x6 to set Q to zero if not Iz
1930 "Iz pid must be in A, Iz delta in Q, X3 must -> sender
1931 mm_iz_either:
1932           cmpa      bb|apte.processid,3
1933           tze       0,6
1934 mm_iz_rcvr:
1935           cmpa      bp|apte.processid
1936           tze       0,6
1937           eaq       0
1938           tra       0,6
1939 " ^L
1940 "come here for various functions during initialization
1941 pw1:
1942           eppap     pds$apt_ptr,*
1943           ldac      ap|apte.wait_event  get wait event
1944           sta       tc_data$init_event  save the event
1945 
1946           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+>
1947 pi_wait:
1948           lxl1      prds$processor_tag  get processor tag for masking
1949           lprpab    scs$mask_ptr,1
1950           xec       scs$read_mask,1     find current mask
1951           staq      pds$tc_mask         and save for return
1952           ldaq      scs$open_level      open up mask to await interrupt
1953           xec       scs$set_mask,1
1954 
1955           sprisp    pds$last_sp         save sp because we will change it to non-PRDS
1956           eppsp     null,*
1957 
1958           read_clock
1959           staq      tc_data$init_wait_time        save time of wait
1960 
1961 check_pi_event:
1962           lca       1,dl                for display
1963           ldq       tc_data$init_event
1964           tze       pi_wait_ret         notify has occured
1965 
1966           ldt       =o200,du            about 1/8 second
1967           inhibit   off                 <-><-><-><-><-><-><-><-><->
1968           dis       0
1969           inhibit   on                  <+><+><+><+><+><+><+><+><+>
1970 
1971           szn       tc_data$init_event  0 => event has occurred
1972           tze       pi_wait_ret
1973           read_clock                    " check for notify-time-out
1974           sbaq      tc_data$init_wait_time " aq = time waiting
1975           cmpaq     tc_data$init_wait_timeout  " more than allowed
1976           tmi       check_pi_event      " no -wait some more
1977 
1978 pi_wait_ret:
1979           eppsp     pds$last_sp,*       restore stack pointer
1980           epbpsb    sp|0                ..
1981           ldaq      pds$tc_mask         must be pwait or page_wait
1982           xec       scs$set_mask,1
1983 
1984           szn       tc_data$init_event  did we NTO
1985           tze       pi_wait_ret_con     no--event occurred
1986 
1987 " check for possible disk polling
1988 
1989           szn       pds$pc_call
1990           tmi       pi_wait_no_poll     normal wait
1991 
1992           ldaq      scs$sys_level       mask down for poll sake
1993           xec       scs$set_mask,1
1994 
1995           lxl3      disk_poll_entry     get address of routine to call
1996           call      lp|0,3*(null_arglist) make call to disk poller
1997 
1998           ldaq      pds$tc_mask
1999           xec       scs$set_mask,1
2000 
2001           szn       tc_data$init_event  did we NTO
2002           tze       pi_wait_ret_con     no--event occurred
2003 
2004 pi_wait_no_poll:
2005           szn       tc_data$init_timeout_severity do we want to print NTO message
2006           tmi       pi_nto_no_message   no
2007           szn       tc_data$init_timeout_recurse  are we recursing
2008           tze       pi_call_syserr      no
2009 pi_nto_no_message:
2010           stz       tc_data$init_event  just notify, don't blow the whistle
2011           tra       pi_wait_ret_con
2012 
2013 
2014 "         call      syserr (tc_data$init_timeout_severity, "pxss:  notify time out:  event=^w. During init/shutdown.")
2015 
2016 pi_call_syserr:
2017           aos       tc_data$init_timeout_recurse
2018           push
2019           epplb     pds$last_sp,*
2020           sprilb    pre_temp
2021           lda       pds$pc_call
2022           sta       pre_temp+2
2023           epplb     tc_data$init_timeout_severity
2024           sprilb    arg+2
2025           epplb     pi_timeout_mess
2026           sprilb    arg+4
2027           epplb     tc_data$init_event
2028           sprilb    arg+6
2029           epplb     fixed_desc
2030           sprilb    arg+8
2031           sprilb    arg+12
2032           epplb     pi_timeout_desc
2033           sprilb    arg+10
2034           ldaq      =v18/6,18/4,18/6,18/0
2035           staq      arg
2036           call      syserr$syserr(arg)
2037           epplb     pre_temp,*
2038           sprilb    pds$last_sp
2039           lda       pre_temp+2
2040           sta       pds$pc_call
2041           stz       tc_data$init_event
2042           lca       1,dl
2043           asa       tc_data$init_timeout_recurse
2044           tra       pi_wait_ret_con
2045 
2046 pi_timeout_mess:
2047           aci       "pxss:  notify time out:  event=^w. During init/shutdown."
2048           equ       pi_timeout_mess_words,*-pi_timeout_mess
2049           equ       pi_timeout_mess_char,4*pi_timeout_mess_words
2050 pi_timeout_desc:
2051           vfd       1/1,6/21,5/0,24/pi_timeout_mess_char
2052 "^L
2053 
2054 pi_wait_ret_con:
2055           eppsp     pds$last_sp,*       restore machine state
2056           szn       pds$pc_call         check if pc wait or not
2057           tze       *+2                 don't reset ap for page_fault
2058           eppap     sp|stack_frame.operator_ptr,*
2059           tmi       nwait_ret           normal wait
2060           szn       pds$pc_call         is the a pc call?
2061           tze       page_fault$wait_return no
2062           tra       device_control$pwait_return
2063 
2064 nwait_ret:
2065           rtcd      sp|stack_frame.return_ptr
2066           inhibit   off                 <-><-><-><-><-><-><-><-><-><->
2067 "^L
2068 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2069 "
2070 "         ADDEVENT -- entry to set up event into APT entry prior
2071 "         to a call to wait.
2072 "         There is no need to lock anything.
2073 "         Call is
2074 "                   call pxss$addevent(event)
2075 "
2076 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2077 
2078 addevent:
2079           ldq       ap|2,*              pick up input event
2080           tnz       *+2                 event must be non-zero
2081           ldq       =o707070,dl         so force it so
2082           szn       tc_data$wait_enable during initialization ?
2083           tze       pi_add              yes, special code
2084           eppbp     pds$apt_ptr,*
2085           stq       bp|apte.wait_event  store event in APT entry
2086 short_ret:
2087           short_return
2088 
2089 pi_add:
2090           stq       tc_data$init_event
2091           tra       short_ret
2092 
2093 fixed_desc:
2094           oct       404000000005
2095 
2096 
2097 "^L
2098 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2099 "
2100 "         DELEVENT -- entry to remove interest in event.
2101 "         Call is
2102 "                   call pxss$delevent (event)
2103 "
2104 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2105 
2106 delevent:
2107           szn       tc_data$wait_enable
2108           tze       pi_notify
2109           eaa       0
2110           ldq       ap|2,*              pick up event
2111           eppbp     pds$apt_ptr,*       get ptr to own apte
2112           stacq     bp|apte.wait_event
2113           short_return
2114 " ^L
2115 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2116 "
2117 "         PAGE_WAIT -- special purpose entry to wait for a page.
2118 "
2119 "         This entry is a combination of pxss$addevent and pxss$wait.
2120 "         The argument (wait event) is passed in pds$arg_1.
2121 "         Called by page_fault, returns to page_fault$wait_return to
2122 "         restart a page fault.
2123 "
2124 " " " " " " " " " " " " " " " " " " " " " "" " " " " " " " " "
2125 
2126 page_wait:
2127           stc1      pds$pxss_args_invalid Signal overwriting of temporaries.
2128           stz       pds$pc_call         set flag for page_wait, vs. waitp.
2129           szn       tc_data$wait_enable see if during initialization
2130           tze       pw1                 yes, special code
2131           tsx6      init_pxss_save_stack init x7 save stack
2132 pwait:                                  "COME FROM WAITP
2133           tsx7      update_te           update times
2134 
2135           tsx6      LOCK_bp             -- Wait --
2136           szn       bp|apte.wait_event  wait?
2137           tze       UNLOCK_bp_unpwait   no -event may have occured
2138           ldx0      waiting,du          set state to waiting
2139           tsx7      update_execution_state
2140           tsx6      UNLOCK_bp           page_wait to call getwk
2141           lda       apte.page_wait_flag,du set flag indicating page wait
2142           orsa      bp|apte.flags       set flag ON in APT entry
2143           aos       bb|waits
2144           ldx0      prds$depth          get depth in queue
2145           aos       bb|pfdepth,0        for metering
2146           tsx7      getwork
2147           read_clock                    " meter time ready after notify
2148           sbaq      bp|apte.state_change_time
2149           ldx0      prds$depth          get depth in queue
2150           adx0      prds$depth          multiply depth by 2
2151           aos       bb|readytime,0
2152           asq       bb|readytime+1,0
2153 unpwait:
2154           szn       pds$pc_call         see if page_wait or waitp
2155           tze       page_fault$wait_return page_wait
2156 waitp_return:
2157           eppsp     pds$last_sp,*       restore pds stack history
2158           epbpsb    sp|0                makes dvctl happy
2159           ldaq      prds$+stack_header.stack_begin_ptr reset prds too
2160           staq      prds$+stack_header.stack_end_ptr ..
2161           tra       device_control$pwait_return
2162 
2163 UNLOCK_bp_unpwait:
2164           tsx6      UNLOCK_bp           if not waiting and APTE locked ..
2165           tra       unpwait
2166 "^L
2167 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2168 "
2169 "         PAGE_PAUSE
2170 "
2171 "         This primitive is a combination of pause, which
2172 "         causes the process to delay in ring 0 and page_wait.
2173 "         It is used by page control when it must delay a page operation,
2174 "         usually for defeating a covert channel.
2175 "         This routine returns to page_fault$wait_return when done.
2176 "
2177 "         The time to delay until is in pds$arg_1.
2178 "
2179 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2180 
2181 page_pause:
2182           stc1      pds$pxss_args_invalid         " overwriting temps
2183           stz       pds$pc_call                   " indicates page_wait
2184           szn       tc_data$wait_enable
2185           tze       page_fault$wait_return        " pxss not setup to delay
2186           tsx6      init_pxss_save_stack          " init x7 save stack
2187           eppbp     pds$apt_ptr,*                 " our apte
2188           epbpbb    bp|0                          " tc_data
2189 
2190           tsx6      WRITE_LOCK                    " changing next_ring0_timer
2191           lda       ring0_timer_event
2192           sta       bp|apte.wait_event            " we are waiting for timer
2193           ldaq      pds$arg_1                     " delay time
2194           cmpaq     bb|next_ring0_timer
2195           tpl       *+2                           " timer will expire before our time
2196           staq      bb|next_ring0_timer           " our time comes first
2197           cmpaq     bb|next_alarm_time
2198           tpl       *+2
2199           staq      bb|next_alarm_time            " also update next system alarm
2200           tsx6      UNLOCK                        " done updating
2201           aos       bb|pauses                     " meter
2202           tra       pwait
2203 "^L
2204 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2205 "
2206 "         PAUSE
2207 "
2208 "         This primitive causes the current process to pause in ring 0.
2209 "         It is used when it is necessary to delay an operation,
2210 "         usually for defeating a covert channel.
2211 "
2212 "         call pxss$pause (delay_time);
2213 "
2214 "         The delay_time is the desired wakeup time.  Note, though, that
2215 "         this function may return before this time, so it is necessary
2216 "         for the caller to repeat the call, if necessary.
2217 "
2218 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2219 
2220 pause:    szn       tc_data$wait_enable
2221           tnz       pause.setup
2222           short_return                            " pxss not setup to delay
2223 
2224 pause.setup:
2225           tsx6      setup_
2226           ldaq      ap|2,*                        " desired delay til time
2227           staq      pds$arg_1                     " copy into wired place
2228 
2229           tsplb     setup_check                   " switch stacks & mask
2230           arg       0,6
2231 
2232           tsx6      WRITE_LOCK                    " changing next_ring0_timer
2233           tsx6      LOCK_me_bp                    " rescheduling
2234           lda       ring0_timer_event
2235           sta       bp|apte.wait_event            " we are waiting for timer
2236           ldaq      pds$arg_1                     " delay time
2237           cmpaq     bb|next_ring0_timer
2238           tpl       *+2                           " timer will expire before our time
2239           staq      bb|next_ring0_timer           " our time comes first
2240           cmpaq     bb|next_alarm_time
2241           tpl       *+2
2242           staq      bb|next_alarm_time            " also update next system alarm
2243           aos       bb|pauses                     " meter
2244 
2245           ldx0      waiting,du
2246           tsx7      update_execution_state
2247           tsx6      UNLOCK_bp
2248           tsx7      update_te
2249           tsx6      UNLOCK
2250           tsx7      getwork                       " pause!
2251           tra       switch_back_pds
2252 "^L
2253 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2254 "
2255 "         WAITP -- General purpose entry to wait for a page control event.
2256 "
2257 "         Called by device_control$pwait, we gain control
2258 "         masked              at sys level, wired stack, and event in pds$arg_1
2259 "
2260 "         Control is returned to caller of device_control$pwait.
2261 "
2262 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2263 
2264 waitp:
2265           stc1      pds$pxss_args_invalid Signal overwriting of temporaries.
2266           lda       1,dl
2267           sta       pds$pc_call         set switch for pds return
2268           szn       tc_data$wait_enable see if in initialization
2269           tze       pw1                 yes, do special code
2270           tsplb     setup               switch stacks
2271           tra       pwait
2272 
2273 
2274 "^L
2275 
2276 
2277 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2278 "
2279 "         WAIT -- entry called to wait for a predictably short time.
2280 "         Call is
2281 "                   call pxss$wait
2282 "
2283 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2284 
2285 wait:
2286           szn       tc_data$wait_enable in initialization ?
2287           tze       w1                  yes, special code
2288           tsplb     setup_mask
2289           tsx6      LOCK_me_bp
2290           szn       bp|apte.wait_event  have we been notified yet?
2291           tze       wait_not            yes so return
2292           ldx0      waiting,du          set state to waiting
2293           tsx7      update_execution_state
2294           tsx6      UNLOCK_bp
2295           aos       bb|te_wait
2296           tsx7      update_te           update times
2297           tsx7      getwork
2298 wait_returns:
2299           tra       switch_back_pds     return to pds stack history
2300 
2301 wait_not:
2302           tsx6      UNLOCK_bp
2303           tra       switch_back
2304 
2305 w1:       lca       1,dl                get negative flag
2306           sta       pds$pc_call
2307           tra       pi_wait
2308 " ^L
2309 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2310 "
2311 "         PAGE_NOTIFY -- special porpose entry for notifies on pages
2312 "
2313 "         This entry is like notify except that an extra argument is passed.
2314 "         The extra argument is the device ID of the device whose
2315 "         page transfer has just completed. This is used for latency
2316 "         metering.
2317 "
2318 "         The                 event being notified is passed in pds$arg_1.
2319 "         The                 device ID is passed in pds$arg_2
2320 "
2321 "
2322 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2323 
2324 page_notify:
2325           stc1      dev_signal          flag says special notify
2326 pn2:      stc1      pds$pxss_args_invalid Signal overwriting of temporaries.
2327           szn       tc_data$wait_enable during initialization?
2328           tze       pn1                 yes, special code
2329 
2330           eppbb     tc_data$            set ptr to base of tcdata
2331           tsx6      init_pxss_save_stack init x7 save stack
2332 
2333           aos       bb|page_notifies
2334           tsx6      notify_             go notify
2335 """""     lxl5      x5                  restore x5
2336           tra       notify_return
2337 pn1:
2338           ldq       pds$arg_1           see if we are waiting for the event being notified
2339           cmpq      tc_data$init_event  is it what we're waiting for?
2340           tnz       notify_return       no, return
2341           stz       tc_data$init_event  yes, reset event
2342 notify_return:
2343           tra       page$notify_return
2344 "^L
2345 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2346 "
2347 "         NOTIFY -- entry to notify that an event has happened.
2348 "         Call is
2349 "                   call pxss$notify(event)
2350 "
2351 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2352 
2353 notify:
2354           szn       tc_data$wait_enable in initialization ?
2355           tze       pi_notify           yes, special code
2356           tsx6      setup_
2357           ldq       ap|2,*              pick up event to notify
2358           tnz       *+2                 can't allow zero, so use 707070
2359           ldq       =o707070,dl
2360           stq       pds$arg_1           save in PDS
2361           tsplb     setup_check         switch stacks and lock
2362           arg       0,6
2363           stz       dev_signal          set flag for normal return
2364           aos       bb|notifies
2365 "
2366 "Come here to notify event which is in pds$arg_1
2367 notify_:
2368           stx6      x5                  save index 6 (used by get_processor )
2369           tsx6      READ_LOCK           notify freezes threads
2370           eax2      bb|eligible_q_head  X2 -> eligible_q_head
2371           eax5      0                   USELESS NOTIFY?
2372           ldq       pds$arg_1           Put event in Q-reg and stack
2373           stq       tmp_event
2374 nfy_loop:
2375           ldx2      bb|apte.thread,2    go to next entry
2376           szn       bb|apte.flags,2     stop at sentinel
2377           tmi       nfy_ret
2378           cmpq      bb|apte.wait_event,2 check current APT for same event
2379           tnz       nfy_loop            not equal, skip
2380 "
2381 "         Fall thru here if must notify this process
2382           tsx6      LOCK_x2
2383           lcx0      apte.page_wait_flag+1,du turn off page wait flag
2384           ansx0     bb|apte.flags,2
2385           stz       bb|apte.wait_event,2
2386           eax5      1,5                 USELESS NOTIFY?
2387           lxl0      bb|apte.state,2     make sure dont change running state
2388           cmpx0     waiting,du
2389           tnz       nfy_not_waiting     not waiting, dont change state
2390           ldx0      ready,du            set state to ready
2391           eppbp     bb|0,2              bp must be set for update..
2392           tsx7      update_execution_state
2393           tsx6      UNLOCK_x2
2394           eax7      nfy_restor          set ret addr for get_(idle_)processor
2395           szn       bb|gp_at_notify     see which flavor gp
2396           tze       get_idle_processor
2397           tra       get_processor
2398 nfy_restor:
2399           ldq       tmp_event           Restore event to Q
2400           tra       nfy_loop            continue scan
2401 nfy_not_waiting:
2402           tsx6      UNLOCK_x2
2403           tra       nfy_restor          restor back
2404 nfy_ret:
2405           eax5      0,5                 USELESS NOTIFY?
2406           tnz       *+3                 USELESS NOTIFY?
2407           stq       bb|notify_nobody_event        USELESS NOTIFY?
2408           aos       bb|notify_nobody_count        USELESS NOTIFY?
2409           tsx6      UNLOCK              notify is done
2410           ldx6      x5                  restore x6
2411           szn       dev_signal          check return flag
2412           tnz       0,6                 return to caller
2413           tra       switch_back
2414 
2415 pi_notify:
2416           ldq       ap|2,*              get event
2417           tnz       *+2                 if non-zero, OK
2418           ldq       =o707070,dl         otherwise use special coded event
2419           cmpq      tc_data$init_event
2420           tnz       short_ret           not the right one
2421           stz       tc_data$init_event
2422           short_return
2423 " ^L
2424 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2425 "
2426 "         PTL_WAIT -- wait for  page table lock
2427 "
2428 "         special cased to avoid cluttering up page_wait even further.
2429 "
2430 "         Note that the per APTE lock protects processes interest in
2431 "         ptl_wait_ct.  ptl_wait_ct is >= num of (unlocked) processes in the
2432 "         ptlocking state.  It is greater only temporarily, while
2433 "         some process is making sure a notify is not lost.
2434 "
2435 " " " " " " " " " " " "  " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2436 
2437 ptl_wait:
2438           stc1      pds$pxss_args_invalid
2439           stz       pds$pc_call         set return switch
2440           eppbb     tc_data$
2441           tsx6      init_pxss_save_stack
2442 
2443 ptlw_:    szn       sst$ptl   quick check on ptl
2444           tze       ptlw_ez             not locked - meter and retn
2445           tsx6      LOCK_me_bp
2446           ldx0      ptlocking,du        go ptlocking
2447           tsx7      update_execution_state now I cannot miss notify
2448           aos       sst$ptl_wait_ct guar notify next time ptl unlocked
2449           szn       sst$ptl   see if still locked
2450           tze       ptlw_not            no - dont wait
2451           tsx6      UNLOCK_bp
2452           tsx7      update_te
2453           aos       bb|ptl_waits        meter these
2454           tsx7      getwork
2455 ptlw_ret: szn       pds$pc_call         test return switch
2456           tze       page_fault$ptl_wait_return return to locking code
2457           tra       waitp_return        take fancy return to dvctl trylock
2458 
2459 ptlw_not: lca       1,dl
2460           asa       sst$ptl_wait_ct dont notify on my account
2461           ldx0      running,du          like delevent ..
2462           tsx7      update_execution_state
2463           tsx6      UNLOCK_bp
2464 ptlw_ez:  aos       bb|ptl_not_waits    meter this window
2465           tra       ptlw_ret
2466 
2467 dvctl_retry_ptlwait:
2468           lda       1,dl
2469           sta       pds$pc_call         set return switch
2470           tsplb     setup
2471           tra       ptlw_               join common ptlwait code
2472 
2473 "^L
2474 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2475 "
2476 "         PTL_NOTIFY -- notify one process that ptl is unlocked
2477 "
2478 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2479 
2480 ptl_notify:
2481           stc1      pds$pxss_args_invalid
2482           eppbb     tc_data$
2483           tsx6      init_pxss_save_stack
2484           tsx6      READ_LOCK           ptl_notify freezes threads
2485 
2486           lda       bb|eligible_q_head
2487 ptln_loop:
2488           ldaq      bb|apte.thread,au
2489           tra       ptln_tv,ql*
2490 
2491           arg       ptln_ret            sentinel
2492 ptln_tv:  arg       DRL_empty_apte      empty
2493           arg       ptln_loop           running
2494           arg       ptln_loop           ready
2495           arg       ptln_loop           waiting
2496           arg       DRL_blocked_apte    blocked
2497           arg       DRL_stopped_apte    stopped
2498           arg       ptln_found_ptlocking
2499 
2500 " This is the place where jump indirects through tables come when they feel
2501 " a need to punt. We lose a few hreg entries, but not so many as a arg *,*!
2502 
2503 DRL_empty_apte:
2504           drltra    (pxss: untenable empty APTE)
2505 DRL_blocked_apte:
2506           drltra    (pxss: untenable blocked APTE)
2507 DRL_stopped_apte:
2508           drltra    (pxss: untenable stopped APTE)
2509 
2510 ptln_found_ptlocking:
2511           szn       sst$ptl   is ptl actually unlocked now?
2512           tnz       ptln_ret            no - abort ptln
2513 
2514           lxl2      bb|apte.thread,au   make X2 -> ptlocking process
2515           tsx6      LOCK_x2             ptln locks to test and set state
2516           lxl0      bb|apte.state,2
2517           cmpx0     ptlocking,du
2518           tnz       ptln_not_ptlocking
2519 
2520           lca       1,dl
2521           asa       sst$ptl_wait_ct one fewer waiting for ptl
2522           eppbp     bb|0,2              set bp for ues
2523           ldx0      ready,du
2524           tsx7      update_execution_state
2525           tsx6      UNLOCK_x2
2526 
2527           eax7      ptln_ret            set ret addr for get_(idle_)processor
2528           szn       bb|gp_at_ptlnotify  see which flavor gp
2529           tze       get_idle_processor
2530           tra       get_processor
2531 
2532 ptln_ret: tsx6      UNLOCK
2533 """""     lxl5      x5                  ??????
2534           tra       core_queue_man$ptl_notify_return
2535 
2536 ptln_not_ptlocking:
2537           tsx6      UNLOCK_x2
2538           tra       ptln_loop
2539 
2540 "^L
2541 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2542 "
2543 "         UPDATE_TE -- procedure to update the virtual cpu time used by
2544 "         the running process into "te".
2545 "
2546 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2547 
2548 update_te:
2549           eppbp     pds$apt_ptr,*       get own apt pointer
2550           epbpbb    bp|0                set bb to point at base of tc_data
2551           szn       pds$vtime_count
2552           tpl       te_vtime_1
2553           read_clock
2554           sbaq      pds$cpu_time
2555           tra       te_vtime_2
2556 te_vtime_1:
2557           ldaq      pds$time_v_temp
2558 te_vtime_2:
2559           sbaq      pds$virtual_delta
2560           sbaq      pds$virtual_time_at_eligibility
2561           stq       bp|apte.te
2562           tra       0,7
2563 
2564 
2565 
2566 " ^L
2567 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2568 "
2569 "         USAGE_VALUES  -- procedure to return the total page faults
2570 "         for this process as well as the total cpu time this process
2571 "         has been charged with.
2572 "
2573 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2574 
2575 usage_values:
2576           szn       tc_data$wait_enable see if during initialization
2577           tze       ret_zero            if so return zeros
2578           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+><+><+><+><+><+><+>
2579           read_clock
2580           sbaq      pds$cpu_time        compute virtual time
2581           sbaq      pds$virtual_delta   convert to virtual cpu time
2582           staq      ap|4,*              return value
2583           ldq       pds$page_waits      also return page waits
2584           stq       ap|2,*              return value
2585           short_return
2586           inhibit   off                 <-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><->
2587 
2588 ret_zero:
2589           fld       0,dl                zero a-q
2590           staq      ap|4,*              return time of zero
2591           stz       ap|2,*              return zero page_waits
2592           short_return
2593 "^L
2594 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2595 "
2596 "         SORT_IN -- procedure to sort a process into the ready list at
2597 "         the appropriate spot depending on his updated ti value.
2598 "         bp must point to the APT entry for the process to be sorted
2599 "         in.
2600 "
2601 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2602 
2603 sort_in_before:
2604           stc1      before              here to sort in before those of same ti
2605           tra       *+2
2606 sort_in:
2607           stz       before
2608           aos       bb|schedulings
2609           ldx0      apte.interaction,du check interaction switch
2610           canx0     bp|apte.flags
2611           tze       sort_no_int         no interaction
2612           tsx0      setup_int           boost priority
2613           lcx0      apte.interaction+1,du
2614           ansx0     bp|apte.flags       turn off interaction bit
2615 
2616 sort_no_int:
2617           lda       bp|apte.ti
2618           cmpa      bp|apte.timax       must always be less than timax
2619           tmi       *+2                 ok, use new value
2620           lda       bp|apte.timax       must use max value
2621           sta       bp|apte.ti
2622 
2623           ldx0      bp|apte.flags
2624           canx0     apte.realtime_burst,du realtime boost
2625           tze       sort_in_again       no
2626           tsx0      setup_io_realtime   yes
2627           tra       realtime_sort
2628 sort_in_again:
2629 "old_assume_bp_not_eligible
2630 "old_assume_bp_wct_index
2631           ldx1      bp|apte.wct_index   here to put in right rdy_q
2632           szn       bb|wcte.realtime,1  if realtime
2633           tnz       realtime_sort       sort into realtime_q
2634           szn       bb|deadline_mode    else if not percenting
2635           tnz       virtual_sort        then put in interactive_q
2636           lda       bb|wcte.interactive_q_word,1  See if interactive queue is
2637           cana      wcte.interactive_q,du           enabled for this WC
2638           tze       ti_loop             Not enabled
2639 "
2640 "         here to sort into workclass or interactive queue by ti
2641 ti_sort:  ldx4      bp|apte.ti          put ti in X4 for sort
2642           tnz       ti_loop             sort into X1 -> wc_q
2643           szn       bp|apte.ts          also if ts not zero
2644           tnz       ti_loop             sort into X1 -> wc_q
2645           szn       bb|int_q_enabled    also if int_q turned off
2646           tze       ti_loop             sort into X1 -> wc_q
2647           eax1      bb|interactive_q    else direct to tail of int_q
2648           tra       thread_him_in
2649 ti_loop:
2650           ldx1      bb|apte.thread,1    chase to next
2651           szn       bb|apte.sentinel,1  put before sentinel
2652           tmi       thread_him_in
2653           cmpx4     bb|apte.ti,1        compare to this ti
2654           tpnz      ti_loop             if greater, go deeper
2655           tmi       thread_him_in       if less, put before
2656           szn       before              if equal and told to put before
2657           tnz       thread_him_in       then put before
2658           tra       ti_loop             else go deeper
2659 "
2660 "         various deadline sorts follow
2661 realtime_sort:
2662           ldx0      apte.realtime_burst,du  mark as realtime
2663           orsx0     bp|apte.flags
2664           eax1      bb|realtime_q       here to put in realtime_q
2665           tra       deadline_sort
2666 virtual_sort:
2667           eax1      bb|interactive_q    int_q has vir deadlines
2668 deadline_sort:
2669           ldaq      bp|apte.deadline    here for general deadline sort
2670 ds_loop:
2671           ldx1      bb|apte.thread,1    chase to next
2672           szn       bb|apte.sentinel,1  put before sentinel
2673           tmi       thread_him_in
2674           cmpaq     bb|apte.deadline,1  compare to this deadline
2675           tpl       ds_loop             sooner => fall thru to thread before
2676 "
2677 "Subroutine to thread unthreaded APTE at bp|0 before that at bb|0,1.
2678 "
2679 thread_him_in:
2680           szn       tc_data$apt_lock    ASSUME write_locked
2681           drlmi     (pxss: APT not locked) ASSUME write_locked
2682           szn       bp|apte.thread      ASSUME bp_unthreaded
2683           drlnz     (pxss: thread_him_in already threaded) ASSUME bp_unthreaded
2684           eax1      0,1                 ASSUME x1_nonzero
2685           drlze     (pxss: thread_him_in x1 zero) ASSUME x1_nonzero
2686           lxl4      bb|apte.thread,1    thread new entry in here
2687           drlze     (pxss: thread_him_in x4 zero) ASSUME x4_nonzero
2688           cmpx1     bb|apte.thread,4    ASSUME x4->apte.fp = x1
2689           drlnz     (pxss: thread_him_in x4->apte.fp ^= x1) ASSUME x4->apte.fp = x1
2690           lxl0      bp|apte.state
2691           cmpx0     ready,du            ASSUME apte.state = "ready"
2692           drlnz     (pxss: apte.state ^= ready)
2693           eax0      bp|0
2694           drlze     (pxss: thread_him_in x0 zero) ASSUME x0_nonzero
2695           sxl0      bb|apte.thread,1
2696           stx0      bb|apte.thread,4
2697           sxl4      bp|apte.thread
2698           stx1      bp|apte.thread
2699           tra       0,7
2700 " ^L
2701 " " " " " " " " " " " " " " " " " " " " " " " " " " "
2702 "
2703 "         THREAD_IN_IDLE -- entry to thread an idle process into the
2704 "         ready list.  Called during initialization and reconfiguration.
2705 "
2706 "         call pxss$thread_in_idle(apt_ptr)
2707 "
2708 "         Where:
2709 "
2710 "                   apt_ptr   is an its pointer to an idle process apt entry
2711 "
2712 " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2713 
2714 thread_in_idle:
2715           tsx6      setup_
2716           ldaq      ap|2,*              save apt_ptr in PDS
2717           staq      pds$arg_1
2718           tsplb     setup_check         switch stacks and lock
2719           arg       0,6
2720           tsx6      WRITE_LOCK          thread_in_idle rethreads
2721           eppbp     pds$arg_1,*         get pointer to APT entry
2722           tsx7      unthread            thread entry out of any list it's in
2723           ldx1      bb|eligible_q_tail
2724           tsx7      thread_him_in       thread into list
2725           tsx6      UNLOCK              thread_in_idle is done
2726           tra       switch_back
2727 "^L
2728 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2729 "
2730 "         UNTHREAD_APTE -- entry to unthread an APTE from whatever
2731 "         queue it's in.  Called by stop_cpu during reconfiguration.
2732 "
2733 "         call pxss$unthread_apte (apt_ptr)
2734 "
2735 "         Where:
2736 "                   apt_ptr   is a pointer to the APTE to be unthreaded.
2737 "
2738 "
2739 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2740 
2741 unthread_apte:
2742           tsx6      setup_
2743           ldaq      ap|2,*
2744           staq      pds$arg_1
2745           tsplb     setup_check
2746           arg       0,6
2747           tsx6      WRITE_LOCK          pxss$unthread_apte
2748 
2749           eppbp     pds$arg_1,*
2750           tsx7      unthread
2751           tsx6      UNLOCK              pxss$unthread_apte
2752           tra       switch_back
2753 "^L
2754 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2755 "
2756 "         GET_PROCESSOR -- procedure to award a processor (via
2757 "         pre_emption of a lower priority process).
2758 "         First check idle processes, then check eligible processes starting
2759 "         with lowest priority eligible process).
2760 "
2761 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2762 "
2763 "         GET_IDLE_PROCESSOR -- procedure to award a processor via
2764 "         pre-emption of an idle process.  This procedure should be
2765 "         called instead of get_processor when the process for whom we
2766 "         are pre-empting may not even be eligible yet.
2767 "
2768 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2769 
2770 get_idle_processor:
2771           eax0      1                   just check idle processes
2772           ldx3      bb|apte.wct_index,2 fall thru to full gp if realtime
2773           szn       bb|wcte.realtime,3
2774           tze       gp_init             go check idle queue
2775 get_processor:
2776           eax0      2                   check both idle and elig queues
2777 
2778 gp_init:  lda       bb|apte.thread,2    pre-empting on behalf of X2
2779           sta       temp                save (unique) threads for compares
2780 
2781           lda       bb|apte.procs_required,2      get procs_required for process being pre-empted
2782           ana       apte.procs_required_mask,du   mask out all but required processors
2783           sta       temp_procs_required           and save in our stack
2784 
2785           lda       bb|idle_tail        start with idle processes
2786           aos       bb|gp_start_count   For getwork/get_processor window
2787 "
2788 "All set up.  Now for the main loop.  It will be executed over the
2789 "Idle processes first.  If no Idle process is running then if the
2790 "XR0 is > 1 (ie: came in at get_processor entry,
2791 "not get_idle_processor) then the loop will be executed over the
2792 "elig processes.
2793 "
2794 gp_loop:  ldaq      bb|apte.thread,al   go higher in queue
2795           cmpa      temp                is this process which was notified?
2796           tnz       gp_tv,ql*           no - branch on state
2797           tra       gp_return           yes - give up and return
2798 
2799           arg       check_eligible      -1 => sentinel
2800 gp_tv:    arg       gp_loop             gp found empty (ok-may be idle)
2801           arg       gp_found_running
2802           arg       gp_loop             gp found ready
2803           arg       gp_loop             gp found waiting
2804           arg       DRL_blocked_apte    gp found blocked
2805           arg       DRL_stopped_apte    gp found stopped
2806           arg       gp_loop             gp found ptlocking
2807 
2808 gp_found_running:
2809           lxl3      bb|apte.thread,au   extract addr from next's backptr
2810           tsx6      LOCK_x3             gp locks
2811           ldq       bb|apte.flags,3     grab fresh copy of flags
2812           canq      apte.pre_empted,du  have we pre-empted it before?
2813           tnz       gp_skip             yes, skip it
2814 
2815           ldq       bb|apte.flags2,3    get processor tag
2816           anq       apte.pr_tag_mask,dl
2817           orq       =o400000,du         convert processor tag to bit position
2818           qrl       0,ql
2819           anq       temp_procs_required is prempting process allowed to use this cpu?
2820           tze       gp_skip             no, skip
2821 
2822           lda       apte.pre_empted+apte.pre_empt_pending,du turn on pre_empted bit
2823           orsa      bb|apte.flags,3
2824           ldq       bb|apte.flags2,3    get processor tag
2825           anq       apte.pr_tag_mask,dl
2826           cmpq      prds$processor_tag  this cpu?
2827           tze       gp_this_cpu         dont cioc if so
2828           cioc      scs$cow_ptrs,ql*
2829           tsx6      UNLOCK_x3           gp unlocks
2830           tra       gp_return
2831 
2832 gp_this_cpu:
2833           tsx6      UNLOCK_x3           gp unlocks
2834           lda       1,dl                set alarm to r1
2835           sta       pds$alarm_ring
2836           lra       pds$alarm_ring
2837           tra       gp_return
2838 
2839 gp_skip:  tsx6      UNLOCK_x3
2840           tra       gp_loop             have not clobbered AL ( -> next)
2841 
2842 check_eligible:
2843           eax0      -1,0                need check the eligibles?
2844           tze       gp_return           no - return to caller
2845 
2846           lda       bb|eligible_q_tail  now check eligibles
2847           tra       gp_loop
2848 gp_return:
2849           aos       bb|gp_done_count    For getwork/get_processor window
2850           tra       0,7                 gp ret to caller
2851 " ^L
2852 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2853 "
2854 "         FIND_NEXT_ELIGIBLE -- the policy implementing part of the
2855 "         scheduler.  This code could be in-line in getwork but is
2856 "         separated for clarity. It is entered at find_next_eligible
2857 "         from getwork if no eligible process can be run.  It is entered
2858 "         with the traffic controller locked for multiple readers but
2859 "         must run with the exclusive lock allowing rethreading and awarding
2860 "         eligibility.  It will return to getwork with x2 -> newly elig
2861 "         or will return to find idle. In either case before returning
2862 "         the lock will be changed to allow concurrency.
2863 "         This code will also be entered at AWARD with the write lock set,
2864 "         from the part of getwork that decides to award eligibility
2865 "         to process with realtime deadlines which are past.
2866 
2867 "
2868 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2869 find_next_eligible:
2870           tsx6      UNLOCK              fne must unlock read before write
2871           tsx6      WRITE_LOCK          fne rethreads, awards elig
2872 "
2873 "If there are any processes which have just interacted,
2874 "we must run them immediately.  So check the interactive_queue.
2875 "If we are in deadline mode the interactive queue contains most processes
2876 "and also some special conditions must be fulfilled.
2877 "
2878 
2879           stz       depth
2880           eax2      bb|interactive_q
2881           stz       temp2               no work class restrictions so far
2882 lr_loop:
2883           ldx2      bb|apte.thread,2    step to next process.
2884           szn       bb|apte.sentinel,2  If none then scan wc queues.
2885           tmi       lr_wcq              Look in workclass queues
2886           szn       bb|deadline_mode    If deadline mode make checks.
2887           tze       test_award          Else return this X2 to getwork.
2888 
2889           ldx1      bb|apte.wct_index,2 Check if limit on n elig
2890           ldq       bb|wcte.maxel,1
2891           tze       lr_e_ok             OK if no limit.
2892           cmpq      bb|wcte.nel,1       Else compare to limit.
2893           tpnz      lr_e_ok             Below limit.
2894           stc1      temp2               Flag work class restriction
2895           tra       lr_loop             And go deeped
2896 lr_e_ok:
2897           lda       bb|max_batch_elig   Limit on batch?
2898           tze       test_award          No.
2899           lxl1      bb|apte.flags2,2    Yes.
2900           canx1     apte.batch,du       Is this process batch?
2901           tze       test_award          No, limit doesn't matter.
2902           cmpa      bb|num_batch_elig   Yes, check limit.
2903           tpnz      test_award          OK, within limit.
2904           stc1      temp2               Flag work class restriction
2905           tra       lr_loop             Go deeper.
2906 
2907 lr_wcq:
2908 "
2909 "Nobody found in interactive/virtual_deadline queue.  We must
2910 "update the credits in each workclass before scanning the workclass queues.
2911 "
2912           szn       bb|deadline_mode
2913           tze       sc_loop             not dmode => scatter credits
2914           stz       bb|credit_bank      clear cell prvents ovfl
2915           tra       sc_done
2916 
2917 sc_loop:
2918           lda       bb|credit_bank      Are there credits to scatter?
2919           tmi       sc_done             No.
2920           stz       bb|credits_scattered None scattered yet.
2921           ldq       bb|telast           Credits always < 4*telast
2922           qls       2
2923           ldx1      bb|min_wct_index    Start at first work class.
2924 
2925 sc_wc_loop:
2926           szn       bb|wcte.realtime,1  Is this wc getting some percent?
2927           tnz       sc_check            No, go to next wc. after clipping
2928           lda       bb|wcte.minf,1      Yes, give credits.
2929           asa       bb|wcte.credits,1
2930           asa       bb|credits_scattered Note we scattered some.
2931 sc_check:
2932           szn       bb|wcte.credits,1   don't let credits go negative
2933           tpl       *+2
2934           stz       bb|wcte.credits,1
2935           cmpq      bb|wcte.credits,1   Make sure credits < 4*telast
2936           tpl       sc_next             OK.
2937           stq       bb|wcte.credits,1   CREDIT SINK
2938 sc_next:
2939           eax1      size_of_wct_entry,1 Move to next work class.
2940           cmpx1     bb|max_wct_index    Done all?
2941           tmoz      sc_wc_loop          more wc to do.
2942 
2943           lca       bb|credits_scattered Did we scatter any?
2944           tze       sc_done             No. Don't loop back!
2945           asa       bb|credit_bank      Yes. Bookkeep and
2946           tra       sc_loop             loop back to scatter more.
2947 sc_done:
2948 
2949 "
2950 "         Now scan the workclass queues to find the most worthy workclass
2951 "         which has a non-empty queue.  In this process, governing credits
2952 "         are distributed to governed work classes.  Any governed work
2953 "         class whose governing credits are negative will not be
2954 "         considered for eligibility.
2955 "
2956 
2957           ldx2      -1,du               Preset to none-found.
2958           ldx1      bb|min_wct_index    Start at first work class.
2959           lda       =o400000,du         Anybody can beat this.
2960           sta       bb|best_credit_value
2961 
2962           eax0      -1                  preset to do-not-pass-out-gv-credits
2963           szn       bb|governing_credit_bank
2964           tmi       fne_loop            none to pass out
2965           lda       bb|governing_credit_bank      pass out, decrementing bank
2966           sba       bb|credits_per_scatter
2967           ars       1                             allow to grow to 2*credits_per_scatter
2968           cmpa      bb|credits_per_scatter        limit growth in the bank
2969           tmoz      *+2
2970           lda       bb|credits_per_scatter        (must be S&L)
2971           als       1
2972           sta       bb|governing_credit_bank
2973           eax0      0                   pass-out-gv-credits
2974 
2975 fne_loop:
2976           lda       bb|wcte.governed_word,1       is this W.C. governed
2977           cana      wcte.governed,du
2978           tze       fne_not_governed    No
2979           eax0      0,0                 governing credits to pass out
2980           tmi       fne_no_gv_credits   no
2981           lda       bb|wcte.maxf,1      credits for this W.C. per scatter
2982           asa       bb|wcte.governing_credits,1
2983 fne_no_gv_credits:
2984           lda       bb|gv_integration   limit of abs value of gv credits
2985           cmpa      bb|wcte.governing_credits,1
2986           tpl       *+2
2987           sta       bb|wcte.governing_credits,1
2988           szn       bb|wcte.governing_credits,1   is this W.C. in the hole?
2989           tpl       fne_not_governed    no - can consider for eligibility
2990           neg       0                   areg = -limit ov abs value of gv credits
2991           cmpa      bb|wcte.governing_credits,1   there's a limit on the hole
2992           tmi       *+2                 negative but not bankrupt
2993           sta       bb|wcte.governing_credits,1   minimum value
2994           cmpx1     bb|wcte.thread,1    Th to self => none ready
2995           tze       fne_try_next
2996           stc1      temp2               flag work class restriction
2997           tra       fne_try_next
2998 
2999 fne_not_governed:
3000           cmpx1     bb|wcte.thread,1    Th to self => none rdy.
3001           tze       fne_try_next
3002           szn       bb|wcte.credits,1   Credits never left negative
3003           tpl       *+2
3004           stz       bb|wcte.credits,1   CREDIT SOURCE
3005 
3006           ldx3      bb|wcte.thread,1
3007           lca       bb|telast           maximize credits - min (ti, 2*telast)
3008           als       1
3009           cmg       bb|apte.ti,3        deal with abs values
3010           tmi       *+2
3011           lca       bb|apte.ti,3
3012 
3013           ada       bb|wcte.credits,1
3014           cmpa      bb|best_credit_value See if this is best sofar.
3015           tmi       fne_try_next        Wasn't, move to next.
3016 
3017           sta       bb|best_credit_value Was, remember value.
3018           eax2      0,3                 remember the champ
3019 
3020 fne_try_next:
3021           eax1      size_of_wct_entry,1 Move to next work class.
3022           cmpx1     bb|max_wct_index    If any.
3023           tmoz      fne_loop
3024           eax2      0,2                 Neg=> nobody
3025           tpl       test_award          See if process fits in core.
3026           tra       recheck_real        Continue looking for candidate.
3027 
3028 "
3029 "Come here if no processes found in int/vird queue or in
3030 "the workclass queues.  We determine whether any process is present in the
3031 "realtime queue.  If so such a process will be awarded eligibility subject
3032 "to the usual constraints even though its deadline has not
3033 "arrived yet.
3034 "
3035 recheck_real:
3036           ldx2      bb|realtime_q       REALTIME AWARD?
3037           szn       bb|apte.sentinel,2
3038           tmi       fne_fail
3039 "
3040 "Arrive here with x2 pointing at a candidate for eligibility.
3041 "A few more checks are made to determine if eligibility will
3042 "actually be awarded.
3043 "
3044 test_award:
3045           lda       bb|apte.flags,2
3046           cana      apte.dbr_loaded,du
3047           tze       *+3                 dbr not loaded ok to award elig
3048           cmpx2     pds$apt_ptr+1
3049           tnz       fne_fail            dbr loaded ok only if this cpu
3050 
3051           lxl0      bb|n_eligible       get number of eligible processes
3052           cmpx0     bb|min_eligible     Below min eligible?
3053           tmi       award               Yes, make eligible.
3054           cmpx0     bb|max_eligible     At max eligible?
3055           tpl       fne_fail            Yes, go idle.
3056           cmpx0     bb|max_max_eligible
3057           tpl       fne_fail
3058           ldq       bb|ws_sum           See if it fits.
3059           adq       bb|apte.ws_size,2
3060           cmpq      sst$nused
3061           tpl       fne_fail            no, go idle.
3062 "
3063 "Here to award eligibility to x2-> apte.  Arrive here
3064 "either by falling through above code or directly from getwork
3065 "if a process 's realtime deadline has arrived.
3066 "
3067 award:
3068           aos       bb|n_eligible       increment count of eligible s
3069           lxl1      bb|apte.flags2,2    DIGS
3070           canx1     apte.batch,du
3071           tze       *+2
3072           aos       bb|num_batch_elig
3073           ldx1      bb|apte.wct_index,2
3074           aos       bb|wcte.nel,1       and per wc count
3075           ldx0      apte.eligible,du
3076           ersx0     bb|apte.flags,2
3077           ldq       bb|apte.ws_size,2   ws_sum = ws_sum + ws_size,2
3078           anq       -1,dl               Leave only ws estimate
3079           asq       bb|ws_sum
3080 "
3081 "put the newly elig process in the proper place in elig queue
3082 "note bp is fudged for sort subr's, then reset
3083 "
3084           eppbp     bb|0,2              Set bp to process of interest
3085           tsx7      unthread            Remove from ready queue
3086           eax1      bb|eligible_q_tail  Assume put at eltail.
3087 
3088           ldx0      bb|apte.flags,2
3089           canx0     apte.realtime_burst,du  Normal process?
3090           tze       put_in_el_q         Yes, put at tail of el queue.
3091           lcx0      apte.realtime_burst+1,du Reset flag
3092           ansx0     bb|apte.flags,2
3093 
3094           ldx1      bb|eligible_q_head  Could sort by deadline here
3095           stz       depth               Reset depth.
3096 put_in_el_q:
3097           tsx7      thread_him_in
3098           ldq       AWARD_ELIGIBILITY,dl
3099           tsx7      meter_response_time$tc        response transition
3100           eppbp     pds$apt_ptr,*       Restore bp -> old_user
3101           tsx6      LOCK_x2             Claim this apte now
3102           tsx6      WRITE_TO_READ       shift lock to read before return
3103 
3104           ldx1      bb|apte.wct_index,2 Determine work class.
3105           lda       bb|apte.temax,2     Decrement wc credits in advance
3106           tnz       *+2
3107           lda       bb|process_initial_quantum    Must be first time thru
3108           sta       bb|apte.saved_temax,2         Save to compensate later
3109           neg
3110           asa       bb|wcte.credits,1
3111           ldq       bb|wcte.governed_word,1       Is wc governed
3112           canq      wcte.governed,du
3113           tze       *+2                 No
3114           asa       bb|wcte.governing_credits,1
3115           aos       bb|wcte.eligibilities,1 Meter elig awarded.
3116 
3117           ldq       bb|apte.ts,2        see if first time since wakeup
3118           adq       bb|apte.ti,2        continue with check ...
3119           tnz       no_response         non-zero means not first time
3120           read_clock                    " meter response time
3121           sbaq      bb|apte.state_change_time,2 get time this process was ready
3122           adaq      bb|response_time    add in to total meter
3123           staq      bb|response_time
3124           aos       bb|response_count   count number of times we added in
3125 no_response:
3126           tra       gw_ck_suspend       Success return from fne
3127 
3128 fne_fail:
3129           tsx6      WRITE_TO_READ
3130           tra       find_idle           Failure return from fne
3131 
3132 
3133 "^L
3134 " " " " " " " " " " " " " " " " " " " "  " " " " " " " " " " " " " " "
3135 "
3136 "         GETWORK -- procedure which is invoked when the running
3137 "         process is ready to give the processor to another process.
3138 "         When it is invoked bb->bp must point into tc_data.
3139 "
3140 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
3141 
3142 getwork:
3143           stc1      pds$pxss_args_invalid Signal overwriting of temporaries.
3144           stz       pds$post_purged     reset flag indicating purge is done
3145           read_clock                    " meter getwork time
3146           staq      getwork_temp        save for user being switched to
3147           sxl7      bp|apte.savex7      save x7 in APT entry
3148           aos       bb|depth_count
3149           lcx0      apte.pre_empted+apte.pre_empt_pending+1,du turn off pre-empted flags
3150           ansx0     bp|apte.flags
3151 
3152 gw_retry:
3153 "
3154 "         The following code, checked each time through the traffic controller, checks to see
3155 "         if the running processor is to be deleted. If so, it branches to the
3156 "         appropriate code which ultimately DISes.
3157 "         1. Force idle process to run on this cpu.
3158 "         2. Rather than returning from getwork, transfer to DIS-ing code.
3159 "
3160           lxl1      prds$processor_tag  get our own processor tag
3161           lda       scs$processor_data,1 get our control word from SCS
3162           cana      processor_data.delete_cpu,du
3163           tnz       find_idle_for_delete
3164 "
3165 "         End of reconfiguration tests
3166 "
3167           read_clock                    " get time in AQ for several tests
3168 
3169           cmpaq     bb|next_alarm_time  go boost priority if time
3170           tpl       alarm_timer         ..
3171 
3172           cmpaq     bb|nto_check_time   go check notify_timeouts if time
3173           tpl       nto_check
3174 
3175           ldx2      bb|realtime_q       maybe realtime award?
3176           szn       bb|apte.sentinel,2
3177           tmi       gw_lock_init_loop   nobody
3178           cmpaq     bb|apte.deadline,2
3179           tmi       gw_lock_init_loop   Not yet
3180 
3181           tsx6      WRITE_LOCK          probable realtime award
3182           lxl0      bb|n_eligible
3183           cmpx0     bb|max_max_eligible
3184           tpl       no_real
3185           ldx2      bb|realtime_q       REALTIME AWARD?
3186           szn       bb|apte.sentinel,2
3187           tmi       no_real
3188           read_clock
3189           cmpaq     bb|apte.deadline,2
3190           tmi       no_real             Delay him for now.
3191 
3192           lda       bb|apte.flags,2
3193           cana      apte.dbr_loaded,du
3194           tze       award               dbr not loaded ok to award elig
3195           cmpx2     pds$apt_ptr+1
3196           tze       award               dbr loaded ok only if this cpu
3197 no_real:
3198           tsx6      WRITE_TO_READ       cant make realtime elig so shift to readlock
3199           tra       gw_init_loop
3200 
3201 gw_lock_init_loop:
3202           tsx6      READ_LOCK
3203 gw_init_loop:
3204           lda       bb|gp_done_count    If gp occur we must not idle
3205           sta       temp1               So we remember the count
3206           lda       bb|eligible_q_head  ELIGIBLE to RUN?
3207           ldx1      -1,du               keep depth in X1
3208 
3209 gw_loop:
3210           ldaq      bb|apte.thread,au   go to next entry via AU
3211           eax1      1,1                 increase depth
3212           tra       gw_tv,ql*           dispatch on state in QL
3213 
3214           arg       find_next_eligible  state was -1 ie sentinel
3215 gw_tv:    arg       DRL_empty_apte      found empty
3216           arg       gw_loop             state was running so go deeper
3217           arg       gw_found_ready
3218           arg       gw_loop             state was waiting so go deeper
3219           arg       DRL_blocked_apte    found blocked
3220           arg       DRL_stopped_apte    found stopped
3221           arg       gw_loop             found ptlocking
3222 
3223 
3224 
3225 gw_found_ready:
3226           ldx2      bb|apte.thread,al   extract ready's addr from prev's fp
3227           tsx6      LOCK_x2             gw must make sure x2 is ready etc
3228           sxl1      depth               remember depth
3229 gw_ck_suspend:
3230           lda       bb|tc_suspend_lock  see if someone wants exclusive use of the system
3231           tze       gw_ck_ready         no one does, so bypass the following checks
3232           cmpa      bb|apte.processid,2 is it I that wants the system?
3233           tze       gw_ck_ready         if so, then I get to run.
3234           lda       bb|apte.flags,2     otherwise,
3235           cana      apte.idle,du        is this an idle process?
3236           tze       gw_cant_run         well, if it's not, then it can't be run
3237 gw_ck_ready:
3238           lda       bb|apte.flags,2     pick up flags&state from locked apte
3239           eax0      0,al                put state in X0
3240           cmpx0     ready,du            really ready?
3241           tnz       gw_cant_run         not really ready
3242           cana      apte.dbr_loaded,du  Is dbr_loaded?
3243           tze       gw_dbr_ok           no - ok to run
3244           cmpx2     pds$apt_ptr+1       yes - Is this self?
3245           tnz       gw_cant_run_dbrl    not self - must not touch
3246 gw_dbr_ok:
3247           cana      apte.loaded,du      is this process loaded?
3248           tze       load_him            no, load the process
3249 
3250           lda       bb|apte.procs_required,2      see whether this process
3251           ana       apte.procs_required_mask,du   can run on this CPU
3252           ana       prds$processor_pattern
3253           tnz       gw_can_run                    OK to run
3254 
3255 gw_cant_run:
3256           tsx6      UNLOCK_x2           unlock the apte
3257           lda       bb|apte.thread,2    repair AU
3258           tra       gw_loop             go loop to next
3259 gw_cant_run_dbrl:
3260           lca       1,dl                force gw retry if we idle
3261           asa       temp1               by spoiling gw_gp_window test
3262           tra       gw_cant_run
3263 
3264 gw_can_run:
3265 "
3266 "We have decided to run this process, but will retry getwork if this
3267 "process is idle and if there has been a get_processor in progress while
3268 "we were chasing down the eligible queue. Strictly speaking, we should retry
3269 "even if the found process is not idle -- but who cares.  Strictly speaking
3270 "we need not retry (cannot lose a get_processor) unless BOTH a process has
3271 "been readied AND a get_processor has been in progress DURING this getwork.
3272 "
3273           eppbp     bb|0,2              processor addevent!
3274           ldx0      running,du          mark as running
3275           tsx7      update_execution_state
3276 
3277           lda       bb|gp_start_count
3278           ssa       temp1               temp1 is nonzero if done(t0) ^= start(t1)
3279 
3280 gw_can_really_run:
3281           tsx7      compute_virtual_clocks
3282           tsx7      set_newt            calculate the time to run
3283           lxl0      depth               set depth meter
3284           cmpx0     max_depth-1,du      depth can't be bigger than max
3285           tmi       *+2
3286           ldx0      max_depth-1,du
3287           stx0      prds$depth
3288           eppap     pds$apt_ptr,*       get pointer to own APT entry
3289           stz       pds$number_of_pages_in_use
3290           spriap    apt_ptr             save pointer to last user to run
3291           eppbp     bb|0,2              make bp -> our APTE
3292 
3293 " " " " " " " " " " " " " " " " " " " " "
3294 "                                       "
3295 "   P R O C E S S   S W I T C H I N G   "
3296 "                                       "
3297 "        D O N E    H E R E             "
3298 "                                       "
3299 " " " " " " " " " " " " " " " " " " " " "
3300           ldx0      lp|prds_link        pick up segno of prds
3301           adlx0     lp|prds_link        multiply by two (add it in again)
3302           sbar      pds$base_addr_reg   save base address reg for process
3303           ldt       prds$last_timer_setting and load with new value
3304           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+><+>
3305           ldaq      dseg$+0,0           pick up prds SDW address
3306           ldbr      bp|apte.dbr         load the dbr
3307           staq      dseg$+0,0           store prds SDW in new DSEG
3308 
3309           spribp    prds$apt_ptr        mark process running this cpu
3310           lda       prds$processor_tag  set proc tag for
3311           era       bp|apte.flags2
3312           ana       apte.pr_tag_mask,dl
3313           tze       *+2
3314           cams      4                   clear cache if different cpu
3315           ersa      bp|apte.flags2
3316           eppab     prds$mode_reg_enabled
3317           lca       mr.enable_hfp+1,dl  is hex fp enabled for this process?
3318           ana       prds$mode_reg
3319           szn       pds$hfp_exponent_enabled
3320           tze       *+2
3321           ora       mr.enable_hfp,dl
3322           sta       prds$mode_reg
3323           ora       mr.enable_mr+mr.enable_hist,dl  enable mode reg and enable hist regs
3324           sta       ab|0
3325           lcpr      ab|0,04
3326           inhibit   off                 <-><-><-><-><-><-><-><-><-><-><-><->
3327 
3328           lda       ap|apte.flags       OLD USER TO BE UNLOADED?
3329           cana      apte.eligible+apte.always_loaded,du Loadedness protected?
3330           tnz       dont_unload         yes - skip unload
3331           cana      apte.loaded,du      Currently loaded?
3332           tze       dont_unload         no - can't unload
3333 
3334           lcx0      apte.loaded+1,du    turn off loaded bit
3335           ansx0     ap|apte.flags
3336 
3337           lda       ap|apte.asteps      pick up both asteps
3338           lcq       ptw.wired+1,dl      set bit for turnoff
3339           ansq      sst$+aste_size,au   unwire one
3340           ansq      sst$+aste_size,al   unwire other
3341           lcq       2,dl                unwired total of two pages
3342           asq       sst$wired keep pc counter up to date
3343 dont_unload:
3344 "
3345 "At this point we can pass the apte.dbr_loaded bit to the new user.
3346 "This simple bit prevented anything interesting from happening
3347 "to old user from the time he left the running state until now.
3348 "Old user cannot have regained elig, except on this cpu, if it was lost.
3349 "Old user cannot be running on any other cpu.
3350 "Old user not subject to load/unload race: gw not go to load_him if dbr_loaded
3351 "If old lost elig then old not in elig_q then old not being loaded.
3352 "There is a window in the opposite direction, analogous to the gp/gw race:
3353 "Old user is HIDDEN from getwork on other cpu's.  It is possible for
3354 "another cpu to go idle because this cpu has hidden old_user.  This possibility
3355 "is prevented by forcing a gw_gp_window retry of getwork if
3356 "a processor is about to go idle but has seen and skipped
3357 "a ready process because that process had it dbrloaded
3358 "on another processor.
3359 "
3360           lcx0      apte.dbr_loaded+1,du turn off dbr_loaded bit for old user
3361           ansx0     ap|apte.flags
3362           ldx0      apte.dbr_loaded,du  turn on dbr_loaded bit for new user
3363           orsx0     bp|apte.flags
3364 
3365           tsx6      UNLOCK_bp           gw unlocks new user
3366           tsx6      UNLOCK
3367 
3368 stop_check:
3369           eppbp     apt_ptr,*           OLD USER STOPPED?
3370           lxl0      bp|apte.state       check for stopped
3371           cmpx0     stopped,du
3372           tze       stop_check_         jump out_of_line
3373 end_stop_check:
3374 
3375 cpu_monitor_check:
3376           szn       bp|apte.cpu_monitor OLD USER MONITOR TIME?
3377           tnz       cpu_monitor_        maybe time now
3378 end_cpu_monitor:
3379 
3380 cput_check:
3381           eppbp     pds$apt_ptr,*       NEW USER CPUT?
3382           lda       bp|apte.flags       see if idle
3383           cana      apte.idle,du        yes, skip timer check
3384           tnz       end_cput_check      ..
3385           szn       pds$timer_time_out+1 see if non-zero time exists
3386           tze       end_cput_check      no, continue with getwork
3387           ldaq      bp|apte.virtual_cpu_time see if process is over time limit
3388           cmpaq     pds$timer_time_out
3389           tmi       end_cput_check      no, continue with getwork
3390           fld       0,dl                zero the time out value
3391           staq      pds$timer_time_out
3392           ldaq      pds$timer_channel   time up, check if ev chan is zero
3393           tnz       cput_wakeup         it's non-zero, need full wakeup
3394           lda       sys_info$cput_mask
3395           tsx6      add_ips_message     use stacq
3396           tra       end_cput_check
3397 cput_wakeup:
3398           stz       tmp_ring            set up for call to 'make_itt_message'
3399           stz       dev_signal          count it as dev_signal
3400           aos       dev_signal          count it as dev_signal
3401           lda       =acput              ev message is 'cputimer'
3402           ldq       =aimer
3403           staq      tmp_ev_message      save in stack
3404           ldaq      pds$timer_channel   copy ev channel into stack
3405           staq      tmp_ev_channel
3406           lda       bp|apte.processid   copy processid for make_itt_message
3407           sta       pds$arg_1
3408           stc1      pds$wakeup_flag     not require unique message
3409           tsx6      LOCK_bp             cput_wakeup protects event thread
3410           tsx7      make_itt_message
3411           lda       apte.wakeup_waiting,du Cheap wakeup of self
3412           orsa      bp|apte.flags
3413           tsx6      UNLOCK_bp           cput_wakeup is done
3414 end_cput_check:
3415 
3416           lda       bp|apte.flags       check stop or ips pending
3417           ana       apte.stop_pending,du
3418           ora       bp|apte.ips_message see if an ips signal must be sent
3419           tze       no_more_pending     no, skip over SMIC
3420           lda       1,dl                set ring alarm for exit from ring 0
3421           sta       pds$alarm_ring
3422 no_more_pending:
3423 
3424           lbar      pds$base_addr_reg   get base address reg for new process
3425           lra       pds$alarm_ring      get his ralr setting too
3426 
3427           ldaq      prds$last_recorded_time calc this process's CPU time
3428           sbaq      bp|apte.time_used_clock fudge it for easy calc later
3429           staq      pds$cpu_time        save in the PDS for the process
3430 
3431           read_clock                    " meter rest of getwork time
3432           sbaq      getwork_temp        set on entry to getwork by 'old_user'
3433           adaq      bb|getwork_time     keep running total
3434           staq      bb|getwork_time
3435           aos       bb|getwork_time+2   keep count of getworks
3436           eppbp     pds$apt_ptr,*       set bp to apt entry
3437 "
3438 "         Still masked and wired, check for need to allocate a stack_0
3439 "         and if needed do so.
3440 
3441           szn       pds$stack_0_sdwp,*
3442           tnz       already_got_stack_0 Doin' fine, no problem.
3443 
3444           tsx6      lock_stack_queue
3445           ldx0      ab|sdt.freep
3446           drlze     (pxss: no available stack_0) A fine time to run out of stacks.
3447           ldx4      ab|sdte.nextp,0     Thread out.
3448           stx4      ab|sdt.freep
3449           eax4      0
3450           stx4      ab|sdte.nextp,0     Clean thread
3451           eax2      bp|0
3452           sxl2      ab|sdte.aptep,0     For debugging.
3453           ldaq      ab|sdte.sdw,0
3454           staq      pds$stack_0_sdwp,*  Store the SDW in DSEG.
3455           cams      4                   Clear cache. Think about it.
3456                               "cams 0 not needed, did ldbr since last stack_0.
3457           tsx6      unlock_stack_queue
3458           lda       apte.shared_stack_0,du        Flag stack to be returned
3459           orsa      bp|apte.flags
3460 already_got_stack_0:
3461 
3462           lda       bp|apte.flags       Load flags once again
3463           cana      apte.firstsw+apte.idle,du First time & ^idle ?
3464           tze       stproc              is first time. do special return
3465 "
3466           cana      apte.idle,du        idle process?
3467           tze       no_idle_no_del      if not, don't do next check
3468           lxl1      prds$processor_tag  get CPU tag
3469           lda       scs$processor_data,1 look at data for this CPU
3470           cana      processor_data.delete_cpu,du to be deleted?
3471           tnz       delete_me           if so, stop it now
3472           szn       temp1               before going idle, see if there was interference
3473           tze       no_idle_no_del      was none, ok to idle
3474           lda       1,dl
3475           sta       pds$alarm_ring      set ring_alarm to remind idle to come back
3476           lda       apte.pre_empt_pending,du
3477           orsa      bp|apte.flags
3478           aos       bb|gw_gp_window_count meter these
3479 no_idle_no_del:
3480 
3481           lxl7      bp|apte.savex7      restore x7 for return
3482           tra       0,7
3483 
3484 stproc:   lda       apte.firstsw,du     turn ON flag saying we're initialized
3485           orsa      bp|apte.flags
3486           lda       bb|process_initial_quantum    Give special quantum first time
3487           sta       bp|apte.temax       put initial quantum in APTE
3488 "
3489 "Unlock,switch stacks, restore mask, and perform special first time call.
3490 "
3491           eppsp     pds$last_sp,*
3492           ldaq      sb|stack_header.stack_begin_ptr Truncate PRDS.
3493           staq      sb|stack_header.stack_end_ptr
3494           epbpsb    sp|0
3495           lda       bp|apte.processid
3496           cmpa      tc_data$initializer_id Is this the initializer?
3497           tze       dont_reset_stack_0
3498           ldaq      sb|stack_header.stack_begin_ptr Clean out any old crud
3499           staq      sb|stack_header.stack_end_ptr
3500 dont_reset_stack_0:
3501           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+><+>
3502           ldaq      scs$open_level
3503           lxl1      prds$processor_tag
3504           lprpab    scs$mask_ptr,1
3505           xec       scs$set_mask,1
3506           inhibit   off                 <-><-><-><-><-><-><-><-><-><-><-><->
3507           eppap     =its(-1,1),*
3508           eppbp     pds$initial_procedure
3509           rtcd      bp|0
3510 
3511 
3512 
3513 
3514 " ^L
3515 "
3516 "         NTO_CHECK -- This code checks for lost notifies.
3517 "                   Salient features include:
3518 "                   1. It is executed every nto_delta microsec.
3519 "                   2. It is entered with no locks set.
3520 "                   3. It looks for processes unchanged for > nto_delta.
3521 "                   4. If one is found it is notified, metered, and johndeaned.
3522 "                   5. If none, the time of the next check is set.
3523 "                   6. It returns to gw_retry with no locks set.
3524 nto_check:
3525           tsx6      READ_LOCK
3526           eax2      bb|eligible_q_head
3527 nto_loop: ldx2      bb|apte.thread,2    step to next process
3528           szn       bb|apte.sentinel,2
3529           tmi       nto_reset_time      have done them all, all done
3530           tsx6      LOCK_x2             no need for speed here
3531           lxl0      bb|apte.state,2     only (ptl)waiters get nto'd
3532           cmpx0     waiting,du          waiter?
3533           tze       nto_wait            this one is waiting now
3534           cmpx0     ptlocking,du        waiter on PTL?
3535           tnz       nto_not             no
3536           lda       =aptlw              yes, fake the event
3537           sta       bb|apte.wait_event,2
3538           tra       nto_wait            now go notify
3539 
3540 nto_not:  tsx6      UNLOCK_x2           not waiting
3541           tra       nto_loop            so go to next
3542 
3543 nto_wait: ldaq      bb|apte.state_change_time,2
3544           adl       bb|nto_delta
3545           cmpaq     getwork_temp        State change more than nto_delta ago?
3546           tpl       nto_not             No, go to next
3547 
3548           aos       bb|nto_count        meter notify timeouts
3549           ldac      bb|apte.wait_event,2 Yes, reset state
3550           sta       tmp_event
3551           sta       bb|nto_event
3552           lda       bb|apte.processid,2
3553           sta       temp1
3554           lcx0      apte.page_wait_flag+1,du
3555           ansx0     bb|apte.flags,2
3556           ldx0      ready,du
3557           eppbp     bb|0,2
3558           tsx7      update_execution_state
3559           tsx6      UNLOCK_x2
3560           tsx7      get_processor
3561           szn       bb|time_out_severity negative means dont print
3562           tmi       nto_loop            can continue looping
3563           tsx6      UNLOCK              don't call out with lock set
3564 "
3565 "         call syserr (tc_data|time_out_severity,"pxss: notify time out: event=^w, pid=^w",
3566 "              apte.wait_event, apte.processid)
3567 "
3568           epplb     bb|time_out_severity
3569           sprilb    arg+2
3570           epplb     nto_message
3571           sprilb    arg+4
3572           epplb     tmp_event
3573           sprilb    arg+6
3574           epplb     temp1
3575           sprilb    arg+8
3576           epplb     fixed_desc
3577           sprilb    arg+10
3578           sprilb    arg+14
3579           sprilb    arg+16
3580           epplb     nto_message_desc
3581           sprilb    arg+12
3582           ldaq      =v18/8,18/4,18/8,18/0
3583           staq      arg
3584           call      syserr$syserr(arg)
3585           tra       gw_retry            nto_check returns with no lock set
3586 "
3587 "Come here when scan of eligible queue has found no nto's.
3588 nto_reset_time:
3589           read_clock
3590           adl       bb|nto_delta
3591           staq      bb|nto_check_time
3592           tsx6      UNLOCK              nto_check returns with no lock set
3593           tra       gw_retry
3594 nto_message_desc:
3595           oct       524000000047
3596 nto_message:
3597           aci       "pxss: notify time out: event=^w, pid=^w"
3598 
3599 "^L
3600 load_him: cana      apte.being_loaded,du see if we must load him
3601           tnz       gw_cant_run         sombody already loading this process
3602 
3603           lda       apte.being_loaded,du turn on being loaded flag
3604           orsa      bb|apte.flags,2
3605           tsx6      UNLOCK_x2
3606           tsx6      UNLOCK
3607           eppap     apt_ptr
3608           spriap    arg+2
3609           eppap     bb|0,2
3610           spriap    apt_ptr
3611           fld       =1b24,dl
3612           staq      arg
3613           call      wired_plm$load(arg) load the process
3614           tsx6      LOCK_x2
3615           eppbp     bb|0,2              set bp to this entry
3616           lda       bp|apte.wait_event   should we wait for the loading to complete ?
3617           tze       loaded_test         no, loading may be complete
3618           lda       apte.page_wait_flag,du
3619           orsa      bp|apte.flags
3620           ldx0      waiting,du          -- Wait --
3621           tsx7      update_execution_state
3622           tra       load_him_done       start over
3623 " must verify loading with APTE locked
3624 loaded_test:
3625           lda       bp|apte.asteps      Get both asteps in Areg
3626           ldq       ptw.wired+ptw.valid,dl        Get mask in Qreg
3627           anq       sst$+aste_size,au   Require this page
3628           anq       sst$+aste_size,al   AND that page
3629           cmpq      ptw.wired+ptw.valid,dl        have required bits on.
3630           tnz       load_him_done       Didn't, must retry getwork.
3631           lda       apte.loaded,du      turn loaded flag on
3632           orsa      bb|apte.flags,2
3633           aos       bb|loadings
3634 load_him_done:
3635           lcx0      apte.being_loaded+1,du Turn off being loading bit
3636           ansx0     bp|apte.flags
3637           tsx6      UNLOCK_x2
3638           tra       gw_retry            load_him retries getwork from the top
3639 
3640 find_idle_for_delete:
3641           tsx6      READ_LOCK
3642 find_idle:
3643           ldx2      prds$idle_ptr+1
3644           tsx6      LOCK_x2
3645           stz       bb|apte.te,2        zero idle's te
3646           tra       gw_can_run
3647 "^L
3648 "         This section of code is invoked when a simulated alarm
3649 "         clock interrupt is detected. Metering is kept of the lag of
3650 "         the simulated timer from when it should really gone off.
3651 
3652 alarm_timer:
3653           tsx6      WRITE_LOCK          alarm timer
3654 at_retry:
3655           read_clock
3656           sbaq      bb|next_alarm_time  compute lag in simulated timer
3657           tpnz      at_now
3658           tsx6      UNLOCK              false alarm
3659           tra       gw_retry
3660 
3661 at_now:
3662           aos       bb|clock_simulations count number of clock simulations
3663           cmpq      bb|max_clock_lag    keep maximum lag
3664           tmi       *+2                 ..
3665           stq       bb|max_clock_lag    ..
3666           adaq      bb|total_clock_lag  add to total
3667           staq      bb|total_clock_lag  ..
3668           read_clock                    " remember clock time
3669           staq      bb|next_alarm_time  ..
3670 
3671 "         The following code checks to see if a process timer should have
3672 "         gone off.
3673 
3674 next_timer:
3675           ldx2      bb|alarm_timer_list get next process on timer list
3676           tze       priority_scheduling no one is on list
3677           eppbp     bb|0,2              set APT pointer
3678           ldaq      bp|apte.alarm_time  when should process timer go off
3679           ana       =o777777,dl         mask off thread
3680           cmpaq     bb|next_alarm_time  has time passed
3681           tpl       priority_scheduling if not then we are done here
3682           ldx3      bp|apte.alarm_time  unthread from list
3683           stx3      bb|alarm_timer_list
3684           fld       0,dl                zero out time
3685           staq      bp|apte.alarm_time  ..
3686           lxl3      bp|apte.state       make sure process is alive
3687           cmpx3     stopped,du          ..
3688           tze       next_timer          if process dead, forget it
3689           tsx6      LOCK_bp             wakup alrm
3690           ldaq      bp|apte.alarm_event get event channel
3691           tnz       wakeup_alarm        if channel then go wakeup
3692           lda       sys_info$alrm_mask
3693           tsx6      add_ips_message
3694           tsx7      send_connect        send connect if running
3695           tra       at_wake
3696 wakeup_alarm:
3697           stz       tmp_ring            send wakeup
3698           stz       dev_signal          count it as dev_signal
3699           aos       dev_signal          count it as dev_signal
3700           lda       =aseta              event message is setalarm
3701           ldq       =alarm              ..
3702           staq      tmp_ev_message      save in stack
3703           ldaq      bp|apte.alarm_event get event channel
3704           staq      tmp_ev_channel      save in stack
3705           lda       bp|apte.processid   copy process id for ITT message
3706           sta       pds$arg_1           ..
3707           stc1      pds$wakeup_flag     not require unique message
3708           tsx7      make_itt_message    create wakeup message
3709 at_wake:  tsx7      wake                wake up process
3710           tsx6      UNLOCK_bp           wakup alrm
3711           tra       next_timer          see if more timers to go off
3712 
3713 "         Now we check to see if there are any priority scheduling processes
3714 "         that must have their priority boosted.
3715 
3716 priority_scheduling:
3717           ldaq      bb|next_alarm_time  see if any processes need boosting
3718           cmpaq     bb|priority_sched_time ..
3719           tmi       check_ring0_timer   no processes need boosting
3720           ldaq      bb|end_of_time_loc  set time to high value
3721           staq      bb|priority_sched_time
3722           ldx2      bb|min_wct_index    begin search of ready lists
3723 
3724 ps_get_rq_head:
3725           ldx2      bb|wcte.thread,2    get index of top guy in ready queue
3726 ps1:      eppbp     bb|0,2              get pointer to next entry in ready list
3727           szn       bp|apte.sentinel    stop if end of ready list
3728           tmi       ps_next_ready_queue Now at sentinel, x2-> wcte again
3729           ldx2      bp|apte.thread      save index to next before rethreading!
3730           lda       bp|apte.flags2      is process in priority sched mode
3731           cana      apte.prior_sched,dl ..
3732           tze       ps1                 if not then go to next entry
3733           ldaq      bp|apte.state_change_time get time lost eligibility
3734           adl       bb|priority_sched_inc add in increment for rescheduling
3735           cmpaq     bb|next_alarm_time  ..
3736           tmi       ps_boost            ..
3737           cmpaq     bb|priority_sched_time see if this is next process to be boosted
3738           tpl       ps1                 if not then go to next entry
3739           staq      bb|priority_sched_time if so then remember time
3740           tra       ps1                 go to next entry
3741 ps_boost:
3742           szn       bp|apte.ti          already interactive?
3743           tze       ps1                 don't boost again, and avoid tail chasing
3744           tsx0      setup_p_int         boost priority
3745           tsx7      unthread            thread out of ready list
3746           tsx7      sort_in             sort into ready list in new place
3747           aos       bb|boost_priority   count number of boosts
3748           tra       ps1                 go to next entry
3749 ps_next_ready_queue:
3750           eax2      size_of_wct_entry,2 Move to next wcte
3751           cmpx2     bb|max_wct_index    If If there is one.
3752           tmoz      ps_get_rq_head
3753 "^L
3754 check_ring0_timer:
3755           ldaq      bb|next_ring0_timer
3756           cmpaq     bb|next_alarm_time
3757           tpl       check_polling
3758 
3759           ldaq      bb|end_of_time_loc  don't allow this again
3760           staq      bb|next_ring0_timer
3761 
3762 " wake up any ring 0 process waiting for a short time
3763 
3764           tsx6      UNLOCK              unlock for notify
3765           ldq       ring0_timer_event
3766           stq       pds$arg_1
3767           stc1      dev_signal          flag says special notify
3768           tsx6      notify_             notify waiters
3769           tsx6      WRITE_LOCK          return to polling checks
3770 
3771 "         Now we check to see if the disk DIM or tty DIM need
3772 "         to be polled.
3773 
3774 check_polling:
3775           eax4      n_polling_table-4   initialize index for table search
3776 polling_loop:
3777           xec       polling_table+2,4   execute before test
3778 test_poll:
3779           ldaq      bb|next_alarm_time  get time for this alarm
3780           ldx3      polling_table,4     get address of link to time
3781           cmpaq     lp|0,3*             has time matured?
3782           tmi       skip_polling        if not, skip this call
3783 
3784           adl       polling_table+1,4   compute time of next poll
3785           staq      lp|0,3*             and set new time
3786 
3787           tsx6      UNLOCK              call out with APT unlocked
3788           lxl3      polling_table,4     get address of routine to call
3789           call      lp|0,3*(null_arglist) make call
3790           tsx6      WRITE_LOCK          relock the APT now
3791           tra       next_poll           on to the next
3792 
3793 skip_polling:
3794           xec       polling_table+3,4   execute after test
3795 next_poll:
3796           eax4      -4,4                step to next table entry
3797           tpl       polling_loop        and loop
3798 
3799 "         Now we compute the next simulated alarm clock time.
3800 
3801 compute_next_alarm:
3802           ldx2      bb|alarm_timer_list get next process timer
3803           tze       *+5                 no process timer
3804           ldaq      bb|apte.alarm_time,2 ..
3805           ana       =o777777,dl         mask off thread
3806           cmpaq     bb|priority_sched_time is it before priority sched time
3807           tmi       *+2
3808           ldaq      bb|priority_sched_time if sched time first use it
3809           cmpaq     bb|next_ring0_timer how about ring0 timers?
3810           tmi       *+2
3811           ldaq      bb|next_ring0_timer
3812 
3813           eax4      n_polling_table-4   initialize index for table search
3814 next_alarm_loop:
3815           ldx3      polling_table,4     get pointer to time
3816           cmpaq     lp|0,3*             test for earliest time
3817           tmi       *+2                 ..
3818           ldaq      lp|0,3*             ..
3819 
3820           eax4      -4,4                try next table entry
3821           tpl       next_alarm_loop     ..
3822 
3823           staq      bb|next_alarm_time  set time for next alarm
3824           tra       at_retry            go check time again
3825 
3826           even
3827 null_arglist:
3828           oct       4,0                 arglist with no args
3829 
3830 polling_table:
3831 disk_poll_entry:
3832           link      disk_polling_time,tc_data$disk_polling_time
3833           link      disk_poll,page$time_out
3834           zero      disk_polling_time,disk_poll
3835           dec       15b15
3836           nop
3837           nop
3838 
3839           link      ioi_polling_time,tc_data$tape_polling_time
3840           link      ioi_poll,ioi_masked$timer
3841           zero      ioi_polling_time,ioi_poll
3842           dec       16b15
3843           nop
3844           nop
3845 
3846           link      mos_polling_time,tc_data$mos_polling_time
3847           link      mos_poll,mos_memory_check$poll
3848           zero      mos_polling_time,mos_poll
3849           dec       600b15
3850           nop
3851           nop
3852 
3853           link      opc_polling_time,tc_data$opc_polling_time
3854           link      opc_poll,ocdcm_$poll_for_timeout
3855           zero      opc_polling_time,opc_poll
3856           dec       30b15
3857           nop
3858           nop
3859 
3860           link      volmap_poll_time,tc_data$volmap_polling_time
3861           link      volmap_poll,page$poll_volmap_io
3862           zero      volmap_poll_time,volmap_poll
3863           dec       30b15
3864           nop
3865           nop
3866 
3867           equ       n_polling_table,*-polling_table
3868 " ^L
3869 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "" " "
3870 "
3871 "         COMPUTE_VIRTUAL_CLOCKS -- procedure to figure out what type of
3872 "         idle time we have, and also to update the time used in the
3873 "         APT entry for the process just run.
3874 "         A meter lock protects per-system doubleword variables
3875 "
3876 "         Idle time is categorized as follows:
3877 "
3878 "         zero idle       - all processes blocked except idle processes
3879 "         nmp idle        - all processes which could be eligible are eligible
3880 "         loading idle    - not all processes which could be eligible are
3881 "                           eligible, and not all eligible processes are loaded
3882 "         work class idle - not all processes which could be eligible are
3883 "                           eligible, at least one work class was
3884 "                           skipped because of work class limits
3885 "                           (governing, max eligible for work class),
3886 "                           and system maxe has not been reached
3887 "         mp idle         - not all processes which could be eligible are
3888 "                           eligible, and criteria for work class idle
3889 "                           not met
3890 "
3891 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
3892 
3893 compute_virtual_clocks:
3894           eppbp     pds$apt_ptr,*       set bp to this process
3895           lda       pds$page_waits      copy page fault count into APT entry
3896           sta       bp|apte.page_faults
3897           ldaq      bp|apte.virtual_cpu_time Remember bp's vcpu
3898           staq      temp                Use temp for delta virtual time.
3899 
3900           read_clock
3901           staq      bb|last_time        save last time anyone run
3902           sbaq      prds$last_recorded_time delta t in microseconds
3903           staq      delta_t
3904           asq       bb|governing_credit_bank
3905 
3906           adaq      bp|apte.time_used_clock update time used in APT
3907           staq      bp|apte.time_used_clock
3908           sbaq      pds$virtual_delta   update the virtual CPU time
3909           staq      bp|apte.virtual_cpu_time
3910 
3911           sbaq      temp                Subtract old vcpu from new
3912           staq      temp                Remember for idle meters.
3913 
3914           ldaq      delta_t             meter last recorded time
3915           adaq      prds$last_recorded_time
3916           staq      prds$last_recorded_time
3917 
3918 mlock_loop:
3919           ldac      bb|metering_lock    LOCK LOCK LOCK LOCK LOCK LOCK LOCK
3920           tnz       mlocked             OK- meters are locked
3921           tra       mlock_loop          retry locking meters
3922 mlocked:
3923           ldaq      delta_t             meter total CPU time for system
3924           adaq      bb|processor_time
3925           staq      bb|processor_time
3926 
3927           ldaq      prds$last_recorded_time compute ave queue length
3928           anq       =o3777777           sample every sec (2**20 usec)
3929           adq       delta_t+1
3930           qrl       20-18               convert to sec
3931 agl:      eaq       -1,qu               count seconds
3932           tmi       age
3933           lda       bb|statistics+running get queue length
3934           ada       bb|statistics+ready
3935           ada       bb|statistics+waiting running+ready+waiting
3936           als       18                  give answer 6 octal points
3937           sba       bb|avequeue         new ave=oldave+(cur-oldave)/64
3938           ars       6
3939           asa       bb|avequeue
3940           lda       bb|n_eligible       now get average eligible
3941           als       18
3942           sba       bb|ave_eligible
3943           ars       6
3944           asa       bb|ave_eligible
3945           tra       agl
3946 
3947 age:
3948 
3949           lda       bp|apte.flags       check for idle process
3950           cana      apte.idle,du
3951           tnz       cvidle              is
3952 
3953           ldx0      prds$depth          count runs at depth
3954           aos       bb|depths,0
3955           adx0      prds$depth          double index
3956           ldaq      delta_t             bump time at level
3957           adaq      bb|tdepth,0
3958           staq      bb|tdepth,0
3959 
3960           ldaq      temp                Update vcpu used by nonidle
3961           adaq      bb|system_virtual_time
3962           staq      bb|system_virtual_time
3963 
3964           ldx0      bp|apte.wct_index   Update work_class data.
3965           ldaq      delta_t             Workclasses get % of tcpu - not vcpu
3966           szn       bb|wcte.realtime,0  Realtime not add to bank.
3967           tnz       *+2
3968           asq       bb|credit_bank      But others do.
3969 
3970           adaq      bb|wcte.cpu_sum,0   Add to time gotten
3971           staq      bb|wcte.cpu_sum,0
3972           lcq       delta_t+1           Decrement credits.
3973           asq       bb|wcte.credits,0
3974           lda       bb|wcte.governed_word,0       Is W.C. governed
3975           cana      wcte.governed,du
3976           tze       m_unlock            no
3977           asq       bb|wcte.governing_credits,0
3978           tra       m_unlock            Now go unlock metering data.
3979 
3980 cvidle:   ldaq      temp                up total idle vcpu
3981           adaq      bb|idle_time
3982           staq      bb|idle_time
3983 
3984           ldaq      delta_t             Update idle  real cpu time.
3985           adaq      bb|gross_idle_time
3986           staq      bb|gross_idle_time
3987 
3988           ldaq      temp                up idle vcpu by type
3989           ldx0      bp|apte.term_processid recall our idle type
3990           tze       m_unlock            ignore first time
3991           adaq      bb|0,0
3992           staq      bb|0,0
3993 
3994 m_unlock: stc1      bb|metering_lock    UNLOCK UNLOCK UNLOCK UNLOCK UNLOCK
3995 cvidt:    lda       bb|apte.flags,2     Is new guy idle?
3996           cana      apte.idle,du
3997           tze       0,7                 no, not idle
3998           eax0      zero_idle           yes, figure type
3999           lda       bb|statistics+running
4000           ada       bb|statistics+ready
4001           ada       bb|statistics+waiting
4002           ada       bb|statistics+ptlocking
4003           tze       cvst                Will be zero_idle
4004           eax0      nmp_idle
4005           cmpa      bb|n_eligible
4006           tze       cvst                Will be NMP idle
4007           eax0      loading_idle
4008           lxl1      bb|eligible_q_tail
4009           ldx1      bb|apte.flags,1
4010           canx1     apte.loaded,du
4011           tze       cvst                Will be Loading idle
4012           eax0      mp_idle
4013           szn       temp2               Work class limit reached?
4014           tze       cvst                No, will be MP idle
4015           lxl1      bb|n_eligible       Are we at system max eligible?
4016           cmpx1     bb|max_eligible
4017           tpl       cvst                Yes, will be MP idle
4018           eax0      work_class_idle     No, will be work class idle
4019 cvst:     stx0      bb|apte.term_processid,2 Remember idle type.
4020           tra       0,7
4021 " ^L
4022 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4023 "
4024 "         SET_NEWT  -- procedure to figure out how long the new process
4025 "         should run.
4026 "
4027 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4028 
4029 set_newt:
4030           lda       bb|apte.flags,2     if idle, give him much time
4031           cana      apte.idle,du
4032           tze       sn1                 if not idle then compute new timer
4033 
4034           read_clock                    " compute time to next alarm
4035           sbaq      bb|next_alarm_time  ..
4036           tpl       setsmall            make sure time has not already passed
4037           negl      0                   make time positive
4038           cmpaq     idle_runout         is it very large
4039           tmi       sn2                 no, go set it
4040           ldaq      idle_runout         yes, reduce it
4041           tra       sn2                 then set it
4042 sn1:
4043 
4044           eaa       0
4045           ldq       bb|apte.temax,2     Pick up correct quantum
4046           sbq       bb|apte.te,2
4047           cmpq      4000,dl
4048           tpl       sn_ck_big
4049           ldq       4000,dl
4050           tra       sn2
4051 sn_ck_big:
4052           cmpaq     bb|max_timer_register
4053           tmi       sn2
4054           ldaq      bb|max_timer_register
4055 
4056 sn2:
4057           qls       3+1                 binary point at 3, round
4058           div       apte.timer_factor,dl convert to clock ticks
4059           adq       1,dl                round
4060           qls       12-1                timer_shift, round bit
4061           tpl       *+2                 must have positive time value
4062 setsmall: ldq       =o010000,dl         small timer value
4063           stq       prds$last_timer_setting
4064           tra       0,7                 success return
4065 
4066           even
4067 idle_runout:
4068           dec       0,250000            timer runout for idle process
4069 " ^L
4070 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4071 "
4072 "         hash_LOCK -- called with alleged processid in pds$arg_1
4073 "
4074 "                   if processid is valid:
4075 "                             apt_ptr, BP -> APTE
4076 "                             APTE is locked
4077 "                             return to 1,7
4078 "
4079 "                   if processid is invalid:
4080 "                             apt_ptr, BP = null
4081 "                             nothing new is locked
4082 "                             return is indirect through 0,7
4083 "
4084 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4085 
4086 hash_LOCK:
4087           ldq       pds$arg_1           get processid
4088           tmi       not_found           Neg pid may cause overflow fault
4089           sbq       bb|apt_offset       subtract apt offset
4090           div       size_of_apt_entry,du
4091           cmpq      bb|apt_size         check against bounds of array
4092           trc       not_found           was invalid offset
4093 
4094           mpy       size_of_apt_entry,dl Apply array to index
4095           eppbp     tc_data$apt,ql
4096           spribp    apt_ptr             return pointer to apt entry
4097           tsx6      LOCK_bp             hash_lock must lock to check pid
4098           ldq       pds$arg_1
4099           cmpq      bp|apte.processid   make sure it's the same one
4100           tze       1,7                 success return from hash_lock
4101           tsx6      UNLOCK_bp           hash_lock found wrong pid
4102 not_found:
4103           eppbp     null,*              get null pointer, return
4104           spribp    apt_ptr             null this too
4105           tra       0,7*                hash_lock failure indirect return
4106 
4107           even
4108 " ^L
4109 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4110 "
4111 "         IPS_WAKEUP -- entry to wake up a process, turn on the ips_pending
4112 "         flag and resort the process with high priority.
4113 "         Call is
4114 "                   call pxss$ips_wakeup(processid,message)
4115 "         wher processid is the process id of the process to be awakened, and
4116 "         message specifies which IPS message is being sent.
4117 "         Currently 'message' is declared char (4), eventually it will be fixed
4118 "
4119 " " " " " " " " " " " " " " " " " " " " " " "" " " "  " " " " " " " " " " " " "
4120 
4121 
4122 ips_wakeup_int:
4123           tsx6      setup_
4124           stz       pds$wakeup_flag     save info about which entry
4125           tra       ijoin
4126 ips_wakeup:
4127           tsx6      setup_
4128           stc1      pds$wakeup_flag
4129 ijoin:
4130           lda       ap|2,*              get processid
4131           sta       pds$arg_1
4132           lda       ap|4,*              pick up IPS bit string
4133           sta       pds$arg_2           save in PDS
4134           tsplb     setup_check         switch stacks and lock
4135           arg       0,6
4136           tsx6      WRITE_LOCK          ips_wakeup protect pid, rethreads
4137           tsx7      hash_LOCK           hash search for the APTE
4138           arg       ips_wakeup_returns_nul no, don't continue
4139           lxl0      bp|apte.state       make sure not stopped
4140           cmpx0     stopped,du
4141           tze       ips_wakeup_returns
4142           lda       pds$arg_2           get IPS bit string
4143           tsx6      send_ips_wakeup     Do the real work, destroys pds$arg_3
4144 "                                       Next instruction may be skipped on return
4145           nop       0                   The subroutine already did the right thing
4146 ips_wakeup_returns:
4147           tsx6      UNLOCK_bp           We're all done now
4148 ips_wakeup_returns_nul:
4149           tsx6      UNLOCK
4150           tra       switch_back         Return to caller
4151 "^L
4152 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
4153 "
4154 "         SEND_IPS_WAKEUP:  called via tsx6.  It saves the value
4155 "         of x6 in pds$arg_3 for use when returning.  This is OK
4156 "         since the current callers are WAKEUP and IPS_WAKEUP
4157 "         who know what they are doing.  It expects the IPS bit
4158 "         string to be in the a register when it is called.  It
4159 "         also expects pds$wakeup_flag to be set to 0 if good
4160 "         priority is desired and to > 0 if not.
4161 "
4162 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
4163 
4164 send_ips_wakeup:
4165           stx6      pds$arg_3           save x6 for later return
4166           tsx6      add_ips_message
4167 
4168           szn       pds$wakeup_flag     should we give good priority ?
4169           tpnz      send_ips_ij2        no, skip code which gives priority
4170 
4171           lxl0      bp|apte.state       get state of process being awakened
4172           cmpx0     ptlocking,du        bugfix:dont OOB quit buckets
4173           tpl       *+2                 bugfix:dont OOB quit buckets
4174           aos       bb|quit_counts,0    and count this ips priority wakeup
4175 
4176           ldq       bp|apte.te          first update ti
4177           adq       bp|apte.ts
4178           adq       bp|apte.ti
4179           mpy       bb|quit_priority    get new priority
4180           lls       36-18               (binary point at 18)
4181           eax3      0,au                Save ti in X3
4182           tsx0      setup_p_int         boost priority
4183           stx3      bp|apte.ti          Store ti from X3.
4184 send_ips_ij2:
4185           ldx0      bp|apte.flags       don't move if eligible
4186           canx0     apte.eligible,du
4187           tze       send_ips_non_elig
4188           canx0     apte.dbr_loaded,du  however, running may never notice
4189           tnz       send_ips_connect
4190           tra       send_ips_wakeup_returns otherwise will notice at next run time
4191 send_ips_non_elig:
4192           lxl0      bp|apte.state
4193           cmpx0     blocked,du          if not blocked, move in q
4194           tze       send_ips_connect
4195           tsx7      unthread
4196           tsx7      sort_in
4197 send_ips_connect:
4198           tsx7      send_connect        send connect if process running
4199           tsx7      wake                wake up process
4200           ldx6      pds$arg_3           restore x6
4201           tra       1,x6                return to wake done place
4202 send_ips_wakeup_returns:
4203           ldx6      pds$arg_3           restore x6
4204           tra       0,x6                return to no wake done place
4205 "^L
4206 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
4207 "
4208 "         SETUP_INT: called via tsx0, sets apte variables to give
4209 "         high priority and initial quantum following interaction.
4210 "         SETUP_P_INT: gives high priority etc w/o interaction.
4211 "
4212 
4213 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
4214 setup_p_int:
4215           aos       bb|p_interactions   Meter priority interactions.
4216           lcx1      apte.interaction+1,du
4217           ansx1     bp|apte.flags       Turn off interaction flag.
4218 
4219 setup_int:
4220           ldx1      bp|apte.wct_index
4221           stz       bp|apte.ti          High priority.
4222           stz       bp|apte.ts
4223           stz       bp|apte.te
4224           read_clock                    " Calc new deadline.
4225           adaq      bb|wcte.resp1,1     By adding to curr time.
4226           staq      bp|apte.deadline
4227 
4228           ldq       bb|wcte.quantum1,1  Pick up new quantum.
4229           lda       bb|deadline_mode    If deadline mode
4230           ada       bb|wcte.realtime,1  or realtime process
4231           tpnz      *+2                 use per-workclass quantum.
4232           ldq       bb|tefirst          use default.
4233           stq       bp|apte.temax
4234 
4235           tra       0,0                 Return from setup_int.
4236 "^L
4237 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4238 "
4239 "         SETUP_IO_REALTIME: called via tsx0, sets apte variables
4240 "         for a realtime burst of eligibility
4241 "
4242 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4243 
4244 setup_io_realtime:
4245           read_clock
4246           adl       bb|realtime_io_deadline
4247           staq      bp|apte.deadline
4248           ldq       bb|realtime_io_quantum        " And quantum
4249           stq       bp|apte.temax
4250           aos       bb|realtime_priorities        " Meter
4251           tra       0,0
4252 
4253 "^L
4254 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4255 "
4256 "         REVOKE_ELIG: called with write_lock, turns off elig, decrements counters
4257 "
4258 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4259 
4260 revoke_elig:
4261           lcx1      apte.eligible+1,du  take away eligibilty
4262           ansx1     bp|apte.flags
4263           lca       1,dl                Put -1 in Areg for subtracts ..
4264           asa       bb|n_eligible
4265           lxl1      bp|apte.flags2      If was batch
4266           canx1     apte.batch,du       then decrement batch counter
4267           tze       *+2                 else dont
4268           asa       bb|num_batch_elig   use -1 in the A
4269 
4270           ldx1      bp|apte.wct_index   Decrement workclass counter.
4271           asa       bb|wcte.nel,1
4272           lda       bp|apte.saved_temax Make up for init decrement
4273           asa       bb|wcte.credits,1   of wc credits.
4274           ldq       bb|wcte.governed_word,1       Is wc governed
4275           canq      wcte.governed,du
4276           tze       *+2                 No
4277           asa       bb|wcte.governing_credits,1
4278           lca       bp|apte.ws_size     Sub ws from sum of elig ws
4279           asa       bb|ws_sum
4280           stz       bp|apte.wait_event  he won't get notified
4281 
4282 "         Give up the stack_0 if it has a shared one
4283 
4284           lda       bp|apte.flags
4285           cana      apte.shared_stack_0,du
4286           tze       0,7
4287 
4288 "         Don't give up the stack for a stopped process, unless the
4289 "         limit of such suspended stacks has been reached
4290 
4291           lxl0      bp|apte.state
4292           cmpx0     stopped,du          is he stopped
4293           tnz       give_up_stack       no--OK to release stack
4294           lda       bb|stopped_stack_0  check limit on suspended
4295           cmpa      bb|max_stopped_stack_0    stacks
4296           tpl       give_up_stack       too bad--flush the stack
4297           aos       bb|stopped_stack_0  add to count of suspended stacks
4298           ldx0      -1,du               and decrement count of
4299           asx0      bb|max_max_eligible   available stacks
4300           tra       0,7
4301 give_up_stack:
4302 
4303 "         Check the validity of the stack
4304 
4305           eppab     sst$
4306           ldaq      pds$stack_0_sdwp,*
4307           arl       12
4308           sbla      sst$ptwbase
4309           eppab     ab|0,al             ptr to ptw for page 0
4310 
4311           lda       ab|0                get the ptw
4312           cana      ptw.wired,dl        check page 0 wired
4313           drlnz     (pxss: stack_0 page 0 wired) SHOULD NOT BE!!!!
4314 
4315           tsx6      lock_stack_queue
4316           ldaq      pds$stack_0_sdwp,*  Get stack SDW
4317           drlze     (pxss: no stack_0 sdw) LOSE! snb/0
4318           lxl0      ab|sdt.num_stacks   This is how many slots
4319           eax4      0                   Entry index
4320 free_stack_0_loop:
4321           cmpaq     ab|sdt.sdw,4
4322           tze       free_stack_0_got
4323           eax4      sdte_size,4
4324           eax0      -1,0
4325           tpnz      free_stack_0_loop
4326           drltra    (pxss: freeing unknown stack_0) STACK NOT FOUND
4327 free_stack_0_got:
4328           tsx6      free_stack_0        Give it up
4329           fld       0,dl
4330           staq      pds$stack_0_sdwp,*  Clear out SDW for getwork check.
4331 
4332           tsx6      unlock_stack_queue
4333 
4334           lcx0      apte.shared_stack_0+1,du
4335           ansx0     bp|apte.flags       reset flag
4336           tra       0,7                 return from revoke_elig
4337 
4338 "^L
4339 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4340 "
4341 "         RESCHEDULE: called with write_lock set
4342 "
4343 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4344 
4345 
4346 reschedule:
4347           lda       bp|apte.te          update te into ts
4348           tmi       *+2                 avoid neg ts
4349           asa       bp|apte.ts
4350 
4351           ldx1      bp|apte.wct_index
4352           read_clock                    " Calc new deadline.
4353           adaq      bb|wcte.resp2,1     By adding to cutime.
4354           staq      bp|apte.deadline
4355 
4356           ldq       bb|wcte.quantum2,1  Pick up new quantum.
4357           lda       bb|deadline_mode    If in deadline_mode
4358           ada       bb|wcte.realtime,1  or realtime process
4359           tpnz      *+2                 then use per workclass quantum.
4360           ldq       bb|telast
4361           stq       bp|apte.temax
4362 
4363           lda       bb|tefirst          if ts>min(tefirst+ti,timax)
4364           ada       bp|apte.ti
4365           cmpa      bp|apte.timax
4366           tmi       *+2
4367           lda       bp|apte.timax
4368           cmpa      bp|apte.ts
4369           tpl       nupti
4370           lda       bp|apte.ts          update ts into ti
4371           asa       bp|apte.ti
4372           stz       bp|apte.ts
4373 nupti:    stz       bp|apte.te
4374 
4375           lda       bp|apte.flags2      is this a guaranteed eligibility process
4376           cana      apte.prior_sched,dl ..
4377           tze       rs_ps_done          if not then OK
4378           aos       bb|lost_priority_eligibility record loss of eligibility
4379           ldaq      bp|apte.state_change_time compute when to boost priority
4380           adl       bb|priority_sched_inc
4381           cmpaq     bb|priority_sched_time remember when to boost next
4382           tpl       rs_ps_done          ..
4383           staq      bb|priority_sched_time
4384           cmpaq     bb|next_alarm_time  update time of next alarm if necessary
4385           tpl       rs_ps_done          ..
4386           staq      bb|next_alarm_time
4387 rs_ps_done:
4388           tra       0,7                 reschedule returns
4389 
4390 "^L
4391 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4392 "
4393 "         purge_UNLOCK: called with write_lock and apte_lock, it unlocks both
4394 "
4395 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4396 
4397 
4398 purge_UNLOCK:
4399           stz       bp|apte.ws_size
4400 
4401           tsx6      UNLOCK_bp           UNLOCK own apte before call out
4402           tsx6      UNLOCK
4403 
4404           szn       bb|post_purge_switch If at all.
4405           tze       pU_ret
4406           ldx1      bp|apte.wct_index
4407           szn       bb|wcte.purging,1   Purge on per wc basis
4408           tze       pU_ret
4409           call      page$post_purge     clean up last process's pages
4410 pU_ret:   tra       0,7                 Return from purge_UNLOCK
4411 
4412 
4413 " ^L
4414 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4415 "
4416 "         stop_check_ -- call if old user probably is stopped
4417 "
4418 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4419 
4420 
4421 stop_check_:
4422           tsx6      WRITE_LOCK          prevent empty_t interference
4423           lxl0      bp|apte.state       check for really stopped
4424           cmpx0     stopped,du
4425           tnz       stop_ul             not stopped, dont notify
4426           lda       =astop              message will be "stopstop"
4427           sta       tmp_ev_message      ..
4428           sta       tmp_ev_message+1
4429           tsplb     wake_term_pid       send stopstop to term pid
4430           eppbp     apt_ptr,*           repair BP for next test
4431 stop_ul:  tsx6      UNLOCK
4432           tra       end_stop_check      stop_check_ ret to getwork
4433 
4434 
4435 
4436 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4437 "
4438 "         cpu_monitor_ -- called if probably need to send cpulimit wakeup
4439 "
4440 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4441 
4442 cpu_monitor_:
4443           ldaq      bp|apte.virtual_cpu_time
4444           lrs       10                  convert to 1/1024 secs
4445           cmpq      bp|apte.cpu_monitor
4446           tmi       end_cpu_monitor
4447           tsx6      WRITE_LOCK
4448           tsx6      LOCK_bp
4449           szn       bp|apte.cpu_monitor
4450           tze       cm_not
4451           ldaq      bp|apte.virtual_cpu_time
4452           lrs       10                  convert to 1/1024 secs
4453           cmpq      bp|apte.cpu_monitor
4454           tmi       cm_not
4455           stz       bp|apte.cpu_monitor clear cell
4456           tsx6      UNLOCK_bp
4457           ldaq      cpulimit_msg
4458           staq      tmp_ev_message
4459           tsplb     wake_term_pid       send cpulimit to term_pid
4460 cm_done:  tsx6      UNLOCK
4461           tra       end_cpu_monitor     return to gw
4462 
4463 cm_not:   tsx6      UNLOCK_bp
4464           tra       cm_done
4465 
4466           even
4467 cpulimit_msg:
4468           aci       "cpulimit"
4469 "^L
4470 
4471 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4472 "
4473 "         WAKE_TERM_PID -- send tmp_ev_message to term_pid over term_chan
4474 "
4475 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4476 
4477 wake_term_pid:
4478           stz       dev_signal          count it as dev_signal
4479           aos       dev_signal          count it as dev_signal
4480           ldaq      bp|apte.term_channel
4481           staq      tmp_ev_channel
4482           stz       tmp_ring
4483           lda       bp|apte.term_processid
4484           sta       pds$arg_1
4485           stc1      pds$wakeup_flag     not require unique message
4486           eppbp     bb|0,au             make bp -> target_apte
4487           tsx6      LOCK_bp             wake_term_pid locks target of wakeup
4488           tsx7      make_itt_message
4489           tsx7      wake
4490           tsx6      UNLOCK_bp           wake_term_pid unlocks target apte
4491           tra       lb|0                wake_term_pid returns
4492 
4493 "^L
4494 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4495 "
4496 "         DELETE_ME
4497 "
4498 "         This is the legendary CPU Graveyard, where CPUs go to die
4499 "         when taken off-line.  When a CPU is to be deleted, getwork
4500 "         will run only an idle process on it.  When this happens,
4501 "         the process will transfer to this routine.  This routine
4502 "         does the following:
4503 "
4504 "         1. Under the Global APT lock, checks whether the system default
4505 "            CPU set would contain no online CPUs.
4506 "
4507 "         2. If the system default CPU set would contain no online
4508 "            CPUs, it changes the system default CPU set to all
4509 "            CPUs, unlocks, and prints a message on the console.
4510 "            Under the Global APT lock, checks the system default CPU
4511 "            set again.  This second check is necessary to avoid races,
4512 "            since the call to syserr must be made with the Global APT
4513 "            lock unlocked. If the second check fails, the first is
4514 "            repeated.  This should happen very rarely.
4515 "
4516 "         3. Changes the state of the idle process for this CPU to
4517 "            empty, unthreading it, but not returning it to the empty
4518 "            list.
4519 "
4520 "         4. Under the connect lock, turn off the bit for this CPU
4521 "            in scs$processor (this must be done under the connect
4522 "            lock to prevent other CPUs doing connects from spinning
4523 "            forever waiting for this one to respond).
4524 "
4525 "         5. Walk the APTE array, looking for processes whose set of
4526 "            required CPUs includes no online CPUs. Any such are changed
4527 "            to require the current system default. This must be done
4528 "            under the Global APT lock.
4529 "
4530 "         6. Unlock the Global APT lock and die (inhibited DIS).
4531 "
4532 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4533 
4534 delete_me:
4535           tsx6      WRITE_LOCK          delete_me locks out sprq
4536 
4537           lda       prds$processor_pattern        bit for this CPU
4538           era       scs$processor                 Areg = bits for remaining CPUs
4539           ana       bb|default_procs_required     Any left in default?
4540           tnz       procs_required_ok             Yes
4541 retry_delete_me:                                  " Also come here if lost race
4542           lda       all_procs_required,du         Set default to all CPUs
4543           sta       bb|default_procs_required
4544 
4545           tsx6      UNLOCK              Unlock before call-out
4546 
4547 "         call      syserr (3, "pxss: System default procs required reset to ABCDEFGH")
4548 
4549           epplb     reset_system_procs_severity
4550           sprilb    arg+2
4551           epplb     reset_system_procs_mess
4552           sprilb    arg+4
4553           epplb     fixed_desc
4554           sprilb    arg+6
4555           epplb     reset_system_procs_desc
4556           sprilb    arg+8
4557           ldaq      =v18/4,18/4,18/4,18/0
4558           staq      arg
4559           call      syserr$syserr(arg)
4560 
4561           tsx6      WRITE_LOCK          relock before checking again
4562 
4563           lda       prds$processor_pattern        Bit for this CPU
4564           era       scs$processor                 Areg = bits for remaining CPUs
4565           ana       bb|default_procs_required     Any left online
4566           tze       retry_delete_me               No - lost race
4567 
4568 procs_required_ok:
4569 
4570 "         Walk APTE array, looking for processes which can't run
4571 
4572           ldq       scs$processor       Bits for CPUs still running
4573           anq       apte.procs_required_mask,du   Strip out garbage
4574           erq       prds$processor_pattern        And bit for this CPU
4575           lca       1,dl
4576           era       apte.procs_required_mask,du   To reset procs required
4577           ldx3      bb|default_procs_required     To set to default
4578           anx3      apte.procs_required_mask,du   Strip out garbage
4579           ldx2      apte.default_procs_required,du To set bit saying it's default
4580           eppap     tc_data$apt         Begin of APTE array
4581           lxl1      bb|apt_size         Number APTEs
4582 check_proc_loop:
4583           ldx0      ap|apte.flags
4584           canx0     apte.idle,du        Skip idle processes
4585           tnz       check_proc_next
4586           canq      ap|apte.procs_required Any left for this process?
4587           tnz       check_proc_next     Yes
4588           ansa      ap|apte.procs_required Clear procs required
4589           orsx3     ap|apte.procs_required Set to default
4590           orsx2     ap|apte.flags       And remember it's the default
4591 check_proc_next:
4592           eppap     ap|size_of_apt_entry Next APTE
4593           eax1      -1,1                One less to go
4594           tpnz      check_proc_loop     But still some left
4595 
4596           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+><+>
4597 
4598           lxl1      prds$processor_tag
4599           lcx0      processor_data.online+1,du turn this bit OFF
4600           ansx0     scs$processor_data,1 ..
4601 
4602           eppbp     prds$idle_ptr,*     bp -> APTE for idle process
4603           tsx6      LOCK_bp
4604           ldx0      empty,du            set empty state
4605           tsx7      update_execution_state ..
4606           tsx6      UNLOCK_bp
4607 
4608           inhibit   off                 <-><-><-><-><-><-><-><-><-><-><-><->
4609           lda       pds$processid       lock the connect lock
4610           stac      scs$connect_lock    before diddling scs$processor
4611           nop
4612           nop
4613           tnz       -3,ic
4614           lca       1,dl                one's in A
4615           era       prds$processor_pattern make a mask
4616           ansa      scs$processor       turn off bit for this processor
4617           lda       0,dl                clear the A
4618           ansa      scs$connect_lock    can undo lock now
4619 
4620           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+><+>
4621           lxl1      prds$processor_tag
4622           lcx0      processor_data.delete_cpu+1,du turn this bit OFF
4623           ansx0     scs$processor_data,1
4624           ldx0      processor_data.offline+processor_data.halted_cpu,du turn these bits ON
4625           orsx0     scs$processor_data,1
4626 
4627           tsx6      UNLOCK              undo the lock before dying
4628 
4629           dis       =o777,dl
4630           tra       *-1
4631 
4632           inhibit   off                 <-><-><-><-><-><-><-><-><-><-><->
4633 
4634 reset_system_procs_severity:
4635           dec       3                   " severity of syserr message
4636 reset_system_procs_mess:
4637           aci       "pxss: System default procs required reset to ABCDEFGH"
4638           equ       reset_system_procs_words,*-reset_system_procs_mess
4639           equ       reset_system_procs_chars,4*reset_system_procs_words
4640 reset_system_procs_desc:
4641           vfd       1/1,6/21,5/0,24/reset_system_procs_chars
4642 "
4643 "^L
4644 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4645 "
4646 "         Hardcore stack queue locking/unlocking
4647 "
4648 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4649 
4650 lock_stack_queue:
4651           lda       pds$processid
4652           eppab     stack_0_data$
4653           cmpa      ab|sdt.lock
4654           drlze     (pxss: mylock on stack queue) mylock err
4655           stac      ab|sdt.lock
4656           nop
4657           nop
4658           tnz       *-3
4659           nop
4660           cmpa      ab|sdt.lock         Check for stac loss.
4661           drlnz     (pxss: lock_stack_queue stac failed)
4662           tra       0,6                 That's why locks are expensive in Multics.
4663 
4664 unlock_stack_queue:
4665           ldq       pds$processid
4666           cmpq      ab|sdt.lock         Check for other random lossage
4667           drlnz     (pxss: unlock_stack_queue not my lock)
4668           eaa       0
4669           stacq     ab|sdt.lock
4670           drlnz     (pxss: unlock_stack_queue stacq failed) stacq claims failure
4671           nop
4672           cmpq      ab|sdt.lock         Stacq really win?
4673           drlze     (pxss: unlock_stack_queue stacq failed)
4674           tra       0,6
4675 "^L
4676 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4677 "
4678 "         subroutine to return a stack_0 to the free list
4679 "
4680 "         tsx6      free_stack_0
4681 "
4682 "         On entry -
4683 "              sdt lock must be owned
4684 "              ab -> stack_0_data$
4685 "              x4 = index of sdte for this stack
4686 "
4687 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4688 
4689 free_stack_0:
4690           eax0      0
4691           sxl0      ab|sdt.aptep,4      No aptep
4692           eax0      ab|sdt.stacks,4     Thread in
4693           ldx4      ab|sdt.freep
4694           stx4      ab|sdte.nextp,0
4695           stx0      ab|sdt.freep
4696           tra       0,6
4697 
4698 add_ips_message:
4699           sta       tmp_event           "Remember the event
4700 add_ips.retry:
4701           ldq       bp|apte.ips_message
4702           lda       bp|apte.ips_message
4703           ora       tmp_event
4704           stacq     bp|apte.ips_message
4705           tnz       add_ips.retry
4706           tra       0,x6
4707 
4708 "^L
4709 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4710 "
4711 "         SUSPEND_GETWORK -- entry to loop until getwork all suspended
4712 "
4713 "         Call is
4714 "                   call pxss$suspend_getwork ()
4715 "
4716 "
4717 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
4718 
4719 suspend_getwork:
4720           lda       pds$processid                 see if i have the suspension lock
4721           cmpa      tc_data$tc_suspend_lock
4722           tnz       sg_returns                    return if we don't hold lock
4723 
4724           tsplb     setup_mask          going to have the APT locked
4725           tsx6      WRITE_LOCK          while we pre-empt other processes
4726 
4727           lda       bb|eligible_q_head
4728 sg_pe_loop:
4729           ldaq      bb|apte.thread,au
4730           tra       sg_pe_tv,ql*
4731 
4732           arg       sg_pe_done          -1 => sentinel
4733 sg_pe_tv: arg       DRL_empty_apte      empty - in eligible list??
4734           arg       sg_pre_empt_it      running - get the process out of there
4735           arg       sg_pe_loop          ready - skip it
4736           arg       sg_pe_loop          waiting - skip it
4737           arg       DRL_blocked_apte    blocked - doesn't belong here
4738           arg       DRL_stopped_apte    stopped - doesn't belong here
4739           arg       sg_pe_loop          ptlwait - skip it
4740 
4741 sg_pre_empt_it:
4742           lxl3      bb|apte.thread,au   get this apte addr from next apte
4743           tsx6      LOCK_x3
4744           ldq       bb|apte.flags,3     get a copy of the flags
4745           canq      apte.pre_empted,du  is it already pre-empted?
4746           tnz       sg_pe_skip          yes, so skip it
4747           lda       apte.pre_empted+apte.pre_empt_pending,du
4748           orsa      bb|apte.flags,3     turn on flags to indicate pre-emption
4749           ldq       bb|apte.flags2,3    get processor tag for the connect
4750           anq       apte.pr_tag_mask,dl
4751           cmpq      prds$processor_tag  is it this processor?
4752           tze       sg_pe_skip          yes, don't connect myself
4753           cioc      scs$cow_ptrs,ql*
4754 
4755 sg_pe_skip:
4756           tsx6      UNLOCK_x3           release the apte
4757           ldaq      bb|apte.thread,3    clobbered by sg_pre_empt_it code
4758           tra       sg_pe_loop
4759 
4760 sg_pe_done:
4761           tsx6      UNLOCK              give up the lock for a few microseconds
4762 
4763           nop       0                   delay between lockings
4764           nop       0
4765 
4766           tsx6      READ_LOCK           for seeing if all are off the cpus
4767 
4768           lda       bb|eligible_q_head
4769 sg_wt_loop:
4770           ldaq      bb|apte.thread,au
4771           tra       sg_wt_tv,ql*
4772 
4773           arg       sg_wt_done          -1 => sentinel
4774 sg_wt_tv: arg       DRL_empty_apte      empty - in eligible list??
4775           arg       sg_check_it         running - see who it is
4776           arg       sg_wt_loop          ready - skip it
4777           arg       sg_wt_loop          waiting - skip it
4778           arg       DRL_blocked_apte    blocked - doesn't belong here
4779           arg       DRL_stopped_apte    stopped - doesn't belong here
4780           arg       sg_wt_loop          ptlwait - skip it
4781 
4782 sg_check_it:
4783           lxl3      bb|apte.thread,au   get this apte addr from next apte
4784           tsx6      LOCK_x3
4785           ldq       bb|apte.flags,3     get a copy of the flags
4786           canq      apte.idle,du        is it an idle?
4787           tnz       sg_wt_skip          yes - this is ok.
4788           ldq       bb|apte.flags2,3    get processor tag for this process
4789           anq       apte.pr_tag_mask,dl
4790           cmpq      prds$processor_tag  is it me??
4791           tze       sg_wt_skip          yes - this is also ok.
4792 
4793           tsx6      UNLOCK_x3           no - unlock and check all over again
4794           tra       sg_pe_done
4795 
4796 sg_wt_skip:
4797           tsx6      UNLOCK_x3           release the apte
4798           ldaq      bb|apte.thread,3    clobbered by sg_check_it code
4799           tra       sg_wt_loop
4800 
4801 sg_wt_done:
4802           tsx6      UNLOCK
4803           tsx7      switch_back_ret_pds
4804 
4805 sg_returns:
4806           short_return
4807 
4808 
4809 "^L
4810 " BEGIN MESSAGE DOCUMENTATION
4811 
4812 " Message:
4813 " pxss: notify time out: event=ZZZZZZZZZZZZ, pid=XXXXXXXXXXXX
4814 
4815 " S:      $info
4816 
4817 " T:      $run
4818 
4819 " M:      A hardcore event has not occurred within a reasonable time.
4820 " This may be due to hardware problems
4821 " or to a programming error.
4822 " The system attempts to continue operation.
4823 
4824 " A:      If this message persists, contact system programmers.
4825 
4826 
4827 " Message:
4828 " pxss: notify time out:  event=ZZZZZZZZZZZZ. During init/shutdown.
4829 
4830 " S:      $info
4831 
4832 " T:      $init
4833 
4834 " M:      A hardcore event has not occurred within a reasonable time
4835 " during system initialization or shutdown.  This may be due to hardware
4836 " problems or to a programming error.  The system attempts to continue
4837 " initialization or shutdown.
4838 
4839 " A:      If this message persists, contact system programmers.
4840 
4841 
4842 " Message:
4843 " pxss: System default procs required reset to ABCDEFGH
4844 
4845 " S:      $beep
4846 
4847 " T:      During CPU deconfiguration.
4848 
4849 " M:      Due to the deletion of a CPU, there were no online CPUs
4850 " remaining in the default set of CPUs.  These CPUs are the only CPUs
4851 " on which processes can run which have not requested to be run on
4852 " specific CPUs. The default set of CPUs has been changed to all
4853 " online CPUs.
4854 
4855 " A:      $inform_sa
4856 
4857 " Message:
4858 " pxss: APTE not locked
4859 "
4860 " S:      $crash
4861 "
4862 " T:      $run
4863 "
4864 " M:      $err
4865 "
4866 " A:      $recover
4867 
4868 " Message:
4869 " pxss: APTE disdains all processors
4870 "
4871 " S:      $crash
4872 "
4873 " T:      $run
4874 "
4875 " M:      $err
4876 "         There are no processors-required set for this APTE.
4877 "
4878 " A:      $recover
4879 
4880 " Message:
4881 " pxss: No term_processid
4882 "
4883 " S:      $crash
4884 "
4885 " T:      $run
4886 "
4887 " M:      $err
4888 "         As a process was about to indicate its demise to the master process,
4889 "         it discovered, to its chagrin, that it had forgotten who that was.
4890 "
4891 " A:      $recover
4892 
4893 " Message:
4894 " pxss: Stop returned from getwork
4895 "
4896 " S:      $crash
4897 "
4898 " T:      $run
4899 "
4900 " M:      $err
4901 "
4902 " A:      $recover
4903 
4904 " Message:
4905 " pxss: sprq already on prds
4906 "
4907 " S:      $crash
4908 "
4909 " T:      $run
4910 "
4911 " M:      $err
4912 "
4913 " A:      $recover
4914 
4915 " Message:
4916 " pxss: empty_t APTE not stopped or empty
4917 "
4918 " S:      $crash
4919 "
4920 " T:      $run
4921 "
4922 " M:      $err
4923 "         an attempt was made to clear an APTE that of a process that was neither
4924 "         stopped nor empty.
4925 "
4926 " A:      $recover
4927 
4928 " Message:
4929 " pxss: APT not locked
4930 "
4931 " S:      $crash
4932 "
4933 " T:      $run
4934 "
4935 " M:      $err
4936 "
4937 " A:      $recover
4938 
4939 " Message:
4940 " pxss: unthread null back ptr
4941 "
4942 " S:      $crash
4943 "
4944 " T:      $run
4945 "
4946 " M:      $err
4947 "
4948 " A:      $recover
4949 
4950 " Message:
4951 " pxss: unthread prev.fp ^= cur
4952 "
4953 " S:      $crash
4954 "
4955 " T:      $run
4956 "
4957 " M:      $err
4958 "
4959 " A:      $recover
4960 
4961 " Message:
4962 " pxss: unthread null cur.fp
4963 "
4964 " S:      $crash
4965 "
4966 " T:      $run
4967 "
4968 " M:      $err
4969 "
4970 " A:      $recover
4971 
4972 " Message:
4973 " pxss: unlock apt read lock bad count
4974 "
4975 " S:      $crash
4976 "
4977 " T:      $run
4978 "
4979 " M:      $err
4980 "
4981 " A:      $recover
4982 
4983 " Message:
4984 " pxss: write_to_read bad lock count
4985 "
4986 " S:      $crash
4987 "
4988 " T:      $run
4989 "
4990 " M:      $err
4991 "
4992 " A:      $recover
4993 
4994 " Message:
4995 " pxss: write_to_read ldac failed
4996 "
4997 " S:      $crash
4998 "
4999 " T:      $run
5000 "
5001 " M:      $err
5002 "         This indicates a hardware error.
5003 "
5004 " A:      $recover
5005 
5006 " Message:
5007 " pxss: UNLOCK_bp not locked
5008 "
5009 " S:      $crash
5010 "
5011 " T:      $run
5012 "
5013 " M:      $err
5014 "
5015 " A:      $recover
5016 
5017 " Message:
5018 " pxss: UNLOCK_X2 not locked
5019 "
5020 " S:      $crash
5021 "
5022 " T:      $run
5023 "
5024 " M:      $err
5025 "
5026 " A:      $recover
5027 
5028 " Message:
5029 " pxss: UNLOCK_x3 not locked
5030 "
5031 " S:      $crash
5032 "
5033 " T:      $run
5034 "
5035 " M:      $err
5036 "
5037 " A:      $recover
5038 
5039 " Message:
5040 " pxss: subroutine_save stack overflow
5041 "
5042 " S:      $crash
5043 "
5044 " T:      $run
5045 "
5046 " M:      $err
5047 "
5048 " A:      $recover
5049 
5050 " Message:
5051 " pxss: ITT overflows
5052 "
5053 " S:      $crash
5054 "
5055 " T:      $run
5056 "
5057 " M:      $err
5058 "
5059 " A:      $recover
5060 
5061 " Message:
5062 " pxss: untenable empty APTE
5063 "
5064 " S:      $crash
5065 "
5066 " T:      $run
5067 "
5068 " M:      $err
5069 "
5070 " A:      $recover
5071 
5072 " Message:
5073 " pxss: untenable blocked APTE
5074 "
5075 " S:      $crash
5076 "
5077 " T:      $run
5078 "
5079 " M:      $err
5080 "
5081 " A:      $recover
5082 
5083 " Message:
5084 " pxss: untenable stopped APTE
5085 "
5086 " S:      $crash
5087 "
5088 " T:      $run
5089 "
5090 " M:      $err
5091 "
5092 " A:      $recover
5093 
5094 " Message:
5095 " pxss: thread_him_in already threaded
5096 "
5097 " S:      $crash
5098 "
5099 " T:      $run
5100 "
5101 " M:      $err
5102 "
5103 " A:      $recover
5104 
5105 " Message:
5106 " pxss: thread_him_in x1 zero
5107 "
5108 " S:      $crash
5109 "
5110 " T:      $run
5111 "
5112 " M:      $err
5113 "
5114 " A:      $recover
5115 
5116 " Message:
5117 " pxss: thread_him_in x4 zero
5118 "
5119 " S:      $crash
5120 "
5121 " T:      $run
5122 "
5123 " M:      $err
5124 "
5125 " A:      $recover
5126 
5127 " Message:
5128 " pxss: thread_him_in x4->apte.fp ^= x1
5129 "
5130 " S:      $crash
5131 "
5132 " T:      $run
5133 "
5134 " M:      $err
5135 "
5136 " A:      $recover
5137 
5138 " Message:
5139 " pxss: apte.state ^= ready
5140 "
5141 " S:      $crash
5142 "
5143 " T:      $run
5144 "
5145 " M:      $err
5146 "
5147 " A:      $recover
5148 
5149 " Message:
5150 " pxss: thread_him_in x0 zero
5151 "
5152 " S:      $crash
5153 "
5154 " T:      $run
5155 "
5156 " M:      $err
5157 "
5158 " A:      $recover
5159 
5160 " Message:
5161 " pxss: no available stack_0
5162 "
5163 " S:      $crash
5164 "
5165 " T:      $run
5166 "
5167 " M:      $err
5168 "
5169 " A:      $recover
5170 
5171 " Message:
5172 " pxss: stack_0 page 0 wired
5173 "
5174 " S:      $crash
5175 "
5176 " T:      $run
5177 "
5178 " M:      $err
5179 "         process loading was about to wire the first page of the ring 0 stack when
5180 "         it discovered that it had been beaten to the punch.
5181 "
5182 " A:      $recover
5183 
5184 " Message:
5185 " pxss: no stack_0 sdw
5186 "
5187 " S:      $crash
5188 "
5189 " T:      $run
5190 "
5191 " M:      $err
5192 "
5193 " A:      $recover
5194 
5195 " Message:
5196 " pxss: freeing unknown stack_0
5197 "
5198 " S:      $crash
5199 "
5200 " T:      $run
5201 "
5202 " M:      $err
5203 "         the stack_0 being returned could not be found in the list of stack_0s.
5204 "
5205 " A:      $recover
5206 
5207 " Message:
5208 " pxss: mylock on stack queue
5209 "
5210 " S:      $crash
5211 "
5212 " T:      $run
5213 "
5214 " M:      $err
5215 "
5216 " A:      $recover
5217 
5218 " Message:
5219 " pxss: lock_stack_queue stac failed
5220 "
5221 " S:      $crash
5222 "
5223 " T:      $run
5224 "
5225 " M:      $err
5226 "         This indicates a hardware error.
5227 "
5228 " A:      $recover
5229 
5230 " Message:
5231 " pxss: unlock_stack_queue not my lock
5232 "
5233 " S:      $crash
5234 "
5235 " T:      $run
5236 "
5237 " M:      $err
5238 "
5239 " A:      $recover
5240 
5241 " Message:
5242 " pxss: unlock_stack_queue stacq failed
5243 "
5244 " S:      $crash
5245 "
5246 " T:      $run
5247 "
5248 " M:      $err
5249 "         This indicates a hardware error.
5250 "
5251 " A:      $recover
5252 
5253 " END MESSAGE DOCUMENTATION
5254 
5255           end