tmm$task_switch             ident
.
..........................................................................................
.
.           This assembly language module contains dispatcher procedures
.           which are written in assembly language to be more efficient.
.           This module contains the following:
.               tmp$select_next_task
.
.........................................................................................
.
.
.  common decks used (not listed here)
.     sya$constants, sya$cybil_interface_procedures, osa$basic_register_equates,
.     sya$xp_and_sf_constants
          list,0   0,0,0
*copyc mta$cpu_state_table
*copyc tma$task_switch
*copy OSA$BASIC_REGISTER_EQUATES
*copy SYA$CONSTANTS
*copy SYA$CYBIL_INTERFACE_PROCEDURES
*copyc sya$xp_and_sf_constants
          list,0   1,2,1
.
.
........................................................................................
.  Define A and X registers.
........................................................................................
.  Register equates used for ploada and pstorxp macros.
.
.
amacscr  equ       15                       .scratch a reg used by macros
amacscr  atrib     #regtyp,#areg
.
.
a_cstp    areg     6                        .Pointer to the CPU state table.
a_dct     areg     7                        .Pointer to the Dispatch Control Table.
a_ptl     areg     8                        .Pointer to the Primary Task List.
a_ijlroot areg     9                        .Pointer to the IJL.
a_ijle    areg     10                       .Pointer to an ijl entry.
a_xcbp    areg     11                       .Pointer to the XCB.
a_jcbp    areg     12                       .Pointer to the JCB.
.                                           .X0 through X3 are scratch registers.
x4_zero   xreg     4                        .X4 will contain the constant 0.
x_lsets   xreg     5                        .Copy of dispatching control sets.
x_ptlo    xreg     6                        .PTL ordinal selected.
x_rset    xreg     7                        .Dispatch control sets converted to a real.
x_prio    xreg     8                        .Dispatching priority selected.
x_ijlo    xreg     9                        .Ijlo of task selected.
x_ajlo    xreg     10                       .Ajlo of task selected.
x_xcboff  xreg     11                       .Offset of the xcb.
x_ptloff  xreg     12                       .Offset of the ptl entry.
x_ijlsize xreg     13                       .Size of an ijl entry.
x_cpus_m1 xreg     14                       .Cpus logically on, minus 1.
x_csti    xreg     15                       .Cst index.
.
.
          page
.........................................................................................
.
.  Define constants
.........................................................................................
.
.
.
........................................................................................
.  Define Binding Section..
........................................................................................
.
          use      binding
          ref      dc_sets
          ref      dct
          ref      cpus_on
          ref      ptl_p
          ref      ijl_p
          ref      ijlsize
dc_sets   alias    tmv$dispatching_control_sets
dct       alias    tmv$dct
cpus_on   alias    osv$cpus_logically_on
ptl_p     alias    tmv$ptl_p
ijl_p     alias    jmv$ijl_p
ijlsize   alias    jmv$ijle_size
bs_sets   address  p,dc_sets                .Pointer to dispatching control sets.
bs_dct    address  p,dct                    .Pointer to the dct.
bs_cpus   address  p,cpus_on                .Pointer to cpus logically on.
bs_ptl    address  p,ptl_p                  .Pointer to the ptl.
bs_ijlr   address  p,ijl_p                  .Pointer to the ijl.
bs_ijlsz  address  p,ijlsize                .Pointer to the size of an ijl entry.
.
.
........................................................................................
.
.  This procedure is used in monitor to select a new task for CPU execution.
.
.    TMP$SELECT_NEXT_TASK (CST_P, PTLO);
.
.    CST_P: (input) This parameter specifies the pointer to the CPU state table
.         for the CPU that a new task is being selected for.
.    PTLO: (output) This parameter returns the PTL ordinal of the task selected
.         to execute.
.
.
.      PROCEDURE [XREF] tmp$select_next_task
.        (    cst_p: ^ost$cpu_state_table;
.         VAR ptlo: ost$task_index);
.
.
.
.     NOTES:
.        Document procedure
.
.
.
........................................................................................
.
          use      code
          def      sel_task
sel_task  alias    tmp$select_next_task
sel_task  procedur
cst_p     param    val,pointer
ptlo      param    ref,subrange,2
.
.
          la       af,a_bindin,bs_sets      .Load a copy of DISPATCHING_CONTROL_SETS
          entp     x4_zero,0                .Initialize X4 to zero
          entp     x_ptlo,0                 .Initialize ptlo to zero.
          lx       x_lsets,af,head          .Load DISPATCHING_CONTROL_SETS, cont.
.
          shfx     x1,x_lsets,x0,-16        .Reorder the dispatching control sets.
          shfx     x2,x_lsets,x0,-48        .Mask out prios which have exceeded max.
          inhx     x1,x2                    .Determine which need minimums satisfied.
.                                           .X1 now has ready tasks to be considered.
          insb     x_lsets,x4_zero,x0,17(8) .Mask out enforce maximums.
          shfx     x2,x_lsets,x0,-32        .Pick up minimums to satisfy.
          andx     x2,x1                    .Multiply minimums by ready tasks.
          insb     x_lsets,x2,x0,2017(8)    .Store minimums back into the sets.
.
          cpyxx    x3,x_lsets               .Pick up maximums exceeded.
          andx     x3,x1                    .Multiply max exceeded by ready tasks.
          insb     x_lsets,x3,x0,6017(8)    .Put maximums exceeded back in the sets.
.
          iorx     x2,x3                    .Mask mins and maxs out of ready tasks so
          xorx     x1,x2                    .no duplicate are priorities in the sets.
.
          insb     x_lsets,x1,x0,4017(8)    .Put the ready tasks back into the sets.
.
          brxeq    x_lsets,x0,quit          .If there are no priorities set, return.
.
          ploada   a_cstp,cst_p             .Load the CST_P (input parameter).
          la       ae,a_bindin,bs_cpus      .Load osv$cpus_logically_on.
          la       a_ptl,a_bindin,bs_ptl    .Load the PTL pointer.
          la       a_ijlroot,a_bindin,bs_ijlr      .Load the IJL pointer.
          la       af,a_bindin,bs_ijlsz     .Load the ijl entry size.
          la       a_dct,a_bindin,bs_dct    .Load the DCT pointer.
          lbyts,1  x_csti,a_cstp,x0,lpid    .Load the cst index.
          lbyts,1  x_cpus_m1,ae,x0,head     .CPUS on, cont.
          la       a_ptl,a_ptl,0            .PTL pointer, cont.
          la       a_ijlroot,a_ijlroot,0    .IJL pointer, cont.
          lbyts,2  x_ijlsize,af,x0,head     .Ijl entry size, cont.
          decr     x_cpus_m1,1              .Subtract 1 from cpus on.
          brxeq    x0,x0,prio_loop          .Jump to select the first prio set.
.
new_prio  shfx     x_rset,x_rset,x0,-48     .Manipulate the real to pull off the bit
          shfx     x_rset,x_rset,x0,6       .number of the priority already
          notx     x_rset,x_rset            .considered so that it can be removed
          isom     x_rset,x_rset,1          .from the sets.
          inhx     x_lsets,x_rset
          brxeq    x_lsets,x0,quit          .Quit if no prio is still set.
.
prio_loop cnif     x_rset,x_lsets           .Convert the dispatch sets to an integer.
          isob     x_prio,x_rset,x0,1403(8) .The first bit in the set is the prio.
.
          shfx     x_prio,x_prio,x0,3       .Multiply prio by 8 to get dcte offset.
          lbyts,2  x_ptlo,a_dct,x_prio,head .Get the head of the dct entry.
          brxne    x_ptlo,x0,ptlo_loop      .If ptlo is 0, halt.
          halt
.
next_ptlo lbyts,2  x_ptlo,a_ptl,x_ptloff,thread    .Get the next task in the DCT.
          brxeq    x_ptlo,x0,new_prio       .While ptlo is not 0, loop.  If ptlo
.                                           .is zero, try a new priority.
.
.                                           .Verify the task can execute.
ptlo_loop shfx     x_ptloff,x_ptlo,x0,ptlshf       .Offset into the PTL of task selected.
          lbyts,2  x_ijlo,a_ptl,x_ptloff,ptl_ijlo  .Get the ijlo of the task.
.                                           .Get a pointer to the ijl entry.
          shfx     x1,x_ijlo,x0,-5          .Isolate the ijl block number.
          lxi      x1,a_ijlroot,x1,0        .Get the pointer to the ijl block.
          cpyxa    a_ijle,x1
          isob     x1,x_ijlo,x0,7304(8)     .Isolate the ijl block index.
          mulx     x1,x_ijlsize             .Determine the offset into the block.
          addax    a_ijle,x1                .Pointer to the ijl entry.
.
          lbyts,1  x_ajlo,a_ijle,x0,ijl_ajlo       .Pick up the ajlo of the task.
          lbyts,4  x2,a_ptl,x_ptloff,xcboff .Load the xcb offset from the ptle to
.                                           .to use for generating an xcb pointer.
.                                           .Generate a JCB pointer.
          ente     x1,1014(16)              .Set up ring, base seg#.
          addx     x1,x_ajlo                .Increase seg# by ajlo.
          shfx     x1,x1,x0,32              .Shift the ring, seg#; offset is 0.
          cpyxa    a_jcbp,x1                .Copy the JCB pointer.
.                                           .Generate an xcb pointer.
          addx     x1,x2                    .Add the xcb offset into the pointer.
          cpyxa    a_xcbp,x1                .Copy the XCB pointer.
.
.                                           .If the task can execute, exit.
.                                           .Otherwise consider another task.
          brxeq    x_cpus_m1,x0,save_cst    .If only one CPU, the task can execute.
.
          lbyts,1  x2,a_xcbp,x0,p_select    .Load the xcb processor_selections.
          shfx     x2,x2,x_csti,58          .Shift the bit to the left.
          brxge    x2,x0,next_ptlo          .If zero, the csti is not in the set.
.
          lbyts,1  x2,a_jcbp,x0,tasks       .Load JCB executing_task_count.
          brxne    x2,x0,multi              .If another task of the job is
.                                           .executing, check multiprocessing.
          lbyts,1  x2,a_jcbp,x0,j_lpid      .Purge buffers if the last processor
          brxne    x2,x_csti,purg_buf       .for the job was not this one.
          brxeq    x0,x0,save_cst           .The task can execute, exit.
.
multi     lbyts,1  x2,a_jcbp,x0,multi       .Load JCB multiprocessing_allowed.
          brxeq    x2,x0,next_ptlo          .If no multiprocessing, select new task.
          lbyts,1  x2,a_xcbp,x0,t_lpid      .Purge buffers if the last processor
          brxeq    x2,x_csti,save_cst       .for the task was not this one.
.
purg_buf  purge    x1,2                     .Purge buffers.
          purge    x1,15
.                                           .Task selected to execute; save cst info.
save_cst  sbyts,1  x_ajlo,a_cstp,x0,ajlo    .Store the ajlo of the task selected.
          sbyts,2  x_ijlo,a_cstp,x0,ijlo    .Store the ijlo of the task selected.
          sa       a_ijle,a_cstp,ijlep      .Store the ijl pointer of the task.
          sa       a_jcbp,a_cstp,jcbp       .Store the jcb pointer of the task.
          sa       a_xcbp,a_cstp,xcbp       .Store the xcb pointer of the task.
.
quit      pstorxp  x_ptlo,ptlo              .Return the ptlo selected.
          return
          end
