1 * ***********************************************************
   2 * *                                                         *
   3 * * Copyright, (C) Honeywell Information Systems Inc., 1982 *
   4 * *                                                         *
   5 * * Copyright (c) 1972 by Massachusetts Institute of        *
   6 * * Technology and Honeywell Information Systems, Inc.      *
   7 * *                                                         *
   8 * ***********************************************************
   9 
  10           lbl       ,scheduler
  11           ttl       multics/fnp scheduler and timer manager
  12           pcc       off
  13           pmc       off
  14           editp     on
  15 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  16 *
  17 *         scheduler, sked
  18 *
  19 *              This module is the scheduler and timer manager
  20 *         for the multics/fnp communications system (mcs). it
  21 *         handles all interrupts and dispatches routines to
  22 *         process them. it also will queue routines to be run as soon
  23 *         as possible or delay for some time before letting them run.
  24 *
  25 *              the timer manager handles the elapsed and interval
  26 *         timers, and includes mechanisms to support time outs
  27 *         for the control_tables and the delayed queueing for the
  28 *         scheduler.
  29 *
  30 *         modified and revised 11/18/74 by mike grady
  31 *         modified 79 jul 26 by art beattie to add support for
  32 *           dn6670 extended memory.
  33 *
  34 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  35           rem
  36           symdef    sked
  37           symdef    invp,mdisp,msdsp
  38           symdef    dspqur,secdsp
  39           symdef    g3wjt
  40           symdef    simclk
  41           symdef    setime
  42           symdef    etrip
  43           symdef    timrjt
  44           symdef    skdata    address of scheduler data
  45           symdef    etrmon    pointer to ic monitoring data
  46           symdef    etrint    elapsed timer interval
  47           symdef    idlmrk    address of one before start of idle loop
  48           symdef    idloop    address of start of idle loop
  49           symdef    idlend    address of end of idle loop
  50           symdef    idlint    idle metering interval (used by init)
  51           symdef    idlcnt    idle loop count (used by init)
  52           symdef    idlmax    idle loop maximum count (set by init)
  53           symdef    idlmin    idle loop minimum count (set by init)
  54           rem
  55           symref    trace
  56           symref    chkiv
  57           symref    hintr
  58           symref    dterm
  59           symref    dmail
  60           symref    lip
  61           symref    consol
  62           symref    tdip
  63           symref    getbuf
  64           symref    frelbf
  65           symref    itmout
  66           symref    icmon
  67           symref    gettib
  68           symref    setptw    set up variable cpu page table word
  69           rem
  70           rem
  71           pmc       save,on
  72           systm
  73           tib
  74           hwcm
  75           comreg
  76           pmc       restore
  77           ttls      symbol definitions
  78           rem     dsptab symbol definitions
  79           rem
  80 crtwd     equ       0         control word
  81 prent     equ       1         primary entry point
  82 scent     equ       2         secondary entry point
  83 rqcnt     equ       3         request count
  84           rem
  85           rem                     where the control word has the following
  86           rem                     format:
  87           rem
  88           rem            bit  - 0   ** request bit
  89           rem                   1   ** execution bit
  90           rem                   2   ** secondary entry pt. present
  91           rem                 3-17  ** suppression bits
  92           rem
  93           rem
  94           rem     dattab symbol definitions
  95           rem
  96 stadd     equ       0         starting add. for list of data
  97 entcnt    equ       1         entry count
  98 excnt     equ       2         exit count
  99 msk       equ       3         count mask
 100           rem
 101           rem
 102           rem     dispatcher queuer symbol definitions
 103           rem
 104 dqlink    equ       0         link word
 105 dqrtn     equ       1         routine address
 106 dqx1      equ       2         x1 - passed to routine when run
 107 dqpri     equ       3         priority
 108           rem
 109 nmqlk     equ       10        number of permanent queue links
 110 nmdqlk    equ       20        number of permanent delay queue links
 111           rem
 112           rem     assigned locations in interrupt saver blocks
 113           rem
 114 intx1     equ       0         x1
 115 intx2     equ       1         x2
 116 intx3     equ       2         x3
 117 inta      equ       3         a reg.
 118 intq      equ       4         q reg.
 119 intir     equ       5         indicator reg.
 120 intic     equ       6         ic at interrupt
 121 intptw    equ       7         cpu ptw at interrupt
 122 intbpw    equ       8         buffering ptw at interrupt
 123           rem
 124           rem
 125           rem     miscellaneous
 126           rem
 127 bufsiz    equ       32
 128 dqlpb     equ       bufsiz/4  dispatcher links/buffer
 129           rem
 130 modtmr    equ       5
 131           rem
 132           rem        control word symbol definitions
 133           rem
 134 rqstbt    bool      400000    request bit
 135 exctbt    bool      200000    execute bit
 136 scdent    bool      100000    secondary entry present
 137 suprmk    bool      /rqstbt*/exctbt*/scdent       suppression mask
 138           rem
 139           rem        mask bits for jump table data
 140           rem
 141 iocmk     bool      740000    mask for ioc#
 142 clmmk     bool      30000     mask for clm#
 143 clmsmk    bool      7600      mask for clmsc#
 144 modmk     bool      77        mask for mod#
 145           rem
 146           rem       dispatcher priority definitions
 147           rem
 148 intpri    bool      7         priority of interpreter
 149 itpri     bool      4         interval timer priority
 150           rem
 151           base      8         temporary for debugging
 152           ttls      trace types and switches
 153           rem
 154 tt.int    equ       1         trace interrupts
 155 tt.idl    equ       2         trace idle time
 156 tt.run    equ       3         trace running of interrupt rtn
 157 tt.rst    equ       4         trace restart of interrupted routine
 158 tt.rnq    equ       5         trace running of queued routine
 159 tt.set    equ       6         trace set timer calls
 160 tt.itr    equ       7         trace interval timer runouts
 161 tt.que    equ       8         trace dspqur entries
 162           rem
 163           rem
 164 ts.int    bool      000002
 165 ts.skd    bool      000004
 166 ts.tim    bool      000010
 167           ttls      various scheduler macros
 168           rem
 169 mpy       macro     (multiplier location-*)
 170           mpf       #1
 171           lrl       1
 172           endm      mpy
 173           rem
 174           rem
 175 dvd       macro     (divisor location-*)
 176           qls       1
 177           dvf       #1
 178           endm      dvd
 179           rem
 180           rem
 181 dspm      macro
 182           oct       0
 183           zero      #1
 184           oct       0,0
 185           endm
 186           rem
 187           rem
 188 chkivs    macro
 189           tsy       2,*
 190           tra       2
 191           ind       chkiv
 192           endm      chkivs
 193           rem
 194           rem
 195 datm      macro
 196           pcc       save,off
 197           pmc       save,off
 198 offset    set       0
 199 count     set       0
 200           pmc       restore
 201 dattab    null
 202           idrp      #1
 203           zero      data+offset
 204           dec       0,0,#1
 205           pmc       save,off
 206 offset    set       offset+#1
 207 count     set       count+1
 208           pmc       restore
 209           idrp
 210           odd
 211 savtab    bss       10*count
 212           rem
 213 data      bss       offset
 214           pcc       restore
 215           endm
 216           eject
 217 cmpaq     macro
 218           crsm      off
 219           ife       '#2','',2
 220           cmpa      #1
 221           ife       1,2,1
 222           cmpa      #1,#2
 223           tnz       2
 224           ife       '#2','',2
 225           cmpq      #1+1
 226           ife       1,2,1
 227           cmpq      #1+1,#2
 228           crsm      on
 229           endm      cmpaq
 230           rem
 231           rem
 232 tblk      macro     (number of blocks to create)
 233 tcnt      set       #1-1
 234           dup       2,tcnt
 235           zero      *+2
 236           oct       0
 237           oct       0,0
 238           endm      tblk
 239           rem
 240           rem
 241 dlyblk    macro     (number of blocks to create)
 242 dcnt      set       #1-1
 243           dup       4,dcnt
 244           zero      *+6
 245           oct       0
 246           oct       0,0
 247           oct       0,0
 248           oct       0,0
 249           oct       0,0
 250           oct       0,0
 251           endm      dlyblk
 252           ttls      links macro
 253           rem
 254           rem            this macro is used to generate linked buffers.
 255           rem         the calling sequence is
 256           rem
 257           rem               links     n,l
 258           rem
 259           rem            n is the number of buffers to generate
 260           rem            l is the length of each buffer
 261           rem            the first word of each buffer points to the
 262           rem            first word of the next buffer.  the last
 263           rem            buffer has a pointer of zero
 264           rem
 265 links     macro
 266           pmc       save,off
 267           dup       2,#1-1
 268           zero      *+#2
 269           bss       #2-1
 270           zero      0
 271           bss       #2-1
 272           pmc       restore
 273           endm      links
 274           ttls      common area for invp, savreg and mdisp
 275           rem
 276 sked      null
 277           rem
 278           even
 279 indreg    oct                 indicator register save-store
 280 icreg     oct                 ic of the interrupt
 281 modsv     oct                 temporary save locations
 282 dtsv      oct                 x
 283 asv       oct                 x
 284 qsv       oct                 x
 285 x1sv      oct                 x
 286 zerow     oct                 a zero word (always)
 287 reqbt     vfd       18/rqstbt request bit
 288 excmsk    vfd       18/exctbt execute bit
 289 secmsk    vfd       18/scdent secondary entry present
 290 supmsk    vfd       18/suprmk suppression mask
 291 dstnum    oct                 number of interrupted module
 292           rem
 293 dspta     zero      dsptab    address of dsptab
 294 datta     zero      dattab    "     "  dattab
 295 savra     zero      savtab    address of savtab(must start on odd loc.)
 296 dspi      ind       dsptab,1  indirect word for dsptab
 297           rem
 298           rem                     at end of dsptab insert:
 299           rem                     dspsz     zero   *-dsptab
 300           rem
 301           rem
 302           start     sked,1
 303           ttls      interrupt vector processor
 304           rem
 305 ***********************************************************
 306 *
 307 *       invp
 308 *
 309 *            input
 310 *                 address of third word of jump table
 311 *               stored in invp.
 312 *
 313 *                  format of jump table:
 314 *
 315 *                1  -  zero        (ic at interrupt)
 316 *                2  -  tsy        invp-*
 317 *                3  -  ioc#,  clm#,  clmsc#,  mod#
 318 *
 319 *              bit #    4  ,   2  ,    5   ,   7
 320 *
 321 ***********************************************************
 322 invp      zero                add. of third word of jump table
 323           sti       indreg-*  save indicator register
 324           inh                 inhibit on
 325           staq      asv-*     temp. save a register
 326           stx1      x1sv-*    and x1 register
 327           rem
 328 *      chkivs
 329           rem
 330           ldx1      invp-*
 331           lda       0,1       have ioc#,clmx#,clmsc#,mod#
 332           sta       dtsv-*    save for later
 333           ldx1      -2,1      have ic at interrupt
 334           stx1      icreg-*   save it
 335           rem
 336           iana      modmk     mask out all but mod#
 337           iaa       -1        subtract 1 from mod#
 338           als       2         mult. mod# by 4
 339           sta       modsv-*   save it
 340           rem
 341           ada       dspta-*   find right place in dsptab
 342           cax1                have dsptab add. + 4 x mod#
 343           rem
 344           lda       reqbt-*
 345           orsa      crtwd,1   set request bit on for this mod
 346           aos       rqcnt,1   add 1 to request count
 347           rem
 348           ldx1      datta-*
 349           adcx1     modsv-*   have dattab add. + 4 x mod#
 350           lda       entcnt,1  entry count
 351           cmpa      msk,1     compare to que size
 352           tmi       invp5-*   ok
 353           rem
 354           stz       entcnt,1  reset
 355           ila       0         this too
 356           rem
 357 invp5     ada       stadd,1   address of list + entry count
 358           aos       entcnt,1  add 1 to entry count
 359           cax1
 360           lda       dtsv-*    get the saved data
 361           sta       0,1       store it
 362           rem
 363           rem        if requested, trace (1) the ic at the interrupt
 364           rem       and (2) the third word of the jump table.
 365           rem
 366           trace     tt.int,ts.int,(icreg,dtsv)
 367           rem
 368           rem       m a s t e r   s a v e r
 369           rem
 370           lda       dstnum-*  get mod#
 371           tze       msdsp-*   were in the dispatcher on the interrupt
 372           rem
 373           iaa       -1        mod# is one more than position in dsptab
 374           mpy       (l.a001-*)          mult. mod# by 10
 375           cqa
 376           cax1
 377           adcx1     savra-*   savtab + 10 x mod#
 378           ldaq      asv-*     get original contents of aq
 379           stx2      intx2,1   store x2
 380           ldx2      x1sv-*    get orig. contents of x1
 381           stx2      intx1,1
 382           stx3      intx3,1
 383           staq      inta,1
 384           ldaq      indreg-*  get indicator and ic
 385           staq      intir,1   store indicator and ic
 386           lda       a.a001-*,*          (.crpte,*) get current page table entry
 387           sta       intptw,1  store page table entry
 388           lda       a.a002-*,*          (.crbpe,*) likewise buffer pte
 389           sta       intbpw,1
 390           rem
 391           tra       msdsp-*   go to master dispatcher
 392           rem
 393           rem
 394 a.a001    ind       .crpte,*  variable cpu page table entry
 395 a.a002    ind       .crbpe,*
 396           rem
 397 l.a001    dec       10
 398           ttls      m a s t e r   d i s p a t c h e r
 399           rem
 400           rem     entry on completion of dispatched routine
 401           rem
 402 mdisp     null
 403           inh                 inhibit on
 404           lda       dstnum-*  get mod#
 405           iaa       -1        subtract one
 406           als       2         mult. by 4
 407           cax1
 408           adcx1     dspta-*   dsptab address + 4 x mod#
 409           lda       excmsk-*  execute mask
 410           ersa      crtwd,1   turn off execute mask
 411           rem
 412           rem     normal entry point from master saver
 413           rem
 414 msdsp     null
 415           stz       dstnum-*  set to 0 - are in master dispatcher
 416           eni                 allow interrupts
 417 *      chkivs
 418           nop
 419           nop
 420           rem
 421 msds5     ldx1      zerow-*   zero x1
 422           rem
 423 msrch     null
 424           lda       dspi-*,*  examine dsptab (control words)
 425           tze       nxmd-*    nothing on at all
 426           rem
 427           cana      excmsk-*  was mod interrupted?
 428           tnz       hvint-*   yes
 429           rem
 430           cana      supmsk-*  is it suppressed?
 431           tnz       nxmd-*    yes - continue search
 432           rem
 433           cana      reqbt-*   is it requested?
 434           tnz       hvreq-*   yes
 435           rem
 436 nxmd      iacx1     4         increment x1 by 4
 437           cmpx1     dspsz-*   are we at the end of table ??
 438           tnz       msrch-*   no
 439           rem
 440           ttls      idle routine
 441           rem
 442           rem       trace state at start of idle
 443           rem
 444           rier                read interrupt enable registers
 445           sta       tcrier-*  save for use in trace
 446           sti       tcint-*   save indicators register
 447           rem
 448 *         trace     tt.idl,ts.int,(tcint,tcrier)
 449           rem
 450           nop
 451 idlmrk    nop
 452 **********************************************************************
 453 *
 454 *         idle loop increments a counter continuously, which permits
 455 *         metering of idle time by comparing counter to value to its
 456 *         maximum value (which is established during initialization by
 457 *         running the idle loop for a second)
 458 *
 459 **********************************************************************
 460           rem
 461 idloop    ila       0         get a doubleword 1
 462           ilq       1
 463           inh                 have to protect load/store sequence
 464           adaq      idlcnt-*  increment counter
 465           staq      idlcnt-*
 466           eni                 ok
 467           tra       idloop-*  go around again until interrupted
 468 idlend    null                so icmon can locate idle loop
 469           rem
 470           even
 471 idlcnt    bss       2
 472 tcint     bss       1
 473 tcrier    bss       1
 474           ttls      run the requested routine
 475           rem
 476 hvreq     cx1a                get the dsptab offset
 477           ars       2         divide by 4
 478           iaa       1         increment by 1
 479           rem
 480           inh                 inhibit
 481           sta       dstnum-*  set dstnum to mod# (1,2,3,,,)
 482           adcx1     dspta-*   address of dsptab + c(x1)
 483           ila       -1
 484           asa       rqcnt,1   subtract 1 from rqcnt
 485           tnz       hv1-*     did request count go to zero?
 486           rem
 487           lda       reqbt-*   yes -- set request bit to 0
 488           ersa      crtwd,1
 489           rem
 490 hv1       lda       excmsk-*  set execute bit
 491           orsa      crtwd,1
 492           rem
 493 *         chkivs
 494           rem
 495 *         trace     tt.run,ts.int,(prent(1))
 496           rem
 497           ldi       zerow-*   initialize the indicator register
 498           tra       prent,1*  go to routine
 499           ttls      return to interrupted module
 500           rem
 501           rem     module was interrupted:  restore registers and
 502           rem     transfer to point of interrupt or secondary
 503           rem     entry point if present.
 504           rem
 505 hvint     stx1      x1sv-*    save for awhile
 506           stz       hvsec-*   initialize
 507           cana      secmsk-*  is there a secondary entry point?
 508           tze       noscp-*   no
 509           rem
 510           aos       hvsec-*   have a secondary entry
 511           adcx1     dspta-*   have desired 4 word block in dsptab
 512           ldx2      scent,1   get secondary entry point
 513           rem
 514 noscp     lda       x1sv-*    get the dsptab offset again
 515           ars       2         divide by 4 to module offset
 516           mpy       (l.a001-*)          multiply by 10
 517           cqa
 518           cax1                for use in accessing savtab
 519           adcx1     savra-*   desired block in savtab
 520           lda       x1sv-*    recover dsptab offset once more
 521           ars       2         convert to module offset
 522           iaa       1         add 1, have mod# (1,2,3...)
 523           rem
 524           szn       hvsec-*   did we find secondary entry?
 525           tze       ictr-*    no
 526           rem
 527           ldx3      intic,1   yes - get ic at interrupt
 528           stx3      0,2       store as first word of secondary routine
 529           iacx2     1
 530           tra       ictr5-*
 531           rem
 532 ictr      ldx2      intic,1   ic at interrupt
 533           rem
 534 ictr5     stx2      icreg-*   store for transfer
 535           cax2                mod# in x2
 536           rem
 537 *         trace     tt.rst,tt.int,(icreg)
 538           rem
 539           ldx3      intx3,1   restore registers -- x3
 540           lda       intir,1   get indicator register
 541           sta       indreg-*  save
 542           lda       intptw,1  restore page table word
 543           sta       a.a001-*,*          (.crpte,*)
 544           lda       intbpw,1  and buffer page table word
 545           sta       a.a002-*,*          (.crbpe,*)
 546           rem
 547           ldaq      inta,1    restore a and q reg.
 548           inh
 549           stx2      dstnum-*  set dstnum to mod#
 550           ldx2      intx2,1   restore x2
 551           ldx1      intx1,1   and x1
 552           rem
 553           rem
 554           ldi       indreg-*  load indicator reg.
 555           tra       icreg-*,* restart the interrupted routine
 556           rem
 557           rem
 558 hvsec     bss       1         indicates whether we have secondary entry
 559           ttls      master dispatcher tables
 560           rem
 561           pmc       save,on
 562           even
 563 dsptab    null
 564           dspm      lip       lsla_man, module 1
 565           dspm      dterm     dia_man terminate, module 2
 566           dspm      dmail     dia_man special, module 3
 567           dspm      hintr     hsla_man, module 4
 568           dspm      itrout    timer_manager, module 5
 569           dspm      consol    console_man, module 6
 570           dspm      tdip      colts (t&d), module 7
 571 scdspa    vfd       18/scdent
 572           zero      secdsp
 573           zero      intsv
 574           oct       0
 575           rem
 576 dspsz     zero      *-dsptab
 577           eject
 578           datm      (8,2,8,8,2,3,2,1)
 579           pmc       restore
 580           odd
 581 grph      bss       10
 582 grpm      bss       10
 583 grpl      bss       10
 584           rem
 585           ttls      retrieve jump table data
 586           rem
 587 *******************************************************
 588 *
 589 *         g3wjt
 590 *                 load q register with saved third word
 591 *                 of jump table and set up registers
 592 *                 x2 and x3 as shown:
 593 *
 594 *               x2 - software communication region
 595 *               x3 - hardware communication region
 596 *
 597 *         calling sequence -
 598 *
 599 *                           tsy      g3wjt-*
 600 *                           return
 601 *
 602 *********************************************************
 603           rem
 604 g3wjt     subr      g3w,(inh)
 605           rem
 606           lda       a.c001-*,*          (=dstnum) get mod number of him
 607           iaa       -1        subtract one
 608           als       2         mult. by 4
 609           ada       a.c002-*  (=dattab) have respective 4 word block
 610           cax1                in dattab
 611           rem
 612           ldx2      excnt,1   exit count
 613           cmpx2     msk,1     compare to length of que
 614           tnz       g3wjt5-*  ok
 615           rem
 616           stz       excnt,1   reset it
 617           ldx2      excnt,1   zero  x2 also
 618           rem
 619 g3wjt5    adcx2     stadd,1   address of list + exit count
 620           aos       excnt,1   increment exit count
 621           ldq       0,2       data (ioc#,clm#,clmsc#,mod#)
 622           cqa
 623           ana       l.c001-*  (=037600) mask out clm# and clmsc#
 624           ars       3         convert to relative address
 625           cax3                x3 - hardware communication region
 626           ldx2      h.sfcm,3  x2 - software communication region
 627           rem
 628           return    g3wjt     return to caller
 629           rem
 630 l.c001    oct       37600     mask for clm# and subchannel #
 631           rem
 632 a.c001    zero      dstnum    pointer to interupted module number
 633 a.c002    zero      dattab    pointer to dattab
 634           ttls      dispatcher queuer
 635           rem
 636 ********************************************************************
 637 *
 638 * dspqur
 639 *      inputs
 640 *             ar  --  time delay/priority
 641 *             qr  --  routine name
 642 *             x1  --  passed to routine when run
 643 *      outputs
 644 *             none
 645 *       registers altered - a,q
 646 *
 647 **********************************************************************
 648           rem
 649 dspqur    subr      qur,(a,q,x1,x2,x3,inh)
 650           rem
 651 *         trace     tt.que,ts.skd,(qursa,qursq,x1)
 652           rem
 653           lda       qursa-*
 654           ldq       qursq-*   restore a and q
 655           icana     -64       (777700) entry for delayed queuer?
 656           tnz       delayq-*  yes
 657           rem
 658           ldx2      lnkptr-*  get link from available chain
 659           tnz       dspq2-*   unless chain is exhausted
 660           tsy       a.d010-*,*          (=getqlk) get and format a new block
 661           ind       lnkchn
 662           rem
 663 dspq2     sta       dqpri,2   store priority into link
 664           stq       dqrtn,2   store routine into link
 665           stx1      dqx1,2    store x1 into link
 666           ldq       dqlink,2  detatch link from remainder of
 667           stq       lnkptr-*  availible chain
 668           rem
 669           ldq       a.d001-*  (=dque) get address of pointer
 670           stq       dtmp1-*   to dispatcher queue chain
 671           rem
 672           ldx3      dque-*    get start of chain
 673           tnz       dspq6-*   good chain, start search
 674           rem
 675           stz       dqlink,2  make link end of chain
 676           tra       dspq12-*
 677           rem
 678 dspq6     cmpa      dqpri,3   search chain until lower priority
 679           tnc       dspq10-*  is found
 680           stx3      dtmp1-*   not yet - save previous link
 681           ldx3      dqlink,3  get next
 682           tnz       dspq6-*   test for end of chain
 683           eject
 684 dspq10    stx3      dqlink,2  put the foward pointer into new link
 685           rem
 686 dspq12    stx2      dtmp1-*,* make previous link point at new one
 687           ldx2      a.d002-*  get address of secondary disp. block
 688           rem
 689           lda       l.d001-*  (=rqstbt) get request bit
 690           orsa      crtwd,2   set request bit on for secondary disp.
 691           ila       1
 692           sta       rqcnt,2   set request count to one
 693           rem
 694 dspq20    null
 695           return    dspqur    return to caller
 696           rem
 697 dtmp1     oct       0         temp for workspace
 698           rem
 699 dque      zero      0         pointer to the dispatcher que chain
 700           rem
 701           rem
 702 lnkchn    ind       0         extra buffer chain
 703           ind       nmqlk     number of permanent links
 704           ind       0         number of calls on getqlk
 705 lnkptr    ind       *+1       pointer to available link chain
 706           links     nmqlk,4   generate permanent links
 707           rem
 708 a.d001    ind       dque
 709 a.d002    ind       scdspa
 710 a.d010    ind       getqlk
 711           rem
 712 l.d001    vfd       18/rqstbt
 713           ttls      delayq -- time delay queuer routine
 714 ************************************************************************
 715 * the function of this routine is identical to the normal queuer
 716 * routine "dspqur" with the following single exception --
 717 *
 718 *      the routine to be queued will be queued only after
 719 *      the specified time interval has elapsed.
 720 *
 721 * the calling sequence is also identical to that of the normal queuer
 722 * except that bits 0-11 of the accumulator are non-zero and represent
 723 * the desired time delay before the routine is actually queued.
 724 *
 725 * inputs--
 726 *      ar(00-11)= desired time delay, in seconds
 727 *      ar(12-17)= priority
 728 *      qr      = routine address
 729 *      x1      = will be passed to routine when run
 730 *
 731 * outputs -- none
 732 *
 733 ************************************************************************
 734           rem
 735 delayq    null                transfered to by dspqur
 736           rem
 737           sel       tmch      select timer channel
 738           cioc      a.e006-*,*          (=mskpcw) mask the interval timer
 739           rem
 740           lda       a.e003-*,*          (=itmb) get the timer value
 741           sta       dtimer+1-*          save it
 742           rem
 743           ldaq      a.e004-*,*          (=simclk) get the simulated clock
 744           sbaq      dtimer-*  get the current time
 745           staq      curtim-*  and save it away
 746           rem
 747           ldx3      dfree-*   get ptr to free chain
 748           tnz       2         all ok
 749           die       1         no more delay queue buffers
 750           rem
 751           lda       dfwd,3    get fwd ptr from first blk
 752           sta       dfree-*   put into free ptr, taking blk
 753           rem
 754           lda       qursa-*   restore a reg
 755           iana      63        leave priority
 756           sta       dpri,3    put into block
 757           lda       qursq-*   get the routine addr
 758           sta       drtn,3    save in block
 759           ldx1      qursx1-*  get the value of x1
 760           stx1      dx1,3     save in block, also
 761           lda       qursa-*   get time value
 762           ars       6         shift down
 763           mpy       l.e002-*  (=1000) in to milliseconds
 764           adaq      curtim-*  add in current time
 765           staq      dtime,3   and put into block
 766           staq      ntime-*   save local copy
 767           rem
 768           stx3      dnew-*    save addr of new block
 769           lda       a.e005-*  (=dnext) get addr of next ptr
 770           sta       dlasta-*  save it also
 771           rem
 772           ldx3      dnext-*   get the next ptr, head of chain
 773           tze       dqr020-*  no chain, start one
 774           rem
 775 dqr010    ldaq      ntime-*   get the new time
 776           cmpaq     dtime,3   is ntime < dtime?
 777           tnc       dqr020-*  yes, chain in here
 778           rem
 779           stx3      dlasta-*  save addr of this block
 780           ldx3      dfwd,3    bump to next block
 781           tnz       dqr010-*  loop for more
 782           rem
 783           ldx3      dnew-*    get ptr to new block
 784           stx3      dlasta-*,*          store into fwd of last block
 785           stz       dfwd,3    zero fwd ptr, end of chain
 786           tra       dqr030-*  all done
 787           rem
 788 dqr020    cx3a                save addr of current block
 789           ldx3      dnew-*    get addr of new block
 790           stx3      dlasta-*,*          put into last block fwd ptr
 791           sta       dfwd,3    chain ahead to next block
 792           rem
 793 dqr030    szn       a.e009-*,*          (=itrint) has interval timer run out?
 794           tnz       dqr060-*  yes, all done, will be set later
 795           rem
 796           ldx3      dnext-*   get ptr to first block
 797           szn       a.e008-*,*          (=runing) is the clock runing?
 798           tze       dqr032-*  no, just start it
 799           rem
 800           ldaq      a.e004-*,*          (=simclk) get the simclk
 801           cmpaq     dtime,3   is simclk < dtime?
 802           tnc       dqr050-*  yes, go start clock
 803           rem
 804 dqr032    ldaq      dtime,3   get the time in block
 805           sbaq      curtim-*  subtract current time, leaving interval
 806           tnz       dqr035-*  zero interval, bad
 807           rem
 808           ila       0         set to very small one
 809           ilq       1         like 1 or so
 810           tra       dqr040-*  done
 811           rem
 812 dqr035    iaa       0         set the indicators
 813           tze       dqr040-*  less than max, set clock
 814           rem
 815           ila       1         get the max value for clock
 816           ilq       0         into the aq
 817           rem
 818 dqr040    stq       a.e003-*,*          (=itmb) set the interval timer
 819           adaq      curtim-*  get the new simclk time
 820           staq      a.e004-*,*          (=simclk) and save it
 821           rem
 822 dqr050    sel       tmch      select the timer channel
 823           cioc      a.e007-*,*          (=runpcw) start the timer
 824           aos       a.e008-*,*          (=runing) it is running now
 825           rem
 826 dqr060    tra       dspq20-*  restore registers and return
 827           rem
 828           rem
 829           even
 830 dtimer    oct       0,0       interval timer value
 831 curtim    oct       0,0       current time
 832 ntime     oct       0,0       new time for new block
 833           rem
 834 dnext     oct       0         ptr to chain of active blocks
 835 dfree     ind       dlyque    ptr to chain of free blocks
 836           rem
 837 dlyque    dlyblk    nmdqlk
 838           rem
 839 dlasta    oct       0
 840 dnew      oct       0
 841           rem
 842           rem
 843 a.e003    ind       itmb
 844 a.e004    ind       simclk
 845 a.e005    ind       dnext
 846 a.e006    ind       mskpcw
 847 a.e007    ind       runpcw
 848 a.e008    ind       runing
 849 a.e009    ind       itrint
 850 a.e012    ind       frelbf
 851           rem
 852 l.e002    dec       1000
 853           rem
 854           rem       equates for a delay queue block
 855           rem
 856 dfwd      equ       0
 857 drtn      equ       1
 858 dtime     equ       2
 859 dx1       equ       4
 860 dpri      equ       5
 861           ttls      emergency queue link routines
 862           rem
 863 ************************************************************
 864 * the function of this subroutine is to fetch and format
 865 * buffers needed by the normal queuer.  the address of
 866 * the first word of the new link chain is returned
 867 * in x2 on exit.
 868 ************************************************************
 869           rem
 870 getqlk    subr      sub,(a,q)
 871           rem
 872           ilq       bufsiz    set size of buffer desired
 873           tsy       a.i004-*,*          (=getbuf) get a buffer
 874           die       1         ** error - no more buffers  **
 875           ldx2      getqlk-*,*          get pointer to link control words
 876           aos       2,2       increment call count
 877           lda       0,2       get the extended chain
 878           sta       0,3       link it to the new buffer
 879           stx3      0,2       set new chain pointer
 880           iacx3     4         compute first link address
 881           cx3a                save link address in x2
 882           cax2
 883           ilq       dqlpb-2   number of links to link
 884           rem
 885 get010    iacx3     4         move to next link
 886           stx3      -4,3      save new pointer in link
 887           iaq       -1        bump loop control counter
 888           tnz       get010-*  process next unless done
 889           rem
 890           stz       0,3       yes, reset last link pointer to zero
 891           aos       getqlk-*  increment return address
 892           rem
 893           return    getqlk    return to caller
 894           eject
 895           rem
 896 ************************************************************
 897 * this routine returns to available space the
 898 * buffers used by the queuer routines
 899 ************************************************************
 900           rem
 901 relqlk    subr      rel,(x1,x2,x3,inh)
 902           rem
 903           ldx1      relqlk-*,*          get pointer to link control words
 904           ldq       1,1       get number of permanent links
 905           iaq       -1
 906           cx1a
 907           iaa       4         compute address of first link
 908           sta       3,1       set new link chain pointer
 909           cax2
 910           rem
 911 rel010    iacx2     4         step address to next link
 912           stx2      -4,2      link it to previous link
 913           iaq       -1        decrement link count
 914           tnz       rel010-*  process next unless done
 915           rem
 916           stz       0,2       zero last link pointer
 917           lda       0,1       get the buffer chain
 918           stz       0,1       clear pointer to it
 919           tsy       a.e012-*,*          (=frelbf) release the chain
 920           rem
 921           aos       relqlk-*  increment return address
 922           rem
 923           return    relqlk    return to caller
 924           ttls      e v e n t   d i s p a t c h e r
 925           rem
 926 *************************************************************
 927 *
 928 *           purpose - dispatch routines from a queued list
 929 *
 930 *           calling sequence -   tra   secdsp-*
 931 *
 932 *                  input
 933 *                         dque - points to top of
 934 *                                  queued chain
 935 *                         dlink - points to avail. chain
 936 *                         prdrt - set to minus one
 937 *
 938 *                  output
 939 *                         x1 - contains saved value
 940 *                         x3 - contains link address
 941 *                         prdrt - contains priority
 942 *                                    shifted 3 right
 943 *
 944 *************************************************************
 945           rem
 946 secdsp    null
 947           rem
 948 *      chkivs
 949           rem
 950           inh                 inhibit on
 951           ila       -1        set to minus
 952           sta       prdrt-*   in the disp. routine
 953           ldx3      a.h002-*,*          (=dque) get queue pointer
 954           tnz       dspr10-*  process next entry
 955           rem
 956           szn       a.h003-*,*          (=lnkchn) queue empty - any buffers to release
 957           tze       a.h001-*,*          no - return to master dispatcher
 958           tsy       relqlk-*  yes - release them
 959           ind       lnkchn
 960           tra       secdsp-*  process new entry in queue
 961           rem
 962 dspr10    lda       dqlink,3  get link address of first rtn queued
 963           sta       a.h002-*,*          (=dque) update queue pointer
 964           ldq       a.h004-*,*          (=lnkptr) pres. disp. routine pointer
 965           stq       dqlink,3  store in queue link
 966           stx3      a.h004-*,*          (=lnkptr) place on top of availible list
 967           lda       dqpri,3   get priority
 968           ars       3         shift right (0,1,2...)
 969           sta       prdrt-*
 970           rem
 971 *         trace     tt.rnq,ts.skd,(dqrtn(3))
 972           rem
 973           ila       pte.s     turn on security bit in ptws so any reference will
 974           orsa      a.h005-*,*          (.crpte,*) cause a store fault
 975           orsa      a.h006-*,*          (.crbpe,*)
 976           rem
 977           ldx1      dqx1,3    saved value in x1
 978           stx1      svx1-*    save for interrupt
 979           ldi       l.h001-*  (=0) initialize indicator register
 980           tra       dqrtn,3*  go execute
 981           rem
 982           rem
 983 prdrt     oct       400000
 984 svx1      zero
 985           rem
 986 a.h001    ind       mdisp
 987 a.h002    ind       dque
 988 a.h003    ind       lnkchn
 989 a.h004    ind       lnkptr
 990 a.h005    ind       .crpte,*  variable cpu page table entry
 991 a.h006    ind       .crbpe,*  buffering page table entry
 992           rem
 993 l.h001    oct       0
 994           rem
 995 pte.s     bool      100       page table entry security bit
 996           ttls      secondary level s a v e r
 997           rem
 998 ******************************************************************
 999 *
1000 *            purpose - save all registers of the interrupted
1001 *                      routine in the following block
1002 *                      format:
1003 *
1004 *                   note:  block must start at an
1005 *                          odd location
1006 *
1007 *                              word        contents
1008 *                               0            x1
1009 *                               1            x2
1010 *                               2            x3
1011 *                               3            a reg.
1012 *                               4            q reg.
1013 *                               5            ind. reg.
1014 *                               6            ic at interrupt
1015 *                               7            page table word
1016 *
1017 *
1018 *                    each priority group has its own 7 word
1019 *                    block.  after all saves; get interrupted
1020 *                    routine's priority, tib address and
1021 *                    queue.
1022 *
1023 ******************************************************************
1024           rem
1025 intsv     zero                will contain ic at interrupt on entry
1026           rem                     from master dispatcher
1027           sti       sv1-*     save ind. register
1028           inh                 inhibit on
1029           szn       prdrt-*   were we in dispatched routine?
1030           tmi       int020-*  no
1031           tnz       svrg-*    yes- save registers and queue
1032           rem
1033           ldi       sv1-*     priority is 0 -- skip queueing
1034           eni
1035           tra       intsv-*,* go to point of interrupt
1036           rem
1037 svrg      stx1      sv2-*     save registers in respective group
1038           ldx1      prdrt-*   get priority ( 0,1,2,...
1039           ldx1      a.i002-*,*          (=grptbl,1) load x1 with add. of group
1040           staq      inta,1    store a and q reg. in word 3 and 4
1041           stx2      intx2,1   "    x2 in word 1
1042           stx3      intx3,1   "    x3 "   "   2
1043           ldaq      sv1-*     load ind. reg. and x1 in aq
1044           sta       intir,1   indicator register
1045           stq       intx1,1   x1 saved in word 0
1046           lda       intsv-*   ic at interrupt
1047           sta       intic,1   save in block
1048           lda       a.h005-*,*          (.crpte,*) get current ptw
1049           sta       intptw,1  save page table word
1050           lda       a.h006-*,*          (.crbpe,*)
1051           sta       intbpw,1  and buffer ptw
1052           rem
1053           lda       prdrt-*   get priority
1054           rem
1055           als       3         reposition ( 0-7,10-17,...
1056           ldq       a.i003-*  (=restor) add. of restore routine
1057           ldx1      svx1-*    restore x1 for restorer
1058           tsy       a.i001-*,*          (=dspqur) call queuer
1059           rem
1060           eni
1061 int020    tra       secdsp-*  return to event dispatcher
1062           rem
1063           even
1064 sv1       oct       0         start at even location
1065 sv2       oct       0
1066           rem
1067 grptbl    zero      grph      points to priority group - h
1068           zero      grpm        "    "      "      "     m
1069           zero      grpl        "    "      "      "     l
1070           rem
1071 a.i001    ind       dspqur
1072 a.i002    ind       grptbl,1
1073 a.i003    ind       restor
1074 a.i004    ind       getbuf
1075           ttls      r e s t o r e r
1076           rem
1077 ******************************************************************
1078 *
1079 *            entered from the dispatcher.
1080 *             restores all registers and transfers to
1081 *             the interrupted routine via ic (word 6
1082 *             of block).
1083 *
1084 ******************************************************************
1085           rem
1086 restor    null
1087           inh
1088           ldx1      prdrt-*   get priority ( 0,1,2,..
1089           ldx1      a.i002-*,*          (=grptbl) load x1 with add. of chain
1090           ldaq      intir,1   load ind. reg. and ic at interrupt
1091           staq      sv1-*     store temp
1092           lda       intptw,1  restore page table entry
1093           sta       a.h005-*,*          (.crpte,*)
1094           lda       intbpw,1
1095           sta       a.h006-*,*          (.crbpe,*)
1096           rem
1097           ldaq      inta,1    restore a and q
1098           ldx2      intx2,1   restore x2
1099           ldx3      intx3,1   restore x3
1100           ldx1      intx1,1   restore x1
1101           ldi       sv1-*     restore indicator register
1102           tra       sv2-*,*   go finish it
1103           ttls      etrip -- elapsed timer rollover interrupt processor
1104 ************************************************************************
1105 * this routine is implemented directly from the interrupt vector.
1106 *
1107 * this routine handles elapsed timer runouts. it is responsible for idle
1108 * time metering and calling the instruction counter monitor if the latter
1109 * is enabled. the idle meter interval is established at initialization
1110 * time, and is normally one second. the ic monitor interval is dynamically
1111 * configurable, and is apt to be shorter.
1112 *
1113 * when this routine finds that the idle meter interval has expired, it
1114 * updates the running total of the idle loop counter so that user-ring
1115 * programs can determine an average idle time.
1116 *
1117 * the idle loop is run for one meter interval during initialization, to
1118 * establish a maximum value for the counter.
1119 ************************************************************************
1120           rem
1121 etrip     subr      etr,(inh,a,q)
1122           ldi       l.o001-*  (=024000o) inhibit overflow as well
1123           lda       etrprv-*  last setting of elapsed timer
1124           tze       etr035-*  this is first time, don't meter
1125           cmpa      idlint-*  was it a full idle time interval?
1126           tpl       etr010-*  yes, meter idle count
1127           ada       etrcum-*  no, has idle interval passed since we
1128           cmpa      idlint-*  last recorded it?
1129           tpl       etr010-*  yes, meter idle now
1130           sta       etrcum-*  no, update cumulative time
1131           tra       etr040-*  check for ic monitoring
1132           rem
1133 etr010    ldaq      a.o001-*,*          idlcnt
1134           cmpaq     idlmin-*  new minimum?
1135           tpl       etr020-*  no
1136           staq      idlmin-*  yes, store it
1137           tra       etr030-*  don't check for max
1138 etr020    cmpaq     idlmax-*  new maximum?
1139           tmi       etr030-*  no
1140           staq      idlmax-*  yes, record it
1141 etr030    adaq      idlcum-*  increment cumulative count
1142           staq      idlcum-*  save result
1143           ila       0         get a double-word 1
1144           ilq       1
1145           adaq      idlinc-*  to update count of idle meters
1146           staq      idlinc-*
1147 etr035    null                now zero the counter. note that a reg
1148           ilq       0         contains 0 no matter how we got here
1149           staq      a.o001-*,*          idlcnt
1150           stz       etrcum-*  starting new idle interval
1151           rem
1152 etr040    szn       etrmon-*  ic monitoring in effect?
1153           tze       etr050-*  no, skip it
1154           tsy       a.o002-*,*          (icmon) yes, call routine
1155 etr050    lda       etrint-*  new interval value
1156           sta       a.o003-*,*          (etmb) to elapsed timer mailbox
1157           iera      -1        convert to positive number
1158           iaa       1
1159           sta       etrprv-*  save for next time
1160           return    etrip
1161           rem
1162           rem
1163 etrprv    bss       1         most recent setting of elapsed timer
1164 etrcum    bss       1         time since last idle measurement
1165 idlint    dec       1000      default idle meter interval (1 second)
1166           rem
1167 l.o001    oct       024000    inhibit interrupts and overflow
1168           rem
1169 a.o001    ind       idlcnt    counter kept by idle loop
1170 a.o002    ind       icmon     address of ic monitoring routine
1171 a.o003    ind       etmb      address of elapsed timer
1172           rem
1173 *         the following data is pointed to .crskd in the comm region
1174 *         ring 4 multics software knows the format of this data
1175           rem
1176           even
1177 skdata    null
1178 idlcum    oct       0,0       cumulative value of idle counter
1179 idlinc    oct       0,0       count of increments to ildcum
1180 idlmax    oct       0,0       max value of counter
1181 idlmin    oct       0,0       min value of counter
1182 etrint    dec       -1000     interrupt every second (may be changed)
1183 etrmon    oct       0         address of data block in ic metering module
1184           rem                 (if configured)
1185           ttls      setime -- routine to set time-outs for tib lines
1186 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1187 *
1188 *         setime
1189 *
1190 *              setime is a routine called by the control tables
1191 *         via the interpreter to set time-outs for the various ttys
1192 *         so that the line can be prodded every so often to determine
1193 *         its state.
1194 *
1195 *         upon entry:
1196 *              x1 - virtual tib address for this line
1197 *              a - time to wait in seconds
1198 *                - or zero to reset a timer
1199 *
1200 *         returns:
1201 *              with a timer set to queue itmout when it goes off.
1202 *
1203 *         notes:
1204 *              If a timer is already running for the line it will
1205 *         just be reset to the new value.
1206 *
1207 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1208           rem
1209 setime    subr      set,(x1,x2,x3,a)
1210           rem
1211           sel       tmch      select the timer channel
1212           cioc      mskpcw-*  mask the timer now
1213           rem
1214           lda       a.h005-*,*          (.crpte,*) get current cpu page table entry
1215           sta       savpte-*  save it for return
1216           rem
1217           lda       t.line,1  get the line number
1218           tsy       a.l002-*,*          (gettib) get real tib address
1219           sta       strtib-*  save it for trace call
1220           rem
1221           trace     tt.set,ts.tim,(setsa,strtib)
1222           rem
1223           lda       a.l007-*,*          (=itmb) get the value of the interval timer
1224           sta       itimer+1-*          store it away
1225           rem
1226           ldaq      simclk-*  get the simulated clock value
1227           sbaq      itimer-*  subtract interval timer value
1228           staq      ctime-*   store as current time
1229           rem
1230           ldx3      tnext-*   get the next ptr
1231           tze       set030-*  none in queue
1232           rem
1233           lda       a.l006-*  (=tnext) save addr of next ptr
1234           sta       tlasta-*  in tlasta for now
1235           lda       strtib-*  get real tib address
1236           rem
1237 set010    cmpa      ttib,3    is this the same tib?
1238           tze       set020-*  yes, process
1239           rem
1240           stx3      tlasta-*  save addr of this block
1241           ldx3      tfwd,3    get fwd ptr
1242           tze       set030-*  end of queue, done
1243           tra       set010-*  loop for more
1244           rem
1245 set020    lda       tfwd,3    get the fwd ptr
1246           sta       tlasta-*,*          and store in last blk
1247           lda       tfree-*   get free ptr
1248           sta       tfwd,3    put into this block
1249           stx3      tfree-*   reset free, putting this on head
1250           rem
1251 set030    lda       setsa-*   restore a reg value
1252           tze       set080-*  zero, no new value to set
1253           tpl       set031-*  positive, value in seconds
1254           ila       0
1255           ilq       0
1256           sbq       setsa-*   compute positive milliseconds
1257           tra       set032-*
1258           rem
1259 set031    mpy       l.l001-*  (=1000) convert to milliseconds
1260 set032    adaq      ctime-*   add in current time
1261           staq      time-*    save as expected timeout time
1262           staq      t.time,1  update into tib
1263           rem
1264           ldx3      tfree-*   get ptr to free block
1265           tnz       set050-*  good, we have one
1266           rem
1267           ilq       bufsiz    load buffer size
1268           tsy       a.i004-*,*          (=getbuf) get the needed buffer
1269           die       1
1270           stx3      tfree-*   save its address
1271           rem
1272           ila       bufsiz-2  get size minus two
1273           ars       1         divide by two
1274 set040    iacx3     2         bump to next block
1275           stx3      -2,3      store its addr in last fwd ptr
1276           iaa       -1        decrement count
1277           tnz       set040-*  loop for more
1278           rem
1279           stz       0,3       zero the last fwd ptr
1280           ldx3      tfree-*   get the free ptr again
1281           rem
1282 set050    lda       tfwd,3    take the block
1283           sta       tfree-*   update free ptr
1284           lda       strtib-*  get real tib address
1285           sta       ttib,3    save real tib address in blk
1286           rem
1287           stx3      tcur-*    save addr of new block
1288           lda       a.l006-*  (=tnext) save addr of next ptr
1289           sta       tlasta-*  for later reference
1290           ldx3      tnext-*   get addr of chain
1291           tze       set070-*  no chain here
1292           rem
1293 set060    lda       ttib,3    get real tib address from blk
1294           tsy       a.l001-*,*          (setptw) virtualize it
1295           cax1                put virtual tib address in x1
1296           ldaq      time-*    get the new time value
1297           cmpaq     t.time,1  is time < t.time?
1298           tnc       set070-*  yes, chain new block here
1299           rem
1300           stx3      tlasta-*  save addr of this blk
1301           ldx3      tfwd,3    bump to next blk
1302           tnz       set060-*  loop if more blks to look at
1303           rem
1304           ldx3      tcur-*    pick up addr of new blk
1305           stx3      tlasta-*,*          store in fwd ptr of last blk
1306           stz       tfwd,3    zero fwd ptr of this one
1307           tra       set080-*  continue
1308           rem
1309 set070    cx3a                save addr of next blk
1310           ldx3      tcur-*    pick up addr of new blk
1311           stx3      tlasta-*,*          store in fwd ptr of last blk
1312           sta       tfwd,3    reset fwd ptr of this blk
1313           rem
1314 set080    szn       itrint-*  has interval timer run out?
1315           tnz       set110-*  yes, will be set later...
1316           rem
1317           ldx3      tnext-*   pick up next ptr again
1318           tnz       set081-*  there are tib entries
1319           szn       runing-*  timer runing?
1320           tze       set110-*  no, nothing at all to do
1321           tra       set100-*  yes, just restart from current value
1322           rem
1323 set081    lda       ttib,3    get real tib address from first blk
1324           tsy       a.l001-*,*          (setptw) virtualize it
1325           cax1                put virtual tib address in x1
1326           szn       runing-*  is the clock running now?
1327           tze       set082-*  no, just set it
1328           rem
1329           ldaq      simclk-*  get the simulated clk value
1330           cmpaq     t.time,1  is simclk < t.time?
1331           tnc       set100-*  yes, all set
1332           rem
1333 set082    ldaq      t.time,1  get the tib time
1334           sbaq      ctime-*   subtract current time
1335           tnz       set085-*
1336           rem
1337           ila       0         set clock to very small number
1338           ilq       1         so we will get interrupt
1339           tra       set090-*
1340           rem
1341 set085    iaa       0         set the indicators
1342           tze       set090-*  less than max, set clock
1343           rem
1344           ila       1         set max timer value in aq
1345           ilq       0         all zeros in q
1346           rem
1347 set090    stq       a.l007-*,*          (=itmb) reset the clock
1348           rem
1349           adaq      ctime-*   add in current time to get new
1350           staq      simclk-*  simulated clock time, and store
1351           rem
1352 set100    sel       tmch      select the timer channel
1353           cioc      runpcw-*  run clock run
1354           aos       runing-*  is running now
1355           rem
1356 set110    null
1357           lda       savpte-*  get orig page table entry
1358           sta       a.l009-*,*          (.crpte,*) restore page table entry
1359           rem
1360           return    setime
1361           rem
1362           rem
1363 savpte    bss       1         saves variable page table entry
1364 strtib    bss       1         saves real tib address
1365           rem
1366           even
1367 mskpcw    vfd       18/0
1368           vfd       5/0,1/1,12/0
1369 runpcw    vfd       18/0
1370           vfd       18/0
1371           rem
1372 simclk    oct       0,0
1373 ctime     oct       0,0
1374 itimer    oct       0,0
1375 time      oct       0,0
1376           rem
1377 runing    oct       0
1378           rem
1379 tnext     oct       0
1380 tfree     ind       tque
1381           rem
1382 tque      tblk      16
1383           rem
1384           rem       equates for the symbols in a tque entry
1385           rem
1386 tfwd      equ       0
1387 ttib      equ       1
1388           rem
1389           rem
1390 tcur      oct       0
1391 tlasta    oct       0
1392           rem
1393           rem
1394 l.l001    dec       1000
1395           even
1396 l.l002    vfd       18/intpri
1397           ind       itmout
1398           rem
1399 a.l001    ind       setptw    set up variable cpu page table word
1400 a.l002    ind       gettib
1401 a.l003    ind       dspqur
1402 a.l004    ind       dnext
1403 a.l005    ind       dfree
1404 a.l006    ind       tnext
1405 a.l007    ind       itmb
1406 a.l008    ind       secdsp
1407 a.l009    ind       .crpte,*  variable cpu page table entry
1408           ttls      itrout -- interval timer runout interrupt processor
1409           rem
1410 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1411 *
1412 *         itrout
1413 *
1414 *              this routine handles the interval timer runout
1415 *         interrupt and schedules the itrip routine to
1416 *         handle the processing of the timouts.
1417 *
1418 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1419           rem
1420 itrout    ldaq      l.m001-*  get the priority and routine
1421           rem                 don't care whats in x1
1422           tsy       a.m001-*,*          (=dspqur) queue to run
1423           rem
1424           aos       itrint-*  interval timer has run out.
1425           rem
1426           tra       a.m002-*,*          (=mdisp) return to master dispatcher
1427           rem
1428 itrint    oct       0
1429           even
1430 l.m001    zero      itpri
1431           ind       itrip
1432           rem
1433 a.m001    ind       dspqur
1434 a.m002    ind       mdisp
1435           rem
1436           rem
1437           rem       jump table for interval timer runout
1438           rem
1439 timrjt    zero
1440           tsy       .invp-*,*
1441           vfd       18/modtmr
1442           rem
1443 .invp     ind       invp
1444           ttls      itrip - interval timer processor
1445           rem
1446 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1447 *
1448 *         itrip
1449 *
1450 *              this routine does the actual processing for
1451 *         the interval timer runout. it finds all people
1452 *         in the tib and delayq lists who have reached
1453 *         the requested time.
1454 *
1455 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1456           rem
1457 itrip     null                called by dispatcher
1458           rem
1459           stz       itrint-*  we have handled interrupt now
1460           stz       runing-*  not running now
1461           ila       0         get a very small number in aq
1462           ilq       2         to use as fudge in finding timouts
1463           adaq      simclk-*  get the real time of this
1464           staq      ctime-*   and save as current time
1465           rem
1466           trace     tt.itr,ts.tim,(ctime,ctime+1)
1467           rem
1468           ldx3      tnext-*   get ptr to tib list
1469           tze       itr020-*  no tibs in tib list
1470           rem
1471 itr010    lda       ttib,3    get ptr to first tib in list
1472           tsy       a.l001-*,*          (setptw) virtualize it
1473           cax1                put virtual tib address in x1
1474           ldaq      ctime-*   get current time
1475           cmpaq     t.time,1  is ctime < t.time?
1476           tnc       itr020-*  yes, all done
1477           rem                 no, give timeout
1478           ldx1      ttib,3    need real tib address for dspqur
1479           ldaq      l.l002-*  get priority and addr of itmout
1480           tsy       a.l003-*,*          (=dspqur) queue it up, real tib in x1
1481           rem
1482           lda       tfwd,3    save old fwd ptr
1483           ldq       tfree-*   get the free ptr
1484           stq       tfwd,3    save as fwd ptr of this one
1485           stx3      tfree-*   make this one first free
1486           rem
1487           cax3                bump to next block
1488           stx3      tnext-*   point the que head at this blk
1489           iacx3     0         set the indicators
1490           tnz       itr010-*  loop if more blks to look at
1491           rem
1492 itr020    ldx3      a.l004-*,*          (=dnext) get delayq next ptr
1493           tze       itr040-*  none in queue now
1494           rem
1495 itr030    ldaq      ctime-*   get the current time
1496           cmpaq     dtime,3   compare: is ctime < dtime?
1497           tnc       itr040-*  yes, all done
1498           rem                 no, give time out
1499           lda       dpri,3    get the priority
1500           ldq       drtn,3    and the routine addr
1501           ldx1      dx1,3     and his value in x1
1502           tsy       a.l003-*,*          (=dspqur) and queue him to run
1503           rem
1504           lda       dfwd,3    get the fwd ptr in this blk
1505           ldq       a.l005-*,*          (=dfree) get the free ptr
1506           stq       dfwd,3    and put into this blk
1507           stx3      a.l005-*,*          (=dfree) and put this on at top
1508           rem
1509           cax3                bump to next guy in list
1510           stx3      a.l004-*,*          (=dnext) point head at this one
1511           iacx3     0         set the indicators
1512           tnz       itr030-*  loop for more work
1513           rem
1514 itr040    stz       itrsw-*   zero the switch word
1515           rem
1516           szn       tnext-*   any tibs in tib list?
1517           tze       3         no
1518           rem
1519           ila       1         yes, set bit
1520           orsa      itrsw-*
1521           rem
1522           szn       a.l004-*,*          (=dnext) any entries in delayq?
1523           tze       3         no
1524           rem
1525           ila       2         yes, set other bit
1526           orsa      itrsw-*
1527           rem
1528           ldx3      itrsw-*   load the switch word
1529           tra       a.n001-*,*          (=itrtbl,3*) use as index to label array
1530           rem
1531 itrtbl    ind       itr041    no timers needed
1532           ind       itr042    only tib timers set
1533           ind       itr043    only delayq timers on
1534           ind       itr044    both set, compare
1535           rem
1536 itr041    ila       0         set standard time for clock
1537           ldq       l.n001-*  (=60*1000) so we idle for a minute
1538           adaq      ctime-*   add it in so we can subtract it out
1539           tra       itr050-*  set clock
1540           rem
1541 itr042    ldx3      tnext-*   get ptr to first tib entry
1542           lda       ttib,3    get real tib address
1543           tsy       a.l001-*,*          (setptw) virtualize it
1544           cax1                put virtual tib address in x1
1545           ldaq      t.time,1  have tib time
1546           tra       itr050-*  set clock
1547           rem
1548 itr043    ldx3      a.l004-*,*          (=dnext) get ptr to delayq list
1549           ldaq      dtime,3   get first delayq time
1550           tra       itr050-*  set clock
1551           rem
1552 itr044    ldx3      tnext-*   get ptr to tib list
1553           lda       ttib,3    get real ptr to first tib in list
1554           tsy       a.l001-*,*          (setptw) virtualize it
1555           cax1                put virtual tib address in x1
1556           ldaq      t.time,1  get the tib time
1557           rem
1558           ldx3      a.l004-*,*          (=dnext) get ptr to delay list
1559           cmpaq     dtime,3   is t.time < dtime?
1560           tnc       itr050-*  yes, all set
1561           rem
1562           ldaq      dtime,3   get the delay q time instead
1563           rem
1564 itr050    sbaq      ctime-*   subtract current time to get interval
1565           tnz       itr055-*  non-zero, all set
1566           rem
1567           ila       0         set to a very
1568           ilq       1         small number to get interrupt
1569           tra       itr060-*
1570           rem
1571 itr055    iaa       0         set indicators
1572           tze       itr060-*  less than max timer values, all set
1573           rem
1574           ila       1         set max value allowed
1575           ilq       0
1576           rem
1577 itr060    stq       a.l007-*,*          (=itmb) put into timer loc
1578           adaq      ctime-*   get next simclk time
1579           staq      simclk-*  and save it away
1580           rem
1581           sel       tmch      select timer
1582           cioc      runpcw-*  start the clock, run, run, run.
1583           aos       runing-*  running again
1584           rem
1585 itr070    tra       a.l008-*,*          (=secdsp) return dispatcher
1586           rem
1587 itrsw     bss       1
1588           rem
1589 l.n001    dec       60000
1590           rem
1591 a.n001    ind       itrtbl,3*
1592           end