?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Task Management : dispatcher' ??
MODULE tmm$dispatcher;
?? RIGHT := 110 ??

{  PURPOSE:
{    This module is used for managing the creation and deletion of tasks, the creation
{    and deletion of jobs, the status of tasks, and the selection of tasks to execute.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc jmc$null_ajl_ordinal
*copyc jmc$special_dispatch_priorities
*copyc mtc$job_fixed_segment
*copyc osc$multiprocessor_constants
*copyc osc$processor_defined_registers
*copyc osc$purge_map_and_cache
*copyc osc$system_table_lock_set
*copyc osc$table_lock_activity
*copyc tmc$free_flag_id
*copyc jme$job_scheduler_conditions
*copyc jse$condition_codes
*copyc mme$condition_codes
*copyc tme$monitor_mode_exceptions
*copyc ptk$performance_keypoints
*copyc gft$locked_file_desc_entry_p
*copyc jmt$active_job_list
*copyc jmt$dispatching_control
*copyc jmt$dispatching_control_index
*copyc jmt$dispatching_priority
*copyc jmt$dispatching_priority_set
*copyc jmt$ijl_p
*copyc jmt$ijl_swap_status
*copyc jmt$ijle_size
*copyc jmt$initiated_job_list_entry
*copyc jmt$initiated_job_list_p
*copyc jmt$service_class_index
*copyc jmt$swapout_reasons
*copyc jst$ijl_swap_queue_link
*copyc mmt$rb_lock_unlock_segment
*copyc ost$cpu_state_table
*copyc ost$execution_control_block
*copyc ost$global_task_id
*copyc ost$heap
*copyc ost$keypoint_class
*copyc ost$name
*copyc ost$status
*copyc pmt$ready_task_list
*copyc pmt$signal
*copyc syt$debug_control
*copyc tmt$cpu_execution_statistics
*copyc tmt$dispatch_control_table
*copyc tmt$dispatching_control_sets
*copyc tmt$dispatching_controls
*copyc tmt$dispatching_prio_controls
*copyc tmt$dual_state_dispatch_prior
*copyc tmt$fnx_search_type
*copyc tmt$idle_resume_sys_task_kind
*copyc tmt$new_ptl_lock
*copyc tmt$primary_task_list
*copyc tmt$ptl_lock
*copyc tmt$rb_cycle
*copyc tmt$rb_delay
*copyc tmt$rb_exit_job
*copyc tmt$rb_exit_task
*copyc tmt$rb_fetch_task_statistics
*copyc tmt$rb_get_job_fixed_segment
*copyc tmt$rb_initiate_job
*copyc tmt$rb_initiate_task
*copyc tmt$rb_task_exit
*copyc tmt$rb_terminate_task
*copyc tmt$rb_update_job_task_enviro
*copyc tmt$rb_wait
*copyc tmt$system_task_id
*copyc tmt$task_queue_link
*copyc tmt$task_status
*copyc tmt$wait_queue_statistics
?? POP ??
*copyc gfp$mtr_get_fde_p
*copyc gfp$mtr_get_locked_fde_p
*copyc jmp$get_ijle_p
*copyc jmf$ijle_p
*copyc jmp$assign_ajl_entry
*copyc jmp$change_ijl_entry_status
*copyc jmp$decrement_swapped_job_count
*copyc jmp$free_ajl_entry
*copyc jmp$free_ajl_with_lock
*copyc jmp$increment_swapped_job_count
*copyc jmp$ready_task_in_swapped_job
*copyc jmp$set_job_terminated
*copyc jmp$set_scheduler_event
*copyc jmp$set_swapout_candidate
*copyc jmp$subsystem_priority_change
*copyc jmp$swap_non_dispatchable_job
*copyc jmp$unlock_ajl_with_lock
*copyc jmp$update_service_class_stats
*copyc jsp$idle_tasks_complete
*copyc jsp$long_wait_aging
*copyc jsp$relink_swap_queue
*copyc jsp$set_delayed_swapin_work_mtr
*copyc mmp$create_job
*copyc mmp$create_task
*copyc mmp$exit_job
*copyc mmp$exit_task
*copyc mmp$get_sdtx_entry_p
*copyc mtf$cst_p
*copyc mtp$error_stop
*copyc mtp$interrupt_processor
*copyc mtp$set_status_abnormal
*copyc osp$update_job_keypoint_mask
*copyc tmp$check_ptl_lock
*copyc tmp$clear_lock
*copyc tmp$get_xcb_access_status
*copyc tmp$send_signal
*copyc tmp$set_lock
*copyc tmp$set_monitor_flag
*copyc tmp$set_system_flag
*copyc tmp$update_system_task_list
*copyc jmv$idle_dispatching_controls
*copyc jmv$ijl_entry_status_statistics
*copyc jmv$job_counts
*copyc jmv$null_ijl_ordinal
*copyc jmv$service_classes
*copyc jmv$subsystem_priority_changes
*copyc mmv$ast_p
*copyc mmv$avail_mod_wait_queue
*copyc mtv$monitor_segment_table
{copyc mtv$ptl_recovery
*copyc mtv$scb
*copyc osv$cpus_logically_on
*copyc osv$cpus_physically_configured
*copyc osv$keypoint_control
*copyc syv$perf_keypoints_enabled
*copyc tmv$null_global_task_id
*copyc i#move
*copyc i#mtr_disable_traps
*copyc i#mtr_restore_traps
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??

  TYPE
    t$dct_placement = (minor_timeslice_insert, major_timeslice_insert, tail_timeslice_insert);

  TYPE
    tmt$ready_task_list_statistics = record
      calls: integer,
      task_list_size: integer,
      executing_count: integer,
      ready_swapped_count: integer,
      ready_count: integer,
      ready_task_priority_changed: array [boolean] of integer,
      subsystem_priotity_change_count: integer,
      task_in_wait_idled: integer,
      task_in_wait_not_idled: array [boolean] of integer,
      task_in_wait_swapping: integer,
      external_event_wait: array [tmc$ts_io_wait_not_queued .. tmc$ts_volume_unavailable] of integer,
      unsuccessful_ready_count: integer,
      calls_with_multiple_preselects: integer,
    recend;

  VAR
    null_pva: 0 .. 0ffffffffffff(16),
    osv$system_family_name: [XDCL, #GATE] ost$name := '$SYSTEM                        ',
    jmv$system_core_id: [XDCL, #GATE] ost$name,
    tmv$dct_priority_integer: integer,
    tmv$dispatch_priority_integer: [XDCL, #GATE] array [jmt$dispatching_priority] of integer,
    tmv$dispatching_controls: [XDCL] tmt$dispatching_controls,
    tmv$dispatching_control_sets: [XDCL, #GATE] tmt$dispatching_control_sets,
    tmv$dispatching_control_time: [XDCL] tmt$dispatching_prio_controls,
    tmv$dual_state_dispatch_prior: [XDCL, #GATE] tmt$dual_state_dispatch_prior :=
          [[1, 8], [1, 8], [2, 8], [2, 8], [3, 8], [3, 8], [4, 8], [4, 8], [5, 8], [5, 8], [6, 8], [6, 8],
          [7, 8], [7, 8]],
    tmv$multiple_cpus_active: [XDCL, #GATE] boolean := FALSE,
    tmv$swapin_in_progress: [XDCL] integer := 0,
    tmv$time_to_call_dispatcher: [XDCL] integer := 0,
    tmv$timed_wait_not_queued: [XDCL, #GATE] integer := 600000000,
    tmv$timed_wait_queue: tmt$task_queue_link := [0, 0],
    tmv$total_task_count: [XDCL, #GATE] 0 .. tmc$maximum_ptl := 0,
    tmv$long_wait_swap_time: [XDCL, #GATE] integer := 6000000,
    tmv$long_wait_force_swap_time: [XDCL, #GATE] integer := 6000000,
    tmv$cycle_delay_time: [XDCL, #GATE] integer := 20000,
    tmv$tables_initialized: [XDCL, #GATE] boolean := FALSE,
    syv$debug_control: [XDCL, #GATE] syt$debug_control,
    syv$all_jobs_selected_for_debug: [XDCL, #GATE] boolean := FALSE,
    tmv$ptl_lock: [XDCL] tmt$ptl_lock := [FALSE, 0],
    tmv$new_ptl_lock: [XDCL] tmt$new_ptl_lock := [FALSE, 0],
    tmv$system_job_monitor_gtid: [XDCL] ost$global_task_id := [1, 1],
    tmv$ptl_p: [XDCL, #GATE] ^tmt$primary_task_list,
    jmv$ajl_p: [XDCL, #GATE] ^jmt$active_job_list := NIL,
    jmv$ijl_p: [XDCL, #GATE] jmt$ijl_p := [NIL, 0, 0],
    jmv$ijle_size: [XDCL, #GATE] jmt$ijle_size := 0,
    jmv$swap_jobs_in_long_wait: [XDCL, #GATE] boolean := TRUE,
    jmv$system_ajl_ordinal: [XDCL, #GATE] jmt$ajl_ordinal := 0,
    jmv$system_ijl_ordinal: [XDCL, #GATE] jmt$ijl_ordinal := [0, 0],
    pmv$quantum: [XDCL, #GATE] integer := 50000,
    tmv$subsystem_prior_threshold: [XDCL, #GATE] 0 .. 0ff(16) := 8,
    tmv$dct: [XDCL, #GATE] tmt$dispatch_control_table;

  VAR
    v$null_dcte: [READ] tmt$dct_entry := [0, 0, 0, 0];

  VAR
    tmv$rtl_attempt_preselection: [XDCL, #GATE] boolean := FALSE;

{ Statistic counters

  VAR
    tmv$cpu_execution_statistics: [XDCL, #GATE] tmt$cpu_execution_statistics,
    tmv$ready_task_list_statistics: [XDCL, #GATE] tmt$ready_task_list_statistics :=
          [0, 0, 0, 0, 0, [0, 0], 0, 0, [0, 0], 0, [0, 0, 0, 0, 0, 0, 0], 0, 0],
    tmv$wait_queue_statistics: [XDCL, #GATE] tmt$wait_queue_statistics := [0, 0, 0, 0, 0, 0, 0];

*if $true(tmc$debug_cycle_requests)

{Define types and variables for tracing CYCLE requests. Note that the code to trace CYCLE requests
{is normally disabled and a special version of the system must be built to record information.

  TYPE
    cyctrace = record
      code: tmc$cycle_reason,
      status: tmt$task_status,
      p1: ^cell,
      p2: ^cell,
      gtid: ost$global_task_id,
      xtask: ost$task_index,
      time: 0 .. 0ffffffffffff(16),
      p: ost$pva,
      utp: ^cell,
    recend;

  VAR
    osv$debug: [XREF] integer,
    tmv$cycle_trace: [XDCL, #GATE] array [0 .. 10001] of cyctrace,
    ti: [STATIC] integer;

*ifend

{ Priority_mask and t$dp_trick_conversion are types for the variable that is
{ used to determine the priority to be considered for select_next_task.
{ #unchecked_conversion is used to "pull off" the leftmost bit set.

  TYPE
    t$priority_mask = packed record
      fill: 0 .. 0ff(16),
      set_number: 0 .. 0f(16),
      dp: jmt$dispatching_priority,
      fill2: 0 .. 0ffffffffffff(16),
    recend,

    t$dp_trick_conversion = record
      case 0 .. 1 of
      = 0 =
        r: real,
      = 1 =
        dp_mask: t$priority_mask,
      casend,
    recend;

?? OLDTITLE ??
?? NEWTITLE := '[INLINE] P$ASSIGN_PTL', EJECT ??

  PROCEDURE [INLINE] p$assign_ptl
    (    xcb_p: ^ost$execution_control_block;
         ijl_ordinal: jmt$ijl_ordinal;
     VAR taskid: ost$global_task_id;
     VAR status: syt$monitor_status);

{ This procedure assignes PTL entries from the free queue. TME$PTL_FULL is returned if the PTL is full.

    VAR
      next_avail_ptlo: ost$task_index,
      ptl_p: ^tmt$primary_task_list_entry;

{Check if PTL space is available.
    status.normal := TRUE;
    next_avail_ptlo := tmv$dct [jmc$null_dispatching_priority].queue_head;
    IF next_avail_ptlo = 0 THEN
      mtp$set_status_abnormal ('TM', tme$ptl_full, status);
      RETURN; {----->
    IFEND;

    ptl_p := ^tmv$ptl_p^ [next_avail_ptlo];
    tmv$dct [jmc$null_dispatching_priority].queue_head := ptl_p^.ptl_thread;

{ If the job is selected for system breakpoints, set the flag for the task to set up debug registers.
    ptl_p^.monitor_flags := $syt$monitor_flags [];
    IF jmf$ijle_p (ijl_ordinal) ^.system_breakpoint_selected THEN
      ptl_p^.monitor_flags := $syt$monitor_flags [syc$mf_system_debugger];
    IFEND;

{Initialize the PTL entry.
    xcb_p^.keypoint_enable := FALSE;
    xcb_p^.keypoint_register_enable := FALSE;
    ptl_p^.status := tmc$ts_ready;
    ptl_p^.ijl_ordinal := ijl_ordinal;
    ptl_p^.xcb_offset := #OFFSET (xcb_p);
    ptl_p^.dispatching_priority := xcb_p^.dispatching_priority;
    ptl_p^.sequence_number := ptl_p^.sequence_number MOD 255 + 1;
    ptl_p^.system_flags := $tmt$system_flags [];
    ptl_p^.idle_status := tmc$is_not_idled;
    ptl_p^.queue_link.head := 0;
    ptl_p^.queue_link.tail := 0;
    ptl_p^.end_of_wait_time := 0;
    ptl_p^.readying_task_priority := 0;
    taskid.index := next_avail_ptlo;
    taskid.seqno := ptl_p^.sequence_number;

  PROCEND p$assign_ptl;
?? OLDTITLE ??
?? NEWTITLE := 'P$CALCULATE_SERVICE_USED', EJECT ??

{ PURPOSE:
{   This procedure calculates the amount of CP service a job has used.  The procedure
{   tmp$reset_dispatching_control determines the dispatching control index to use, based
{   on the SERVICE_USED returned.
{
{ DESIGN:
{   For interactive jobs, return 0 for service_used; the dispatching control index should
{   be reset to the first index.  For batch classes, base service_used on total cp time.
{   If the job's service class has circular dynamic dispatching priorities defined,
{   MOD the service_used by the sums of the service limits.

  PROCEDURE p$calculate_service_used
    (    ijle_p: ^jmt$initiated_job_list_entry;
     VAR service_used: integer);

    VAR
      circular_service: integer,
      dispatching_control_p: ^jmt$dispatching_control,
      dispatching_control_index: jmt$dispatching_control_index;

    IF ijle_p^.job_mode <> jmc$batch THEN
      service_used := 0;
    ELSE
      service_used := ijle_p^.statistics.cp_time.time_spent_in_job_mode +
            ijle_p^.statistics.cp_time.time_spent_in_mtr_mode -
            ijle_p^.dispatching_control.cp_service_at_class_switch;
      circular_service := 0;
      dispatching_control_p := ^jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
            dispatching_control;

    /calculate_circular_service/
      FOR dispatching_control_index := jmc$max_dispatching_control DOWNTO jmc$min_dispatching_control DO
        IF dispatching_control_p^ [dispatching_control_index].set_defined THEN
          IF dispatching_control_p^ [dispatching_control_index].service_limit <>
                jmc$dc_maximum_service_limit THEN
            circular_service := circular_service + dispatching_control_p^ [dispatching_control_index].
                  service_limit;
          ELSE
            EXIT /calculate_circular_service/; {----->
          IFEND;
        IFEND;
      FOREND /calculate_circular_service/;

      IF circular_service <> 0 THEN
        service_used := service_used MOD circular_service;
      IFEND;
    IFEND;

  PROCEND p$calculate_service_used;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$CHECK_TASKID_WITH_LOCK_SET', EJECT ??

  PROCEDURE [INLINE] p$check_taskid_with_lock_set
    (    taskid: ost$global_task_id;
     VAR status: syt$monitor_status);

    IF (taskid = tmv$null_global_task_id) OR (taskid.index > UPPERBOUND (tmv$ptl_p^)) OR
          (tmv$ptl_p^ [taskid.index].sequence_number <> taskid.seqno) OR
          (tmv$ptl_p^ [taskid.index].status = tmc$ts_null) THEN
      mtp$set_status_abnormal ('TM', tme$invalid_global_taskid, status);
    IFEND;

  PROCEND p$check_taskid_with_lock_set;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$DCT_READY_TASK', EJECT ??
*copyc tmh$dct_ready_task

  PROCEDURE [INLINE] p$dct_ready_task
    (    xcb_p: ^ost$execution_control_block;
         ijle_p: ^jmt$initiated_job_list_entry;
         ptlo: ost$task_index;
         attempt_preselection: boolean);

    VAR
      cst_index: integer,
      dct_placement: t$dct_placement,
      dcte: tmt$dct_entry,
      insert_ijle_p: ^jmt$initiated_job_list_entry,
      insert_ptle_p: ^tmt$primary_task_list_entry,
      low_prio_cst_p: ^ost$cpu_state_table,
      low_prio_csti: integer,
      low_priority: integer,
      next_ptlo: ost$task_index,
      ptle_p: ^tmt$primary_task_list_entry,
      timeslice: jmt$time_slice_values;

    ptle_p := ^tmv$ptl_p^ [ptlo];
    timeslice := jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
          dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].dispatching_timeslice;

{ Determine where the task is to be positioned in the DISPATCH_CONTROL_TABLE.
    IF xcb_p^.timeslice.minor > (timeslice.minor DIV 8) THEN
      dct_placement := minor_timeslice_insert;
    ELSEIF xcb_p^.timeslice.major > (timeslice.minor DIV 8) THEN
      dct_placement := major_timeslice_insert;
      xcb_p^.timeslice.minor := timeslice.minor;
    ELSE
      dct_placement := tail_timeslice_insert;
      xcb_p^.timeslice := timeslice;
    IFEND;

    #SPOIL (timeslice); {makes optimization better

{ If a task has subsystem table locks set for more than the subsystem lock threshold, then
{ lower the tasks priority. If the task received a READY request while it had subsystem
{ locks set, the priority is lowered to the greater of the task's or the READYING task's
{ dispatching priority.

    IF xcb_p^.system_table_lock_count <= 0 THEN
      ;
    ELSEIF xcb_p^.system_table_lock_count < osc$system_table_lock_set THEN
      IF xcb_p^.subsystem_lock_priority_count >= tmv$subsystem_prior_threshold THEN
        IF (xcb_p^.dispatching_priority < ptle_p^.readying_task_priority) THEN
          ptle_p^.dispatching_priority := ptle_p^.readying_task_priority;
        ELSE
          ptle_p^.dispatching_priority := xcb_p^.dispatching_priority;
        IFEND;
      ELSE
        IF ptle_p^.dispatching_priority < jmc$prior_subsystem_tbls_locked THEN
          ptle_p^.dispatching_priority := jmc$prior_subsystem_tbls_locked;
        IFEND;
        IF dct_placement <> minor_timeslice_insert THEN
          xcb_p^.subsystem_lock_priority_count := xcb_p^.subsystem_lock_priority_count + 1;
        IFEND;
      IFEND;
      xcb_p^.subsystem_give_up_cpu := TRUE;
    ELSE
      xcb_p^.system_give_up_cpu := TRUE;
      IF ptle_p^.dispatching_priority < jmc$prior_system_tbls_locked THEN
        ptle_p^.dispatching_priority := jmc$prior_system_tbls_locked;
      IFEND;
    IFEND;

{ Determine if the priority is high enough to preempt a task that is currently executing.
{ Send an interrupt to the processor executing the lowest priority task (or an idle processor).

    IF attempt_preselection THEN
      low_priority := tmv$dispatch_priority_integer [ptle_p^.dispatching_priority];
      cst_index := osv$cpus_physically_configured - 1;
      low_prio_csti := -1;

{preselect_loop
      REPEAT
        IF (mtv$cst0 [cst_index].dispatching_priority_integer < low_priority) AND
              (cst_index IN xcb_p^.processor_selections) THEN
          low_prio_csti := cst_index;
          low_priority := mtv$cst0 [cst_index].dispatching_priority_integer;
        IFEND;
        cst_index := cst_index - 1;
      UNTIL (cst_index < 0) OR (low_priority = 0);

      IF low_prio_csti >= 0 THEN
        low_prio_cst_p := ^mtv$cst0 [low_prio_csti];
        next_ptlo := low_prio_cst_p^.next_ptlo_to_dispatch;
        IF next_ptlo <> 0 THEN

{ A task has already been pre-selected to run on the pre-selected processor.  The task must be inserted
{ at the head of its priority DCT queue.

          insert_ptle_p := ^tmv$ptl_p^ [next_ptlo];
          jmp$get_ijle_p (insert_ptle_p^.ijl_ordinal, insert_ijle_p);
          insert_ijle_p^.executing_task_count := insert_ijle_p^.executing_task_count - 1;
          insert_ptle_p^.status := tmc$ts_ready;
          dcte := tmv$dct [insert_ptle_p^.dispatching_priority];
          IF dcte.queue_head = 0 THEN
            insert_ptle_p^.ptl_thread := 0;
            dcte.queue_head := next_ptlo;
            dcte.queue_tail := next_ptlo;
            dcte.minor_priority := next_ptlo;
            dcte.major_priority := next_ptlo;
            tmv$dispatching_control_sets.ready_tasks := tmv$dispatching_control_sets.ready_tasks +
                  $jmt$dispatching_priority_set [jmc$dp_conversion - insert_ptle_p^.dispatching_priority];
            tmp$calculate_dct_priority_int;
          ELSE
            insert_ptle_p^.ptl_thread := dcte.queue_head;
            dcte.queue_head := next_ptlo;
          IFEND;
          tmv$dct [insert_ptle_p^.dispatching_priority] := dcte;
        IFEND;

        low_prio_cst_p^.next_ptlo_to_dispatch := ptlo;
        low_prio_cst_p^.dispatching_priority_integer := tmv$dispatch_priority_integer
              [ptle_p^.dispatching_priority];
        low_prio_cst_p^.dispatch_control.call_dispatcher := TRUE;
        ptle_p^.status := tmc$ts_ready_and_selected;
        ijle_p^.executing_task_count := ijle_p^.executing_task_count + 1;
        IF (low_prio_csti <> mtf$cst_p () ^.cst_index) AND (low_priority <> 0) THEN
          mtp$interrupt_processor (mtv$cst0 [low_prio_csti].memory_port_mask);
        IFEND;

        RETURN; {----->

      IFEND; {  low_prio_csti >= 0 }
    IFEND; { attempt_preselection }

{ If no processor is executing a task with a lower priority then the task being readied must be
{ placed in the DCT queue.

    dcte := tmv$dct [ptle_p^.dispatching_priority];

    IF dcte.queue_head = 0 THEN
      ptle_p^.ptl_thread := 0;
      dcte.queue_head := ptlo;
      dcte.queue_tail := ptlo;
      dcte.minor_priority := ptlo;
      dcte.major_priority := ptlo;
      tmv$dispatching_control_sets.ready_tasks := tmv$dispatching_control_sets.ready_tasks +
            $jmt$dispatching_priority_set [jmc$dp_conversion - ptle_p^.dispatching_priority];
      tmp$calculate_dct_priority_int;
      tmv$dct [ptle_p^.dispatching_priority] := dcte;
      RETURN; {----->
    IFEND; { dcte.queue_head = 0 }

    CASE dct_placement OF
    = minor_timeslice_insert =
      ptle_p^.ptl_thread := tmv$ptl_p^ [dcte.minor_priority].ptl_thread;
      tmv$ptl_p^ [dcte.minor_priority].ptl_thread := ptlo;

{ The following is required to insure that the major pointer
{ is never higher than the minor pointer in the DCT.

      IF dcte.minor_priority = dcte.major_priority THEN
        dcte.major_priority := ptlo;
      IFEND;
      dcte.minor_priority := ptlo;
      IF ptle_p^.ptl_thread = 0 THEN
        dcte.queue_tail := ptlo;
      IFEND;
    = major_timeslice_insert =
      ptle_p^.ptl_thread := tmv$ptl_p^ [dcte.major_priority].ptl_thread;
      tmv$ptl_p^ [dcte.major_priority].ptl_thread := ptlo;
      dcte.major_priority := ptlo;
      IF ptle_p^.ptl_thread = 0 THEN
        dcte.queue_tail := ptlo;
      IFEND;
    = tail_timeslice_insert =
      tmv$ptl_p^ [dcte.queue_tail].ptl_thread := ptlo;
      ptle_p^.ptl_thread := 0;
      dcte.queue_tail := ptlo;
    CASEND;

{ If any task in a job has specified a relative task priority, all of the tasks in the job are subject
{ to the relative priority algorithms.
{
{ NOTE: Relative_Priority is set by pmp$set_relative_priority, but there is no caller for the request yet.

    IF ijle_p^.relative_priority_enabled THEN
      p$relative_insert_dct (dct_placement, xcb_p^.relative_task_priority, ptlo, ijle_p, dcte);
    IFEND;

    tmv$dct [ptle_p^.dispatching_priority] := dcte;

  PROCEND p$dct_ready_task;
?? OLDTITLE ??
?? NEWTITLE := '[inline] p$determine_dispatch_priority', EJECT ??

{ PURPOSE:
{   This procedure determines which dispatching priority a job should have and stores it in the IJL.
{
{ DESIGN:
{   If the operator has changed the dispatching priority for a job, that dispatching
{   priority is used.  Otherwise the job is assigned the lesser of the user requested
{   dispatching priority (if there is one) and the dispatching priority defined in the
{   service class table dispatching control sets.

  PROCEDURE [INLINE] p$determine_dispatch_priority
    (    ijle_p: ^jmt$initiated_job_list_entry);

    VAR
      update_scheduling_priority: boolean;

{ The scheduling_dispatching_priority and the dispatching_controls.dispatching_priority will only
{ be different in the case of a task of the job having subsystem locks set and being readied by
{ a task which has a higher dispatching priority. In that instance, the scheduling_dispatching_priority
{ will be updated when the task releases the lock and issues a CYCLE request.

    update_scheduling_priority := ijle_p^.dispatching_control.dispatching_priority =
          ijle_p^.scheduling_dispatching_priority;

    IF (ijle_p^.dispatching_control.operator_set_dispatching_prio = jmc$null_dispatching_priority)
{ } AND (ijle_p^.dispatching_control.user_requested_dispatching_prio = jmc$null_dispatching_priority) THEN
      ijle_p^.dispatching_control.dispatching_priority := jmv$service_classes
            [ijle_p^.job_scheduler_data.service_class]^.attributes.
            dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].dispatching_priority;

    ELSEIF ijle_p^.dispatching_control.operator_set_dispatching_prio <> jmc$null_dispatching_priority THEN
      ijle_p^.dispatching_control.dispatching_priority := ijle_p^.dispatching_control.
            operator_set_dispatching_prio;

    ELSEIF ijle_p^.dispatching_control.user_requested_dispatching_prio <
          jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.
          attributes.dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].
          dispatching_priority THEN
      ijle_p^.dispatching_control.dispatching_priority := ijle_p^.dispatching_control.
            user_requested_dispatching_prio;

    ELSE {User tried to set the priority higher than allowed.
      ijle_p^.dispatching_control.dispatching_priority := jmv$service_classes
            [ijle_p^.job_scheduler_data.service_class]^.attributes.
            dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].dispatching_priority;
    IFEND;

    IF update_scheduling_priority THEN
      ijle_p^.scheduling_dispatching_priority := ijle_p^.dispatching_control.dispatching_priority;
    IFEND;

  PROCEND p$determine_dispatch_priority;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$FIND_NEXT_XCB_CONTINUE', EJECT ??

  PROCEDURE [INLINE] p$find_next_xcb_continue
    (VAR state: tmt$find_next_xcb_state;
     VAR xcb_p: ^ost$execution_control_block);

    VAR
      ijl_bi: jmt$ijl_block_index,
      ijl_bn: jmt$ijl_block_number,
      ijlb_p: ^jmt$initiated_job_list_block,
      inhibit_access: boolean,
      next_ijle_p: ^jmt$initiated_job_list_entry,
      start_index: integer;

    IF (state.next_ptlo = 0) AND (state.search = tmc$fnx_system) THEN
      jmp$unlock_ajl_with_lock (state.ijle_p);
      state.in_use_incremented := FALSE;

      start_index := state.ijl_ordinal.block_index + 1;

    /find_next_job/
      FOR ijl_bn := state.ijl_ordinal.block_number TO jmv$ijl_p.max_block_in_use DO
        ijlb_p := ^jmv$ijl_p.block_p^ [ijl_bn];
        IF (ijlb_p^.index_p <> NIL) AND (ijlb_p^.in_use_count <> 0) THEN
          FOR ijl_bi := start_index TO UPPERVALUE (jmt$ijl_block_index) DO
            next_ijle_p := ^ijlb_p^.index_p^ [ijl_bi];
            IF next_ijle_p^.entry_status <> jmc$ies_entry_free THEN
              state.ijl_ordinal.block_index := ijl_bi;
              state.ijl_ordinal.block_number := ijl_bn;
              tmp$get_xcb_access_status (next_ijle_p, state.ijl_ordinal, inhibit_access);
              state.in_use_incremented := NOT inhibit_access;
              IF NOT inhibit_access THEN
                state.next_ptlo := next_ijle_p^.job_monitor_taskid.index;
                state.ajl_ordinal := next_ijle_p^.ajl_ordinal;
                state.ijle_p := next_ijle_p;
                EXIT /find_next_job/; {----->
              IFEND;
            IFEND;
          FOREND;
          start_index := LOWERVALUE (jmt$ijl_block_index);
        IFEND;
      FOREND /find_next_job/;
    IFEND;

    p$get_next_xcb_from_next_ptlo (state, xcb_p);

  PROCEND p$find_next_xcb_continue;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$FIND_NEXT_XCB_INIT_NON_SYSTEM', EJECT ??

  PROCEDURE [INLINE] p$find_next_xcb_init_non_system
    (    search: tmt$fnx_search_type;
         ijle_p: ^jmt$initiated_job_list_entry;
         ijl_ordinal: jmt$ijl_ordinal;
     VAR state: tmt$find_next_xcb_state;
     VAR xcb_p: ^ost$execution_control_block);

    VAR
      inhibit_access: boolean;

    state.search := search;
    tmp$get_xcb_access_status (ijle_p, ijl_ordinal, inhibit_access);
    state.in_use_incremented := NOT inhibit_access;
    IF (search = tmc$fnx_job) AND inhibit_access THEN
      state.next_ptlo := 0;
    ELSE
      state.ajl_ordinal := ijle_p^.ajl_ordinal;
      state.next_ptlo := ijle_p^.job_monitor_taskid.index;
      state.ijl_ordinal := ijl_ordinal;
      state.ijle_p := ijle_p;
    IFEND;

    p$get_next_xcb_from_next_ptlo (state, xcb_p);

  PROCEND p$find_next_xcb_init_non_system;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$FIND_NEXT_XCB_INIT_SYSTEM', EJECT ??

  PROCEDURE [INLINE] p$find_next_xcb_init_system
    (VAR state: tmt$find_next_xcb_state;
     VAR xcb_p: ^ost$execution_control_block);

    state.search := tmc$fnx_system;
    state.ajl_ordinal := jmv$system_ajl_ordinal;
    state.ijl_ordinal := jmv$system_ijl_ordinal;
    state.in_use_incremented := TRUE;
    jmv$ajl_p^ [jmv$system_ajl_ordinal].in_use := jmv$ajl_p^ [jmv$system_ajl_ordinal].in_use + jmc$lock_ajl;
    state.ijle_p := jmf$ijle_p (jmv$system_ijl_ordinal);
    state.next_ptlo := jmv$ajl_p^ [state.ajl_ordinal].ijle_p^.job_monitor_taskid.index;

    p$get_next_xcb_from_next_ptlo (state, xcb_p);

  PROCEND p$find_next_xcb_init_system;
?? OLDTITLE ??
?? NEWTITLE := '[INLINE] P$FREE_PTL', EJECT ??

{  NOTE : Anyone calling this routine must have tmv$ptl_lock set.
{  The caller must also call the procedure p$remove_ijl to remove the task from the ijl_thread,
{  which links all tasks of a job, if the task being freed is NOT the job monitor task.
{  If all tasks are being freed, the caller can zero out the ijl_thread.

  PROCEDURE [INLINE] p$free_ptl
    (    ptlo: ost$task_index);

    tmv$ptl_p^ [ptlo].status := tmc$ts_null;
    tmv$ptl_p^ [ptlo].dispatching_priority := jmc$null_dispatching_priority;
    tmv$ptl_p^ [ptlo].ptl_thread := 0;
    IF tmv$dct [jmc$null_dispatching_priority].queue_head = 0 THEN
      tmv$dct [jmc$null_dispatching_priority].queue_head := ptlo;
    ELSE
      tmv$ptl_p^ [tmv$dct [jmc$null_dispatching_priority].queue_tail].ptl_thread := ptlo;
    IFEND;
    tmv$dct [jmc$null_dispatching_priority].queue_tail := ptlo;

  PROCEND p$free_ptl;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$GET_NEXT_XCB_FROM_NEXT_PTLO', EJECT ??

  PROCEDURE [INLINE] p$get_next_xcb_from_next_ptlo
    (VAR state: tmt$find_next_xcb_state;
     VAR xcb_p: ^ost$execution_control_block);

    IF state.next_ptlo <> 0 THEN
      xcb_p := #ADDRESS (1, mtc$job_fixed_segment + state.ajl_ordinal, tmv$ptl_p^ [state.next_ptlo].
            xcb_offset);
      state.next_ptlo := tmv$ptl_p^ [state.next_ptlo].ijl_thread;
    ELSE
      xcb_p := NIL;
      IF state.in_use_incremented THEN
        jmp$unlock_ajl_with_lock (state.ijle_p);
        state.in_use_incremented := FALSE;
      IFEND;
    IFEND;

  PROCEND p$get_next_xcb_from_next_ptlo;
?? OLDTITLE ??
?? NEWTITLE := 'P$I_UPDATE_JOB_TASK_ENVIRONMENT', EJECT ??

  PROCEDURE p$i_update_job_task_environment
    (    ijle_p: ^jmt$initiated_job_list_entry;
     VAR state: tmt$find_next_xcb_state;
     VAR xcb_p: ^ost$execution_control_block);

    VAR
      attempt_preselection: boolean,
      dispatching_priority: integer, {must be integer}
      ptle_p: ^tmt$primary_task_list_entry,
      ptlo: ost$task_index;

    WHILE xcb_p <> NIL DO
      IF xcb_p^.dispatching_priority_bias_id <> jmc$dpb_absolute THEN
        IF xcb_p^.dispatching_priority_bias_id = jmc$dpb_positive THEN
          dispatching_priority := ijle_p^.dispatching_control.dispatching_priority +
                xcb_p^.dispatching_priority_bias;
        ELSE
          dispatching_priority := ijle_p^.dispatching_control.dispatching_priority -
                xcb_p^.dispatching_priority_bias;
        IFEND;
        IF dispatching_priority > jmc$max_dispatching_priority THEN
          dispatching_priority := jmc$max_dispatching_priority;
        ELSEIF dispatching_priority < jmc$min_dispatching_priority THEN
          dispatching_priority := jmc$min_dispatching_priority;
        IFEND;
        xcb_p^.dispatching_priority := dispatching_priority;
        xcb_p^.timeslice := jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
              dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].
              dispatching_timeslice;
        IF xcb_p^.system_table_lock_count <= 0 THEN
          ptlo := xcb_p^.global_task_id.index;
          ptle_p := ^tmv$ptl_p^ [ptlo];
          IF ptle_p^.status <= tmc$ts_last_status_in_dct THEN
            p$remove_task_from_dct (ptlo);
            ptle_p^.dispatching_priority := dispatching_priority; {cannot be moved outside of the if!
            attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
            p$dct_ready_task (xcb_p, ijle_p, ptlo, attempt_preselection);
          ELSE
            ptle_p^.dispatching_priority := dispatching_priority;
          IFEND;
          #SPOIL (ptle_p, ptlo);
        IFEND;
      IFEND;
      p$get_next_xcb_from_next_ptlo (state, xcb_p);
    WHILEND;

  PROCEND p$i_update_job_task_environment;
?? OLDTITLE ??
?? NEWTITLE := 'P$IDLE_TASKS_IN_SYSTEM_JOB', EJECT ??

  PROCEDURE p$idle_tasks_in_system_job
    (    idle_resume_sys_task_kind: tmt$idle_resume_sys_task_kind;
     VAR status: syt$monitor_status);

    VAR
      ptlo: ost$task_index,
      xcb_p: ^ost$execution_control_block,
      ready_task_count: integer,
      ijle_p: ^jmt$initiated_job_list_entry,
      tasks_not_swappable_count: 0 .. osc$max_tasks;

    status.normal := TRUE;
    ijle_p := jmv$ajl_p^ [jmv$system_ajl_ordinal].ijle_p;
    tmp$set_lock (tmv$ptl_lock{, mtc$reissue});

{ Scan the IJL thread and mark the entries swapped.
    ptlo := ijle_p^.job_monitor_taskid.index;
    ready_task_count := 0;
    tasks_not_swappable_count := 0;

    IF idle_resume_sys_task_kind = tmc$ir_dm_system_tasks THEN { Idle ONLY the Device_Management tasks. }

      WHILE ptlo <> 0 DO
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + jmv$system_ajl_ordinal, tmv$ptl_p^ [ptlo].xcb_offset);
        IF (xcb_p^.system_task_id = tmc$stid_administer_log) OR
              (xcb_p^.system_task_id = tmc$stid_dm_split_al) OR
              (xcb_p^.system_task_id = tmc$stid_volume_space_managemnt) THEN
          IF (xcb_p^.system_table_lock_count >= osc$system_table_lock_set) OR
                (tmv$ptl_p^ [ptlo].status = tmc$ts_executing) OR
                (tmv$ptl_p^ [ptlo].status = tmc$ts_ready_and_selected) OR
                (xcb_p^.system_table_lock_count > 0) AND ((tmv$ptl_p^ [ptlo].status <
                tmc$ts_timeout_reqexp_shortshrt) OR (tmv$ptl_p^ [ptlo].status > tmc$ts_last_status_in_wait_q))
                THEN
            tasks_not_swappable_count := tasks_not_swappable_count + 1;
            tmv$ptl_p^ [ptlo].idle_status := tmc$is_idle_initiated;
          ELSEIF tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_dct THEN
            p$remove_task_from_dct (ptlo);
            tmv$ptl_p^ [ptlo].status := tmc$ts_ready_but_swapped;
            ready_task_count := ready_task_count + 1;
            tmv$ptl_p^ [ptlo].idle_status := tmc$is_idled_sched_notified;
          ELSE
            tmv$ptl_p^ [ptlo].idle_status := tmc$is_idled;
          IFEND;
        IFEND;
        ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
      WHILEND;

      tmp$clear_lock (tmv$ptl_lock);

      IF tasks_not_swappable_count <> 0 THEN
        { Some Device_Management task is still executing. }
        mtp$set_status_abnormal ('JS', jse$unable_to_idle_all_tasks, status);
      IFEND;

    ELSE { Idle everything EXCEPT the Device_Management tasks. }

      WHILE ptlo <> 0 DO
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + jmv$system_ajl_ordinal, tmv$ptl_p^ [ptlo].xcb_offset);
        IF (xcb_p^.system_task_id <> tmc$stid_administer_log) AND
              (xcb_p^.system_task_id <> tmc$stid_dm_split_al) AND
              (xcb_p^.system_task_id <> tmc$stid_volume_space_managemnt) THEN
          IF (xcb_p^.system_table_lock_count >= osc$system_table_lock_set) OR
                (tmv$ptl_p^ [ptlo].status = tmc$ts_executing) OR
                (tmv$ptl_p^ [ptlo].status = tmc$ts_ready_and_selected) OR
                (xcb_p^.system_table_lock_count > 0) AND ((tmv$ptl_p^ [ptlo].status <
                tmc$ts_timeout_reqexp_shortshrt) OR (tmv$ptl_p^ [ptlo].status > tmc$ts_last_status_in_wait_q))
                THEN
            tasks_not_swappable_count := tasks_not_swappable_count + 1;
            tmv$ptl_p^ [ptlo].idle_status := tmc$is_idle_initiated;
          ELSEIF tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_dct THEN
            p$remove_task_from_dct (ptlo);
            tmv$ptl_p^ [ptlo].status := tmc$ts_ready_but_swapped;
            ready_task_count := ready_task_count + 1;
            tmv$ptl_p^ [ptlo].idle_status := tmc$is_idled_sched_notified;
          ELSE
            tmv$ptl_p^ [ptlo].idle_status := tmc$is_idled;
          IFEND;
        IFEND;
        ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
      WHILEND;

      tmp$clear_lock (tmv$ptl_lock);

      IF tasks_not_swappable_count <> 1 THEN
        { A system task other than the system JOB_MONITOR is still executing. }
        mtp$set_status_abnormal ('JS', jse$unable_to_idle_all_tasks, status);
      IFEND;
    IFEND;

  PROCEND p$idle_tasks_in_system_job;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$INITIATE_SWAP_IF_POSSIBLE', EJECT ??

{  NOTE : Caller must have tmv$ptl_lock set.

  PROCEDURE [INLINE] p$initiate_swap_if_possible
    (    cst_p: ^ost$cpu_state_table);

    VAR
      jcb_p: ^jmt$job_control_block,
      temp_next_cyclic_aging: integer,
      ptlo: ost$task_index;

    ptlo := cst_p^.ijle_p^.job_monitor_taskid.index;
    WHILE (ptlo <> 0) AND (tmv$ptl_p^ [ptlo].idle_status >= tmc$is_idled) DO
      ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
    WHILEND;
    IF ptlo = 0 THEN
      jcb_p := #ADDRESS (1, mtc$job_fixed_segment + cst_p^.ajlo, 0);
      temp_next_cyclic_aging := jcb_p^.next_cyclic_aging_time - #FREE_RUNNING_CLOCK (0);
      IF temp_next_cyclic_aging < 0 THEN
        jcb_p^.next_cyclic_aging_time := 0;
      ELSE
        jcb_p^.next_cyclic_aging_time := temp_next_cyclic_aging;
      IFEND;
      jsp$idle_tasks_complete (cst_p^.ijl_ordinal);
    IFEND;

  PROCEND p$initiate_swap_if_possible;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$INSERT_IJL', EJECT ??

  PROCEDURE [INLINE] p$insert_ijl
    (    taskid: ost$global_task_id;
         cst_p: ^ost$cpu_state_table);

{ Inserts the selected task's PTL entry in the IJL thread for it's job. The first task in the IJL
{ thread is the job monitor task.
{ NOTE: Caller must have tmv$ptl_lock set.

    VAR
      index: ost$task_index;

    index := cst_p^.ijle_p^.job_monitor_taskid.index;
    tmv$ptl_p^ [taskid.index].ijl_thread := tmv$ptl_p^ [index].ijl_thread;
    tmv$ptl_p^ [index].ijl_thread := taskid.index;

  PROCEND p$insert_ijl;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$INSERT_TIMED_WAIT_QUEUE', EJECT ??

  PROCEDURE [INLINE] p$insert_timed_wait_queue
    (    ptlo: ost$task_index);

{  Adds a task to tmv$timed_wait_queue. Tasks are arranged in the queue in ascending order according
{  to their END_OF_WAIT_TIME.
{  NOTE : Caller must have tmv$ptl_lock set.

    VAR
      end_of_wait_time: integer,
      next_index: ost$task_index,
      previous_index: ost$task_index;

    next_index := tmv$timed_wait_queue.head;
    previous_index := 0;
    end_of_wait_time := tmv$ptl_p^ [ptlo].end_of_wait_time;

    IF tmv$timed_wait_queue.head = 0 THEN
      tmv$timed_wait_queue.head := ptlo;
      tmv$timed_wait_queue.tail := ptlo;
    ELSE
      WHILE (tmv$ptl_p^ [next_index].end_of_wait_time <= end_of_wait_time) AND (next_index <> 0) AND
            (next_index <> ptlo) DO
        previous_index := next_index;
        next_index := tmv$ptl_p^ [next_index].queue_link.head;
      WHILEND;

      IF ptlo = next_index THEN {Dont put this in the while loop - it kills optimization.}
        mtp$error_stop ('TM02.5 - already queued');
      IFEND;

      tmv$ptl_p^ [ptlo].queue_link.head := next_index;
      IF next_index = tmv$timed_wait_queue.head THEN
        tmv$timed_wait_queue.head := ptlo;
      ELSE
        tmv$ptl_p^ [previous_index].queue_link.head := ptlo;
      IFEND;
      tmv$ptl_p^ [ptlo].queue_link.tail := previous_index;
      IF previous_index = tmv$timed_wait_queue.tail THEN
        tmv$timed_wait_queue.tail := ptlo;
      ELSE
        tmv$ptl_p^ [next_index].queue_link.tail := ptlo;
      IFEND;
    IFEND;

  PROCEND p$insert_timed_wait_queue;
?? OLDTITLE ??
?? NEWTITLE := 'P$RELATIVE_INSERT_DCT', EJECT ??

{This request simply groups the different inlined relative insert procedures together.
{This adds another call to p$dct_ready_task, but helps to optimize code generation.
{And, anyway, relative priority is never enabled anyway....

  PROCEDURE p$relative_insert_dct
    (    dct_placement: t$dct_placement;
         relative_task_priority: 0 .. 255;
         ptlo: ost$task_index;
         ijle_p: ^jmt$initiated_job_list_entry;
     VAR dcte: tmt$dct_entry);

    IF ijle_p^.statistics.ready_task_count > 1 THEN
      CASE dct_placement OF
      = minor_timeslice_insert =
        p$relative_insert_minor_dct (relative_task_priority, ptlo, ijle_p, dcte);
      = major_timeslice_insert =
        p$relative_insert_major_dct (relative_task_priority, ptlo, ijle_p, dcte);
      = tail_timeslice_insert =
        p$relative_insert_tail_dct (relative_task_priority, ptlo, ijle_p, dcte);
      CASEND;
    IFEND;

  PROCEND p$relative_insert_dct;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$RELATIVE_INSERT_MAJOR_DCT', EJECT ??

  PROCEDURE [INLINE] p$relative_insert_major_dct
    (    relative_priority: 0 .. 255;
         ptlo: ost$task_index;
         ijl_p: ^jmt$initiated_job_list_entry;
     VAR dcte: tmt$dct_entry);

{ The following procedure is responsible for making sure a task which was
{ inserted in the MAJOR timeslice position is corrected prioritized with the
{ other tasks of the same job. This job is currently running with relative
{ prioritization enabled. The position of tasks of other jobs can only be
{ improved, they will never regress.

    VAR
      insert_ptlo: ost$task_index,
      next_search_ptlo: ost$task_index,
      save_ptlo: ost$task_index,
      search_ptlo: ost$task_index,
      search_xcb: ^ost$execution_control_block;

    { Insert_ptlo is the most recently moved ptlo.
    { Search_ptlo is the task which we are currently testing for possible movement.
    { Save_ptlo is the last task which was NOT moved.

    insert_ptlo := ptlo;
    search_ptlo := dcte.queue_head;
    save_ptlo := 0;

    { The task has been positioned in the DCT. Now, all the tasks of that
    { job (currently in DCT) must be prioritized. The task has been placed
    { in the major priority position. Tasks above that point are checked to
    { determine if any of them have to be moved below the new task. If the
    { task is in the same job, and has a lower relative priority, the task is
    { moved below the new task.

    WHILE (search_ptlo <> ptlo) DO
      next_search_ptlo := tmv$ptl_p^ [search_ptlo].ptl_thread;
      IF (tmv$ptl_p^ [search_ptlo].ijl_ordinal = tmv$ptl_p^ [ptlo].ijl_ordinal) THEN
        search_xcb := #ADDRESS (1, ijl_p^.ajl_ordinal + mtc$job_fixed_segment,
              tmv$ptl_p^ [search_ptlo].xcb_offset);
        IF (search_xcb^.relative_task_priority < relative_priority) THEN
          IF search_ptlo = dcte.queue_head THEN
            dcte.queue_head := tmv$ptl_p^ [search_ptlo].ptl_thread;
          ELSE
            tmv$ptl_p^ [save_ptlo].ptl_thread := tmv$ptl_p^ [search_ptlo].ptl_thread;
          IFEND;
          IF search_ptlo = dcte.minor_priority THEN
            dcte.minor_priority := tmv$ptl_p^ [search_ptlo].ptl_thread;
          IFEND;
          tmv$ptl_p^ [search_ptlo].ptl_thread := tmv$ptl_p^ [insert_ptlo].ptl_thread;
          tmv$ptl_p^ [insert_ptlo].ptl_thread := search_ptlo;
          insert_ptlo := search_ptlo;
        ELSE
          save_ptlo := search_ptlo;
        IFEND;
      ELSE
        save_ptlo := search_ptlo;
      IFEND;
      search_ptlo := next_search_ptlo;
    WHILEND;

    IF insert_ptlo <> ptlo THEN
      dcte.major_priority := insert_ptlo;
      IF tmv$ptl_p^ [insert_ptlo].ptl_thread = 0 THEN
        dcte.queue_tail := insert_ptlo;
      IFEND;
    ELSE

{ There were not any tasks moved below the new task. We must now check to
{ see if there are any tasks below the new task, which have a relative priority
{ higher than the new task. A search is made of all of the tasks below the new
{ task, the new task is moved below the last task (of the same job) which
{ has a higher relative priority than the new task.

      insert_ptlo := 0;
      search_ptlo := tmv$ptl_p^ [ptlo].ptl_thread;
      WHILE search_ptlo <> 0 DO
        IF (tmv$ptl_p^ [search_ptlo].ijl_ordinal = tmv$ptl_p^ [ptlo].ijl_ordinal) THEN
          search_xcb := #ADDRESS (1, ijl_p^.ajl_ordinal + mtc$job_fixed_segment,
                tmv$ptl_p^ [search_ptlo].xcb_offset);
          IF (search_xcb^.global_task_id <> tmv$null_global_task_id) AND
                (search_xcb^.relative_task_priority > relative_priority) THEN
            insert_ptlo := search_ptlo;
          IFEND;
        IFEND;
        search_ptlo := tmv$ptl_p^ [search_ptlo].ptl_thread;
      WHILEND;
      IF insert_ptlo <> 0 THEN
        IF ptlo = dcte.queue_head THEN
          dcte.queue_head := tmv$ptl_p^ [ptlo].ptl_thread;
        IFEND;
        IF ptlo = dcte.minor_priority THEN
          dcte.minor_priority := tmv$ptl_p^ [ptlo].ptl_thread;
        IFEND;
        IF ptlo = dcte.major_priority THEN
          dcte.major_priority := tmv$ptl_p^ [ptlo].ptl_thread;
        IFEND;
        tmv$ptl_p^ [save_ptlo].ptl_thread := tmv$ptl_p^ [ptlo].ptl_thread;
        tmv$ptl_p^ [ptlo].ptl_thread := tmv$ptl_p^ [insert_ptlo].ptl_thread;
        tmv$ptl_p^ [insert_ptlo].ptl_thread := ptlo;
        IF tmv$ptl_p^ [ptlo].ptl_thread = 0 THEN
          dcte.queue_tail := ptlo;
        IFEND;
      IFEND;
    IFEND;

  PROCEND p$relative_insert_major_dct;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$RELATIVE_INSERT_MINOR_DCT', EJECT ??

  PROCEDURE [INLINE] p$relative_insert_minor_dct
    (    relative_priority: 0 .. 255;
         ptlo: ost$task_index;
         ijl_p: ^jmt$initiated_job_list_entry;
     VAR dcte: tmt$dct_entry);

{ The following procedure is responsible for making sure a task which was
{ inserted in the MINOR timeslice position is corrected prioritized with the
{ other tasks of the same job. This job is currently running with relative
{ prioritization enabled. The position of tasks of other jobs can only be
{ improved, they will never regress.

    VAR
      insert_ptlo: ost$task_index,
      next_search_ptlo: ost$task_index,
      save_ptlo: ost$task_index,
      search_ptlo: ost$task_index,
      search_xcb: ^ost$execution_control_block;

    { Insert_ptlo is the most recently moved ptlo.
    { Search_ptlo is the task which we are currently testing for possible movement.
    { Save_ptlo is the last task which was NOT moved.

    insert_ptlo := ptlo;
    search_ptlo := dcte.queue_head;
    save_ptlo := 0;

    { The task has been positioned in the DCT. Now, all the tasks of that
    { job (currently in DCT) must be prioritized. The task has been placed
    { in the minor priority position. Tasks above that point are checked to
    { determine if any of them have to be moved below the new task. If the
    { task is in the same job, and has a lower relative priority, the task is
    { moved below the new task.

    WHILE (search_ptlo <> ptlo) DO
      next_search_ptlo := tmv$ptl_p^ [search_ptlo].ptl_thread;
      IF (tmv$ptl_p^ [search_ptlo].ijl_ordinal = tmv$ptl_p^ [ptlo].ijl_ordinal) THEN
        search_xcb := #ADDRESS (1, ijl_p^.ajl_ordinal + mtc$job_fixed_segment,
              tmv$ptl_p^ [search_ptlo].xcb_offset);
        IF (search_xcb^.relative_task_priority < relative_priority) THEN
          IF search_ptlo = dcte.queue_head THEN
            dcte.queue_head := tmv$ptl_p^ [search_ptlo].ptl_thread;
          ELSE
            tmv$ptl_p^ [save_ptlo].ptl_thread := tmv$ptl_p^ [search_ptlo].ptl_thread;
          IFEND;
          tmv$ptl_p^ [search_ptlo].ptl_thread := tmv$ptl_p^ [insert_ptlo].ptl_thread;
          tmv$ptl_p^ [insert_ptlo].ptl_thread := search_ptlo;
          insert_ptlo := search_ptlo;
        ELSE
          save_ptlo := search_ptlo;
        IFEND;
      ELSE
        save_ptlo := search_ptlo;
      IFEND;
      search_ptlo := next_search_ptlo;
    WHILEND;

    IF insert_ptlo <> ptlo THEN { One or more tasks have been moved below the new task.
      IF dcte.minor_priority = dcte.major_priority THEN
        dcte.major_priority := insert_ptlo;
      IFEND;
      IF tmv$ptl_p^ [insert_ptlo].ptl_thread = 0 THEN
        dcte.queue_tail := insert_ptlo;
      IFEND;
      dcte.minor_priority := insert_ptlo;
    ELSE

{ There were not any tasks moved below the new task. We must now check to
{ see if there are any tasks below the new task, which have a relative priority
{ higher than the new task. A search is made of all of the tasks below the new
{ task, the new task is moved below the last task (of the same job) which
{ has a higher relative priority than the new task.

      insert_ptlo := 0;
      search_ptlo := tmv$ptl_p^ [ptlo].ptl_thread;
      WHILE search_ptlo <> 0 DO
        IF (tmv$ptl_p^ [search_ptlo].ijl_ordinal = tmv$ptl_p^ [ptlo].ijl_ordinal) THEN
          search_xcb := #ADDRESS (1, ijl_p^.ajl_ordinal + mtc$job_fixed_segment,
                tmv$ptl_p^ [search_ptlo].xcb_offset);
          IF (search_xcb^.relative_task_priority > relative_priority) THEN
            insert_ptlo := search_ptlo;
          IFEND;
        IFEND;
        search_ptlo := tmv$ptl_p^ [search_ptlo].ptl_thread;
      WHILEND;

      IF insert_ptlo <> 0 THEN
        IF ptlo = dcte.queue_head THEN
          dcte.queue_head := tmv$ptl_p^ [ptlo].ptl_thread;
        IFEND;
        IF ptlo = dcte.minor_priority THEN
          dcte.minor_priority := tmv$ptl_p^ [ptlo].ptl_thread;
        IFEND;
        IF insert_ptlo = dcte.major_priority THEN
          dcte.major_priority := ptlo;
        IFEND;
        tmv$ptl_p^ [save_ptlo].ptl_thread := tmv$ptl_p^ [ptlo].ptl_thread;
        tmv$ptl_p^ [ptlo].ptl_thread := tmv$ptl_p^ [insert_ptlo].ptl_thread;
        tmv$ptl_p^ [insert_ptlo].ptl_thread := ptlo;
        IF tmv$ptl_p^ [ptlo].ptl_thread = 0 THEN
          dcte.queue_tail := ptlo;
        IFEND;
      IFEND;
    IFEND;

  PROCEND p$relative_insert_minor_dct;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$RELATIVE_INSERT_TAIL_DCT', EJECT ??

  PROCEDURE [INLINE] p$relative_insert_tail_dct
    (    relative_priority: 0 .. 255;
         ptlo: ost$task_index;
         ijle_p: ^jmt$initiated_job_list_entry;
     VAR dcte: tmt$dct_entry);

    { The new task has been placed at the tail of the DCT.
    { All of the tasks in the DCT are scanned. Any tasks (of the
    { same job) which have a lower relative priority than the new
    { task, are moved below the new task.

    VAR
      insert_ptlo: ost$task_index,
      next_search_ptlo: ost$task_index,
      save_ptlo: ost$task_index,
      search_ptlo: ost$task_index,
      search_xcb: ^ost$execution_control_block;

    { Insert_ptlo is the most recently moved ptlo.
    { Search_ptlo is the task which we are currently testing for possible movement.
    { Save_ptlo is the last task which was NOT moved.

    search_ptlo := dcte.queue_head;
    save_ptlo := 0;
    insert_ptlo := ptlo;

    WHILE (search_ptlo <> ptlo) DO
      next_search_ptlo := tmv$ptl_p^ [search_ptlo].ptl_thread;
      IF (tmv$ptl_p^ [search_ptlo].ijl_ordinal = tmv$ptl_p^ [ptlo].ijl_ordinal) THEN
        search_xcb := #ADDRESS (1, ijle_p^.ajl_ordinal + mtc$job_fixed_segment,
              tmv$ptl_p^ [search_ptlo].xcb_offset);
        IF (search_xcb^.relative_task_priority < relative_priority) THEN
          IF (search_ptlo = dcte.queue_head) THEN
            dcte.queue_head := tmv$ptl_p^ [search_ptlo].ptl_thread;
          IFEND;
          IF (search_ptlo = dcte.minor_priority) THEN
            dcte.minor_priority := tmv$ptl_p^ [search_ptlo].ptl_thread;
          IFEND;
          IF (search_ptlo = dcte.major_priority) THEN
            dcte.major_priority := tmv$ptl_p^ [search_ptlo].ptl_thread;
          IFEND;
          IF save_ptlo <> 0 THEN
            tmv$ptl_p^ [save_ptlo].ptl_thread := tmv$ptl_p^ [search_ptlo].ptl_thread;
          IFEND;
          tmv$ptl_p^ [search_ptlo].ptl_thread := 0;
          tmv$ptl_p^ [insert_ptlo].ptl_thread := search_ptlo;
          insert_ptlo := search_ptlo;
        ELSE
          save_ptlo := search_ptlo;
        IFEND;
      ELSE
        save_ptlo := search_ptlo;
      IFEND;
      search_ptlo := next_search_ptlo;
    WHILEND;

    dcte.queue_tail := insert_ptlo;

  PROCEND p$relative_insert_tail_dct;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$REMOVE_IJL', EJECT ??

  PROCEDURE [INLINE] p$remove_ijl
    (    taskid: ost$global_task_id;
         cst_p: ^ost$cpu_state_table);

{ Remove the PTL entry for the specified task from the IJL thread.
{ NOTE : Caller must have tmv$ptl_lock set.

    VAR
      curr_ptlo: ost$task_index,
      last_ptlo: ost$task_index;

    last_ptlo := 0;
    curr_ptlo := cst_p^.ijle_p^.job_monitor_taskid.index;

  /search_loop/
    WHILE curr_ptlo <> 0 DO
      IF curr_ptlo = taskid.index THEN
        EXIT /search_loop/; {----->
      IFEND;
      last_ptlo := curr_ptlo;
      curr_ptlo := tmv$ptl_p^ [last_ptlo].ijl_thread;
    WHILEND /search_loop/;

    tmv$ptl_p^ [last_ptlo].ijl_thread := tmv$ptl_p^ [curr_ptlo].ijl_thread;
    tmv$ptl_p^ [curr_ptlo].ijl_thread := 0;

  PROCEND p$remove_ijl;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$REMOVE_TASK_FROM_DCT', EJECT ??

  PROCEDURE [INLINE] p$remove_task_from_dct
    (    ptlo: ost$task_index);

{ Removes the current task's PTL entry from the DCT thread.
{ NOTE : Caller must have tmv$ptl_lock set.

    VAR
      dcte: tmt$dct_entry,
      ptle_p: ^tmt$primary_task_list_entry,
      save_ptlo: ost$task_index,
      scan_ptlo: ost$task_index;

    ptle_p := ^tmv$ptl_p^ [ptlo];
    dcte := tmv$dct [ptle_p^.dispatching_priority];

    IF dcte.queue_tail = dcte.queue_head THEN
      IF dcte.queue_head <> ptlo THEN
        mtp$error_stop ('TM--remove task from empty DCT');
      IFEND;
      dcte := v$null_dcte;
      tmv$dispatching_control_sets.ready_tasks := tmv$dispatching_control_sets.ready_tasks -
            $jmt$dispatching_priority_set [jmc$dp_conversion - ptle_p^.dispatching_priority];
      tmp$calculate_dct_priority_int;
    ELSEIF ptlo = dcte.queue_head THEN
      dcte.queue_head := ptle_p^.ptl_thread;
      IF ptlo = dcte.major_priority THEN
        dcte.major_priority := ptle_p^.ptl_thread;
      IFEND;
      IF ptlo = dcte.minor_priority THEN
        dcte.minor_priority := ptle_p^.ptl_thread;
      IFEND;
    ELSE
      scan_ptlo := dcte.queue_head;
      WHILE scan_ptlo <> ptlo DO
        save_ptlo := scan_ptlo;
        scan_ptlo := tmv$ptl_p^ [scan_ptlo].ptl_thread;
        IF scan_ptlo = 0 THEN
          mtp$error_stop ('TM-cant find ptlo to remove from DCT');
        IFEND;
      WHILEND;
      tmv$ptl_p^ [save_ptlo].ptl_thread := tmv$ptl_p^ [ptlo].ptl_thread;
      IF ptlo = dcte.queue_tail THEN
        dcte.queue_tail := save_ptlo;
      IFEND;
      IF ptlo = dcte.major_priority THEN
        dcte.major_priority := save_ptlo;
      IFEND;
      IF ptlo = dcte.minor_priority THEN
        dcte.minor_priority := save_ptlo;
      IFEND;
    IFEND;
    ptle_p^.ptl_thread := 0;
    tmv$dct [ptle_p^.dispatching_priority] := dcte;

  PROCEND p$remove_task_from_dct;
?? OLDTITLE ??
?? NEWTITLE := 'P$REMOVE_TASK_FROM_EXTERNAL_Q', EJECT ??

  PROCEDURE p$remove_task_from_external_q
    (    taskid: ost$global_task_id;
         ijle_p: ^jmt$initiated_job_list_entry;
         ptl_p: ^tmt$primary_task_list_entry);

{  Remove a task from an external queue. This task has been readied by another task.
{  NOTE : Caller must have tmv$ptl_lock set.

    VAR
      status: tmt$task_status,
      queue_link: tmt$task_queue_link,
      xcb_p: ^ost$execution_control_block;

*if false
{debug

    CONST
      c$max_traps = 10;

    VAR
      stop: cell,
      kill: ^cell,
      tmv$ptles_trap_p: [XDCL, #GATE] array [0 .. c$max_traps - 1] of ^tmt$primary_task_list_entry,
      tmv$ptles_trap_index: [XDCL, #GATE] 0 .. c$max_traps - 1 := 0;

{debug end
*ifend

    status := ptl_p^.status;
    IF status = tmc$ts_avail_mod_q_full_wait THEN
{This is currently the only Q that should end up here. (What when we start to use the job event Q?
      queue_link := mmv$avail_mod_wait_queue;
    ELSE
      mtp$error_stop ('TM - Unsupported PTL status');
    IFEND;

*if false
{debug
    tmv$ptles_trap_p [tmv$ptles_trap_index] := ptl_p;
    tmv$ptles_trap_index := tmv$ptles_trap_index MOD c$max_traps;
    IF ptl_p^.status < tmc$ts_first_external_queue THEN
      kill := NIL;
      stop := kill^;
    IFEND;
{debug end
*ifend

    tmv$wait_queue_statistics [status] := tmv$wait_queue_statistics [status] - 1;
    IF ptl_p^.idle_status < tmc$is_idled THEN
      xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);
      p$remove_task_from_q (ptl_p, queue_link);
      ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
      ptl_p^.status := tmc$ts_ready;
      jmv$ajl_p^ [ijle_p^.ajl_ordinal].job_is_good_swap_candidate := FALSE;
      p$dct_ready_task (xcb_p, ijle_p, taskid.index, TRUE {attempt_preselection} );
    ELSE
      p$remove_task_from_q (ptl_p, queue_link);
      ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
      ptl_p^.status := tmc$ts_ready_but_swapped;
      ptl_p^.idle_status := tmc$is_idled_sched_notified;
      jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
    IFEND;

  PROCEND p$remove_task_from_external_q;
?? OLDTITLE ??
?? NEWTITLE := '[inline] PREMOVE_TASK_FROM_FREE_QUEUE', EJECT ??

  PROCEDURE [INLINE] p$remove_task_from_free_queue
    (    ptlo: ost$task_index);

{  Removes a task's PTL entry from the free DCT thread.
{  NOTE : Caller must have tmv$ptl_lock set.

    VAR
      dcte: tmt$dct_entry,
      save_ptlo: ost$task_index,
      scan_ptlo: ost$task_index,
      ptle_p: ^tmt$primary_task_list_entry;

    ptle_p := ^tmv$ptl_p^ [ptlo];
    dcte := tmv$dct [jmc$null_dispatching_priority];

    IF dcte.queue_tail = dcte.queue_head THEN
      IF dcte.queue_head <> ptlo THEN
        mtp$error_stop ('TM--task not in free queue');
      IFEND;
      dcte.queue_head := 0;
      dcte.queue_tail := 0;
    ELSEIF ptlo = dcte.queue_head THEN
      dcte.queue_head := ptle_p^.ptl_thread;
    ELSE
      scan_ptlo := dcte.queue_head;
      WHILE (scan_ptlo <> ptlo) AND (scan_ptlo <> 0) DO
        save_ptlo := scan_ptlo;
        scan_ptlo := tmv$ptl_p^ [scan_ptlo].ptl_thread;
      WHILEND;
      IF scan_ptlo = 0 THEN
        mtp$error_stop ('TM--task not in free queue');
      IFEND;
      tmv$ptl_p^ [save_ptlo].ptl_thread := tmv$ptl_p^ [ptlo].ptl_thread;
      IF ptlo = dcte.queue_tail THEN
        dcte.queue_tail := save_ptlo;
      IFEND;
    IFEND;
    tmv$dct [jmc$null_dispatching_priority] := dcte;

  PROCEND p$remove_task_from_free_queue;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$REMOVE_TASK_FROM_Q', EJECT ??

  PROCEDURE [INLINE] p$remove_task_from_q
    (    ptle_p: ^tmt$primary_task_list_entry;
     VAR queue: tmt$task_queue_link);

{ Removes a task from either the timed wait queue, or a segment lock queue.
    IF ptle_p^.queue_link.head = 0 THEN
      queue.tail := ptle_p^.queue_link.tail;
    ELSE
      tmv$ptl_p^ [ptle_p^.queue_link.head].queue_link.tail := ptle_p^.queue_link.tail;
    IFEND;

    IF ptle_p^.queue_link.tail = 0 THEN
      queue.head := ptle_p^.queue_link.head;
    ELSE
      tmv$ptl_p^ [ptle_p^.queue_link.tail].queue_link.head := ptle_p^.queue_link.head;
    IFEND;

    ptle_p^.queue_link.head := 0;
    ptle_p^.queue_link.tail := 0;

  PROCEND p$remove_task_from_q;
?? OLDTITLE ??
?? NEWTITLE := 'P$REMOVE_TASK_FROM_SEG_LOCK_Q', EJECT ??

  PROCEDURE p$remove_task_from_seg_lock_q
    (    taskid: ost$global_task_id;
         ijle_p: ^jmt$initiated_job_list_entry;
         ptl_p: ^tmt$primary_task_list_entry);

{  Remove a task from the segment lock queue. This task has been readied by another task. It will NOT
{  have the segment lock.
{  NOTE : Caller must have tmv$ptl_lock set.

    VAR
      asti: mmt$ast_index,
      fde_p: gft$locked_file_desc_entry_p,
      found: boolean,
      queue_link: tmt$task_queue_link,
      sdtx_p: ^mmt$segment_descriptor_extended,
      segnum: ost$segment,
      task_rb: ^mmt$rb_lock_unlock_segment,
      xcb_p: ^ost$execution_control_block;

    found := FALSE;
    IF ptl_p^.idle_status < tmc$is_idled THEN
      xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);
      task_rb := #LOC (xcb_p^.xp.x_registers [0]);
      segnum := #SEGMENT (task_rb^.pva);
      sdtx_p := mmp$get_sdtx_entry_p (xcb_p, segnum);
      gfp$mtr_get_locked_fde_p (sdtx_p^.sfid, ijle_p, fde_p);
      p$remove_task_from_q (ptl_p, fde_p^.segment_lock.task_queue);
      ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
      ptl_p^.status := tmc$ts_ready;
      jmv$ajl_p^ [ijle_p^.ajl_ordinal].job_is_good_swap_candidate := FALSE;
      p$dct_ready_task (xcb_p, ijle_p, taskid.index, TRUE {attempt_preselection} );
    ELSE

    /search_loop/
      FOR asti := LOWERBOUND (mmv$ast_p^) TO UPPERBOUND (mmv$ast_p^) DO
        IF (mmv$ast_p^ [asti].in_use) AND (mmv$ast_p^ [asti].sfid.residence = gfc$tr_system) THEN
          gfp$mtr_get_locked_fde_p (mmv$ast_p^ [asti].sfid, NIL, fde_p);
          queue_link := fde_p^.segment_lock.task_queue;
          WHILE NOT found AND (queue_link.head <> 0) DO
            IF queue_link.head = taskid.index THEN
              found := TRUE;
              EXIT /search_loop/; {----->
            ELSE
              queue_link := tmv$ptl_p^ [queue_link.head].queue_link;
            IFEND;
          WHILEND;
        IFEND;
      FOREND /search_loop/;

      IF NOT found THEN
        mtp$error_stop ('TM112-task not found in seg lock Q');
      IFEND;

      p$remove_task_from_q (ptl_p, fde_p^.segment_lock.task_queue);
      ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
      ptl_p^.status := tmc$ts_ready_but_swapped;
      ptl_p^.idle_status := tmc$is_idled_sched_notified;
      jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
    IFEND;
    tmv$wait_queue_statistics [tmc$ts_segment_lock_wait] :=
          tmv$wait_queue_statistics [tmc$ts_segment_lock_wait] - 1;

  PROCEND p$remove_task_from_seg_lock_q;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$RESET_DISPATCHING_PRIORITY', EJECT ??

  PROCEDURE [INLINE] p$reset_dispatching_priority
    (    ijle_p: ^jmt$initiated_job_list_entry;
         ijl_ordinal: jmt$ijl_ordinal);

{ A new command line has been scanned for an interactive job or the job is through critical initiation;
{ the first dispatching control set for the class is used.

    ijle_p^.interactive_task_gtid := tmv$null_global_task_id;

    ijle_p^.dispatching_control.dispatching_control_index := jmc$min_dispatching_control;
    ijle_p^.dispatching_control.service_remaining := jmv$service_classes
          [ijle_p^.job_scheduler_data.service_class]^.attributes.dispatching_control [1].service_limit;
    ijle_p^.cp_time_last_dc_reset := ijle_p^.statistics.cp_time.time_spent_in_job_mode +
          ijle_p^.statistics.cp_time.time_spent_in_mtr_mode;
    p$determine_dispatch_priority (ijle_p);
    p$update_job_task_environment (ijle_p, ijl_ordinal);

  PROCEND p$reset_dispatching_priority;
?? OLDTITLE ??
?? NEWTITLE := 'P$RESTART_TASKS_IN_SYSTEM_JOB', EJECT ??

  PROCEDURE p$restart_tasks_in_system_job
    (    idle_resume_sys_task_kind: tmt$idle_resume_sys_task_kind;
     VAR status: syt$monitor_status);

    VAR
      attempt_preselection: boolean,
      ptlo: ost$task_index,
      ready_task_count: integer,
      xcb_p: ^ost$execution_control_block,
      ijle_p: ^jmt$initiated_job_list_entry;

    status.normal := TRUE;
    ijle_p := jmf$ijle_p (jmv$ajl_p^ [jmv$system_ajl_ordinal].ijl_ordinal);

    IF jmc$dsw_update_keypoint_masks IN ijle_p^.delayed_swapin_work THEN
      osp$update_job_keypoint_mask (ijle_p, jmv$system_ijl_ordinal);
    IFEND;

    ptlo := ijle_p^.job_monitor_taskid.index;

{ Scan the IJL thread and mark the entries swapped in.

    ready_task_count := 0;

{ Not sure what to do here. Will need further thought.
    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});

    IF idle_resume_sys_task_kind = tmc$ir_dm_system_tasks THEN { Restart ONLY the Device_Management tasks. }

      WHILE ptlo <> 0 DO
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + jmv$system_ajl_ordinal, tmv$ptl_p^ [ptlo].xcb_offset);
        IF (xcb_p^.system_task_id = tmc$stid_administer_log) OR
              (xcb_p^.system_task_id = tmc$stid_dm_split_al) OR
              (xcb_p^.system_task_id = tmc$stid_volume_space_managemnt) THEN
          IF (tmv$ptl_p^ [ptlo].idle_status >= tmc$is_idled) THEN
            IF tmv$ptl_p^ [ptlo].status = tmc$ts_ready_but_swapped THEN
              tmv$ptl_p^ [ptlo].status := tmc$ts_ready;
              ready_task_count := ready_task_count + 1;
            IFEND;
            IF tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_dct THEN
              attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
              p$dct_ready_task (xcb_p, ijle_p, ptlo, attempt_preselection);
            IFEND;
          IFEND;
          tmv$ptl_p^ [ptlo].idle_status := tmc$is_not_idled;
        IFEND;
        ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
      WHILEND;

      tmp$clear_lock (tmv$ptl_lock);

    ELSE { Restart everything EXCEPT the Device_Management tasks. }

      WHILE ptlo <> 0 DO
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + jmv$system_ajl_ordinal, tmv$ptl_p^ [ptlo].xcb_offset);
        IF (xcb_p^.system_task_id <> tmc$stid_administer_log) AND
              (xcb_p^.system_task_id <> tmc$stid_dm_split_al) AND
              (xcb_p^.system_task_id <> tmc$stid_volume_space_managemnt) THEN
          IF (tmv$ptl_p^ [ptlo].idle_status >= tmc$is_idled) THEN
            IF tmv$ptl_p^ [ptlo].status = tmc$ts_ready_but_swapped THEN
              tmv$ptl_p^ [ptlo].status := tmc$ts_ready;
              ready_task_count := ready_task_count + 1;
            IFEND;
            IF tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_dct THEN
              attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
              p$dct_ready_task (xcb_p, ijle_p, ptlo, attempt_preselection);
            IFEND;
          IFEND;
          tmv$ptl_p^ [ptlo].idle_status := tmc$is_not_idled;
        IFEND;
        ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
      WHILEND;

      tmp$clear_lock (tmv$ptl_lock);
    IFEND;

  PROCEND p$restart_tasks_in_system_job;
?? OLDTITLE ??
?? NEWTITLE := 'P$SET_SWAPOUT_CANDIDATE', EJECT ??

{  NOTE : Caller must have tmv$ptl_lock set.

  PROCEDURE p$set_swapout_candidate
    (    ajl_ordinal: jmt$ajl_ordinal);

    VAR
      ijle_p: ^jmt$initiated_job_list_entry,
      jcb_p: ^jmt$job_control_block,
      ptlo: ost$task_index,
      temp_next_cyclic_aging: integer;

    ijle_p := jmv$ajl_p^ [ajl_ordinal].ijle_p;
    IF (ajl_ordinal = jmv$system_ajl_ordinal)
{ } OR (NOT jmv$swap_jobs_in_long_wait)
{ } OR (NOT jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
          swap_jobs_in_longwait) THEN
      RETURN; {----->
    IFEND;

{ Scan the IJL thread and mark the entries swapped.
    ptlo := ijle_p^.job_monitor_taskid.index;

    WHILE ptlo <> 0 DO
      tmv$ptl_p^ [ptlo].idle_status := tmc$is_idled;
      ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
    WHILEND;

    jcb_p := #ADDRESS (1, mtc$job_fixed_segment + ajl_ordinal, 0);
    temp_next_cyclic_aging := jcb_p^.next_cyclic_aging_time - #FREE_RUNNING_CLOCK (0);
    IF temp_next_cyclic_aging < 0 THEN
      jcb_p^.next_cyclic_aging_time := 0;
    ELSE
      jcb_p^.next_cyclic_aging_time := temp_next_cyclic_aging;
    IFEND;

    jmp$set_swapout_candidate (ajl_ordinal, jmc$sr_long_wait);

  PROCEND p$set_swapout_candidate;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$STOP_IF_BAD_TASKID', EJECT ??

  PROCEDURE [INLINE] p$stop_if_bad_taskid
    (    taskid: ost$global_task_id);

{ NOTE: The caller of this procedure MUST set the PTL lock.

    IF (taskid = tmv$null_global_task_id) OR (taskid.index > UPPERBOUND (tmv$ptl_p^)) OR
          (tmv$ptl_p^ [taskid.index].sequence_number <> taskid.seqno) OR
          (tmv$ptl_p^ [taskid.index].status = tmc$ts_null) THEN
      mtp$error_stop ('TM01 - taskid error');
    IFEND;

  PROCEND p$stop_if_bad_taskid;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$UPDATE_CP_STATISTICS', EJECT ??

  PROCEDURE [INLINE] p$update_cp_statistics
    (    cst_p: ^ost$cpu_state_table);

{  Updates the cp statistics in the IJL, XCB, JCB and the system statistics record.

    VAR
      accumulated_job_cptime: integer,
      accumulated_monitor_cptime: integer,
      dispatching_priority: jmt$dispatching_priority,
      excess_cp_time_used: integer,
      ijle_p: ^jmt$initiated_job_list_entry,
      minor_time_slice_remaining: integer,
      major_time_slice_remaining: integer,
      status: syt$monitor_status,
      task_time_slice_used: integer,
      total_cptime: integer,
      xcb_p: ^ost$execution_control_block;

{ Update cp statistics in IJL.
    ijle_p := cst_p^.ijle_p;
    accumulated_job_cptime := cst_p^.accumulated_job_cptime;
    accumulated_monitor_cptime := cst_p^.accumulated_monitor_cptime;

    ijle_p^.statistics.cp_time.time_spent_in_mtr_mode := ijle_p^.statistics.cp_time.time_spent_in_mtr_mode +
          accumulated_monitor_cptime;
    ijle_p^.statistics.cp_time.time_spent_in_job_mode := ijle_p^.statistics.cp_time.time_spent_in_job_mode +
          accumulated_job_cptime;

    task_time_slice_used := accumulated_job_cptime + accumulated_monitor_cptime;

{ Update the dispatching priority controls.
    dispatching_priority := cst_p^.dispatching_priority;
    IF tmv$dispatching_controls.controls_defined THEN
      p$update_dispatching_controls (task_time_slice_used, dispatching_priority);
    IFEND;

{ Update system data statistics.
    tmv$cpu_execution_statistics [dispatching_priority].time_spent_in_mtr_mode :=
          tmv$cpu_execution_statistics [dispatching_priority].time_spent_in_mtr_mode +
          accumulated_monitor_cptime;
    tmv$cpu_execution_statistics [dispatching_priority].time_spent_in_job_mode :=
          tmv$cpu_execution_statistics [dispatching_priority].time_spent_in_job_mode + accumulated_job_cptime;

{ Update cp statistics in XCB.
    xcb_p := cst_p^.xcb_p;
    xcb_p^.cp_time.time_spent_in_mtr_mode := xcb_p^.cp_time.time_spent_in_mtr_mode +
          accumulated_monitor_cptime;
    xcb_p^.cp_time.time_spent_in_job_mode := xcb_p^.cp_time.time_spent_in_job_mode + accumulated_job_cptime;

    IF task_time_slice_used >= ijle_p^.dispatching_control.service_remaining THEN

{ Reset the dispatching control for the task, based on the service class dispatching controls.
      excess_cp_time_used := task_time_slice_used - ijle_p^.dispatching_control.service_remaining;
      tmp$reset_dispatching_control (ijle_p, cst_p^.ijl_ordinal, excess_cp_time_used, TRUE);

    ELSE

{Calculate the time remaining on this tasks time slice.
      ijle_p^.dispatching_control.service_remaining := ijle_p^.dispatching_control.service_remaining -
            task_time_slice_used;
      minor_time_slice_remaining := xcb_p^.timeslice.minor - task_time_slice_used;
      major_time_slice_remaining := xcb_p^.timeslice.major - task_time_slice_used;
      IF minor_time_slice_remaining < 0 THEN
        xcb_p^.timeslice.minor := 0;
      ELSE
        xcb_p^.timeslice.minor := minor_time_slice_remaining;
      IFEND;
      IF major_time_slice_remaining < 0 THEN
        xcb_p^.timeslice.major := 0;
      ELSE
        xcb_p^.timeslice.major := major_time_slice_remaining;
      IFEND;
    IFEND;

{  Send a flag to the job monitor of the current job if the flag interval
{  has expired.

    total_cptime := ijle_p^.statistics.cp_time.time_spent_in_job_mode +
          ijle_p^.statistics.cp_time.time_spent_in_mtr_mode;
    IF total_cptime - cst_p^.jcb_p^.cptime_signal_last_sent >= cst_p^.jcb_p^.signal_interval THEN
      tmp$set_system_flag (cst_p^.jcb_p^.job_monitor_id, avc$monitor_statistics_flag, status);
      cst_p^.jcb_p^.cptime_signal_last_sent := total_cptime;
    IFEND;

  PROCEND p$update_cp_statistics;
?? OLDTITLE ??
?? NEWTITLE := 'P$UPDATE_DEBUG_REGISTERS', EJECT ??

{ PURPOSE:
{   This procedure sets the debugger flag for all tasks.  The next time a task executes, it will trap to
{   reset the debug list and mask in its exchange package.  This procedure is called whenever a breakpoint
{   is selected, set, removed, or modified during a debugger session.

  PROCEDURE p$update_debug_registers;

    VAR
      ptlo: ost$task_index;

    FOR ptlo := 1 TO UPPERBOUND (tmv$ptl_p^) DO
      IF tmv$ptl_p^ [ptlo].status <> tmc$ts_null THEN
        tmv$ptl_p^ [ptlo].monitor_flags := tmv$ptl_p^ [ptlo].monitor_flags +
              $syt$monitor_flags [syc$mf_system_debugger];
      IFEND;
    FOREND;

  PROCEND p$update_debug_registers;
?? OLDTITLE ??
?? NEWTITLE := 'P$UPDATE_DISPATCHING_CONTROLS', EJECT ??

{We do not have dispatching controls defined, so do not make it inline.

  PROCEDURE p$update_dispatching_controls
    (    time_used: integer;
         dispatching_priority: jmt$dispatching_priority);

    VAR
      dps: jmt$dispatching_priority_set,
      dp: jmt$dispatching_priority;

    IF (tmv$dispatching_controls.controls_defined) AND (dispatching_priority < jmc$priority_p9) THEN
      IF time_used >= tmv$dispatching_control_time.time_left_in_interval THEN {RESET THE TABLE}
        tmv$dispatching_control_time := tmv$dispatching_controls.controls;
        tmv$dispatching_control_sets.minimums_to_satisfy := tmv$dispatching_controls.minimums_to_satisfy;
        tmv$dispatching_control_sets.maximums_exceeded := $jmt$dispatching_priority_set [];
        tmv$dispatching_control_sets.enforce_maximums := $jmt$dispatching_priority_set [];
        tmp$calculate_dct_priority_int;
        FOR dp := jmc$priority_p1 TO jmc$priority_p8 DO
          p$update_priority_integer (dp);
        FOREND;
      ELSE
        tmv$dispatching_control_time.time_left_in_interval :=
              tmv$dispatching_control_time.time_left_in_interval - time_used;
        IF dispatching_priority <> jmc$null_dispatching_priority THEN
          dp := jmc$dp_conversion - dispatching_priority;
          dps := $jmt$dispatching_priority_set [dp];
          IF dp IN tmv$dispatching_control_sets.minimums_to_satisfy THEN
            IF time_used >= tmv$dispatching_control_time.dispatching_priority_time [dispatching_priority].
                  minimum_time THEN
              tmv$dispatching_control_sets.minimums_to_satisfy :=
                    tmv$dispatching_control_sets.minimums_to_satisfy - dps;
              tmp$calculate_dct_priority_int;
              p$update_priority_integer (dispatching_priority);
            ELSE
              tmv$dispatching_control_time.dispatching_priority_time [dispatching_priority].minimum_time :=
                    tmv$dispatching_control_time.dispatching_priority_time [dispatching_priority].
                    minimum_time - time_used;
            IFEND;
          IFEND;

          IF (dp IN tmv$dispatching_controls.maximums_defined) AND
                NOT (dp IN tmv$dispatching_control_sets.maximums_exceeded) THEN
            IF time_used >= tmv$dispatching_control_time.dispatching_priority_time [dispatching_priority].
                  maximum_time THEN
              tmv$dispatching_control_sets.maximums_exceeded :=
                    tmv$dispatching_control_sets.maximums_exceeded + dps;
              jmv$idle_dispatching_controls.maximums_exceeded :=
                    jmv$idle_dispatching_controls.maximums_exceeded + dps;
              IF dp IN tmv$dispatching_controls.enforce_maximums THEN
                tmv$dispatching_control_sets.enforce_maximums :=
                      tmv$dispatching_control_sets.enforce_maximums + dps;
              IFEND;
              tmp$calculate_dct_priority_int;
              p$update_priority_integer (dispatching_priority);
            ELSE
              tmv$dispatching_control_time.dispatching_priority_time [dispatching_priority].maximum_time :=
                    tmv$dispatching_control_time.dispatching_priority_time [dispatching_priority].
                    maximum_time - time_used;
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND p$update_dispatching_controls;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$UPDATE_JOB_TASK_ENVIRONMENT', EJECT ??

  PROCEDURE [INLINE] p$update_job_task_environment
    (    ijle_p: ^jmt$initiated_job_list_entry;
         ijl_ordinal: jmt$ijl_ordinal);

    VAR
      xcb_p: ^ost$execution_control_block,
      state: tmt$find_next_xcb_state;

    p$find_next_xcb_init_non_system (tmc$fnx_job, ijle_p, ijl_ordinal, state, xcb_p);

    IF xcb_p = NIL THEN
      ijle_p^.delayed_swapin_work := ijle_p^.delayed_swapin_work +
            $jmt$delayed_swapin_work [jmc$dsw_update_job_task_enviro];
    ELSE
      p$i_update_job_task_environment (ijle_p, state, xcb_p);
    IFEND;

  PROCEND p$update_job_task_environment;
?? OLDTITLE ??
?? NEWTITLE := '[inline] P$UPDATE_PRIORITY_INTEGER', EJECT ??

{ Calculates and changes the integer priority value for a specific dispatching priority, when the
{ priority crosses a minimum allocated or maximum allocated dispatching allocation threshold.

  PROCEDURE [INLINE] p$update_priority_integer
    (    dp: jmt$dispatching_priority);

    VAR
      local_set: tmt$dispatching_control_sets;

    local_set := tmv$dispatching_control_sets;

    local_set.ready_tasks := $jmt$dispatching_priority_set [jmc$dp_conversion - dp] -
          (local_set.enforce_maximums * local_set.maximums_exceeded);
    local_set.enforce_maximums := $jmt$dispatching_priority_set [];
    local_set.minimums_to_satisfy := local_set.minimums_to_satisfy * local_set.ready_tasks;
    local_set.maximums_exceeded := local_set.maximums_exceeded * local_set.ready_tasks;
    local_set.ready_tasks := local_set.ready_tasks XOR (local_set.minimums_to_satisfy +
          local_set.maximums_exceeded);
    #UNCHECKED_CONVERSION (local_set, tmv$dispatch_priority_integer [dp]);

  PROCEND p$update_priority_integer;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, inline] TMP$CALCULATE_DCT_PRIORITY_INT', EJECT ??

{ Calculates the integer priority value for the DCT queues with ready tasks.
{ If there is nothing queued in the DCT, the integer priority will be 0.
{ If there are tasks queued, the integer priority represents the highest allocated dispatching priority.

  PROCEDURE [XDCL, INLINE] tmp$calculate_dct_priority_int;

    VAR
      local_set: tmt$dispatching_control_sets;

    local_set := tmv$dispatching_control_sets;
    local_set.ready_tasks := local_set.ready_tasks - (local_set.enforce_maximums *
          local_set.maximums_exceeded);
    local_set.enforce_maximums := $jmt$dispatching_priority_set [];
    local_set.minimums_to_satisfy := local_set.minimums_to_satisfy * local_set.ready_tasks;
    local_set.maximums_exceeded := local_set.maximums_exceeded * local_set.ready_tasks;
    local_set.ready_tasks := local_set.ready_tasks XOR (local_set.minimums_to_satisfy +
          local_set.maximums_exceeded);

    #UNCHECKED_CONVERSION (local_set, tmv$dct_priority_integer);

  PROCEND tmp$calculate_dct_priority_int;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CAUSE_TASK_SWITCH', EJECT ??

  PROCEDURE [XDCL] tmp$cause_task_switch;

    VAR
      cst_p: ^ost$cpu_state_table,
      ptle_p: ^tmt$primary_task_list_entry;

    cst_p := mtf$cst_p ();
    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    ptle_p := ^tmv$ptl_p^ [cst_p^.taskid.index];
    IF (ptle_p^.new_task_status > tmc$ts_null) AND (ptle_p^.new_task_status <>
          tmc$ts_timeout_reqexp_shortshrt) THEN
      mtp$error_stop ('TM38 - bad call to cause_task_switch');
    IFEND;
    ptle_p^.new_task_status := tmc$ts_timeout_reqexp_shortshrt;
    ptle_p^.end_of_wait_time := #FREE_RUNNING_CLOCK (0) + tmv$cycle_delay_time;
    cst_p^.dispatch_control.call_dispatcher := TRUE;
    IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
      cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
    IFEND;

*if $true(tmc$debug_cycle_requests)
    IF (osv$debug > 0) THEN
      tmv$cycle_trace [ti].code := tmc$cyc_cause_task_switch;
      tmv$cycle_trace [ti].time := #FREE_RUNNING_CLOCK (0);
      ti := ti + 1;
      IF ti > 10000 THEN
        mtp$error_stop ('TM - trace buffer full');
      IFEND;
    IFEND;
*ifend;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$cause_task_switch;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CHANGE_TASKS_170_CP_SELECTS', EJECT ??

{ PURPOSE:
{   This procedure resets the processor selections of all tasks to exclude selection of the dual state CPU
{   when that CPU is dedicated to the 170 system.  The procedure will add the cpus which are currently
{   logically ON to all of the tasks which have selected only the dual state processor.  (This procedure is
{   called when a cpu is dedicated to, or undedicated from, the 170 system.)
{ DESIGN:
{   1). Search for all of the XCBs that have the processor selection of the dual state cpu.
{   2). Change the processor selections in each XCB in the following manner:
{       . If the set of selected processors consists only of the processor which is dedicated to 170, reselect
{         all processors which are logically ON.

  PROCEDURE [XDCL] tmp$change_tasks_170_cp_selects
    (    dedicate_cpu: boolean;
         cpu_to_dedicate: ost$processor_id);

    VAR
      delayed_swapin_work_record: jmt$delayed_swapin_work_record,
      ijle_p: ^jmt$initiated_job_list_entry,
      state: tmt$find_next_xcb_state,
      xcb_p: ^ost$execution_control_block;

    { Set the delayed swapin work bit in the ijl for all jobs.  Only swapped jobs will look at it.

    delayed_swapin_work_record.delayed_swapin_work := $jmt$delayed_swapin_work
          [jmc$dsw_adjust_cpu_selections];
    jsp$set_delayed_swapin_work_mtr (delayed_swapin_work_record);

    { Update the XCB in active jobs.

    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    p$find_next_xcb_init_system (state, xcb_p);

    WHILE xcb_p <> NIL DO
      IF xcb_p^.requested_processor_selections = $ost$processor_id_set [cpu_to_dedicate] THEN
        IF dedicate_cpu THEN
          ijle_p := jmf$ijle_p (tmv$ptl_p^ [xcb_p^.global_task_id.index].ijl_ordinal);
          IF ijle_p^.job_scheduler_data.job_class = jmc$maintenance_job_class THEN
            xcb_p^.processor_selections := mtv$scb.cpus.logically_on;
          ELSE
            xcb_p^.processor_selections := mtv$scb.cpus.available_for_use;
          IFEND;
        ELSE {undedicate}
          xcb_p^.processor_selections := xcb_p^.requested_processor_selections;
        IFEND;
      IFEND;
      p$find_next_xcb_continue (state, xcb_p);
    WHILEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$change_tasks_170_cp_selects;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CHECK_FOR_SWAPOUT_CANDIDATE', EJECT ??

  PROCEDURE [XDCL] tmp$check_for_swapout_candidate
    (    ajl_ordinal: jmt$ajl_ordinal);

    VAR
      ijle_p: ^jmt$initiated_job_list_entry,
      next_ready_time: integer,
      ptlo: ost$task_index,
      xcb_p: ^ost$execution_control_block;

    ijle_p := jmv$ajl_p^ [ajl_ordinal].ijle_p;
    IF (ajl_ordinal = jmv$system_ajl_ordinal)
{ } OR (NOT jmv$swap_jobs_in_long_wait)
{ } OR (NOT jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
          swap_jobs_in_longwait) THEN
      RETURN; {----->
    IFEND;

    ptlo := ijle_p^.job_monitor_taskid.index;
    next_ready_time := 0ffffffffffff(16);

{ Do long wait aging if not already done.
    IF NOT ijle_p^.long_wait_aging_complete THEN
      jsp$long_wait_aging (ijle_p);
      ijle_p^.long_wait_aging_complete := TRUE;
    IFEND;

{ If the job now has a ready task (that condition must be checked with the PTL lock set) or if a
{ task of the job has a system lock set, do NOT swap out the job.
{ Scan the PTL thread for the job and search for next ready time.  If the next ready time of all
{ tasks is greater than the force-long-wait-swap-time, then swap the job out.

    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});

    IF ijle_p^.statistics.ready_task_count > 0 THEN
      tmp$clear_lock (tmv$ptl_lock);
      RETURN; {----->
    IFEND;

    WHILE ptlo <> 0 DO
      xcb_p := #ADDRESS (1, ajl_ordinal + mtc$job_fixed_segment, tmv$ptl_p^ [ptlo].xcb_offset);
      IF xcb_p^.system_table_lock_count <> 0 THEN
        tmp$clear_lock (tmv$ptl_lock);
        RETURN; {----->
      ELSEIF (tmv$ptl_p^ [ptlo].status >= tmc$ts_first_status_in_wait_q) AND
            (tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_wait_q) AND
            (tmv$ptl_p^ [ptlo].end_of_wait_time < next_ready_time) THEN
        next_ready_time := tmv$ptl_p^ [ptlo].end_of_wait_time;
      IFEND;
      ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
    WHILEND;

    IF (next_ready_time - #FREE_RUNNING_CLOCK (0)) > tmv$long_wait_force_swap_time THEN
      p$set_swapout_candidate (ajl_ordinal);
    IFEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$check_for_swapout_candidate;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CHECK_TASKID', EJECT ??

  PROCEDURE [XDCL] tmp$check_taskid
    (    taskid: ost$global_task_id;
         option: tmt$option;
     VAR status: syt$monitor_status);

*copyc tmh$check_taskid

    status.normal := TRUE;
    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
{   mtv$ptl_recovery_info.class := mtc$ignore;
    IF (taskid = tmv$null_global_task_id) OR (taskid.index > UPPERBOUND (tmv$ptl_p^)) OR
          (tmv$ptl_p^ [taskid.index].sequence_number <> taskid.seqno) OR
          (tmv$ptl_p^ [taskid.index].status = tmc$ts_null) THEN
      tmp$clear_lock (tmv$ptl_lock);
      IF option = tmc$opt_return THEN
        mtp$set_status_abnormal ('TM', tme$invalid_global_taskid, status);
        RETURN; {----->
      ELSE
        mtp$error_stop ('TM01 - taskid error');
      IFEND;
    IFEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$check_taskid;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CHECK_TASKID_WITH_LOCK_SET', EJECT ??

  PROCEDURE [XDCL] tmp$check_taskid_with_lock_set
    (    taskid: ost$global_task_id;
         option: tmt$option;
     VAR status: syt$monitor_status);

*copyc tmh$check_taskid_with_lock_set

    status.normal := TRUE;
    IF (taskid = tmv$null_global_task_id) OR (taskid.index > UPPERBOUND (tmv$ptl_p^)) OR
          (tmv$ptl_p^ [taskid.index].sequence_number <> taskid.seqno) OR
          (tmv$ptl_p^ [taskid.index].status = tmc$ts_null) THEN
      IF option = tmc$opt_return THEN
        mtp$set_status_abnormal ('TM', tme$invalid_global_taskid, status);
        RETURN; {----->
      ELSE
        mtp$error_stop ('TM01 - taskid error');
      IFEND;
    IFEND;

  PROCEND tmp$check_taskid_with_lock_set;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CHECK_TIMED_WAIT_NOT_QUEUED', EJECT ??

  PROCEDURE [XDCL] tmp$check_timed_wait_not_queued
    (    time_next_scan_wait_not_queued: integer);

    VAR
      ptlo: ost$task_index;

    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});

    FOR ptlo := 1 TO UPPERBOUND (tmv$ptl_p^) DO
      IF (tmv$ptl_p^ [ptlo].status = tmc$ts_timed_wait_not_queued) AND
            (tmv$ptl_p^ [ptlo].end_of_wait_time <= time_next_scan_wait_not_queued) THEN
        tmv$ptl_p^ [ptlo].status := tmc$ts_timeout_reqexp_longvlong;
        p$insert_timed_wait_queue (ptlo);
      IFEND;
    FOREND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$check_timed_wait_not_queued;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CREATE_JOB', EJECT ??

  PROCEDURE [XDCL] tmp$create_job
    (VAR rb: tmt$rb_initiate_job;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$create_job

    TYPE
      t$keypoint_type_translation = packed record
        case boolean of
        = TRUE =
          s: string (5),
        = FALSE =
          f1: 0 .. 0fffff(16),
          f2: 0 .. 0fff(16),
        casend,
      recend;

    VAR
      ajl_ordinal: jmt$ajl_ordinal,
      attempt_preselection: boolean,
      ijl_ordinal: jmt$ijl_ordinal,
      ijle_p: ^jmt$initiated_job_list_entry,
      jcb_p: ^jmt$job_control_block,
      jm: ost$keypoint_mask,
      job_segnum: ost$segment,
      ktt: t$keypoint_type_translation,
      sdt_p: mmt$max_sdt_p,
      segnum: ost$segment,
      xcb_p: ^ost$execution_control_block;

{ Make an entry in the monitor segment table for the JOB FIXED SEGMENT of the new job.
    sdt_p := #ADDRESS (1, cst_p^.ajlo + mtc$job_fixed_segment, cst_p^.xcb_p^.sdt_offset);
    job_segnum := #SEGMENT (rb.xcb_p);
    jmp$assign_ajl_entry (sdt_p^.st [job_segnum].ste.asid, rb.ijlo, jmc$swapping_ajl, FALSE {must assign} ,
          ajl_ordinal, rb.status);
    IF NOT rb.status.normal THEN
      RETURN; {----->
    IFEND;

    rb.ajo := ajl_ordinal;

{ Make an entry in the PTL for the new task.
    segnum := rb.ajo + mtc$job_fixed_segment;
    ijl_ordinal := jmv$ajl_p^ [rb.ajo].ijl_ordinal;
    ijle_p := jmf$ijle_p (ijl_ordinal);
    IF syv$all_jobs_selected_for_debug THEN
      ijle_p^.system_breakpoint_selected := TRUE;
    IFEND;
    xcb_p := #ADDRESS (1, segnum, #OFFSET (rb.xcb_p));
    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});

{   mtv$ptl_recovery_info.ajl_ord := ajl_ordinal;
{   mtv$ptl_recovery_info.subcode := mtc$sc_abort_ajl;

    p$assign_ptl (xcb_p, ijl_ordinal, rb.jmtr_taskid, rb.status);
    IF NOT rb.status.normal THEN
      mtv$monitor_segment_table.st [segnum].ste.vl := osc$vl_invalid_entry;
      null_pva := 0;
      #PURGE_BUFFER (osc$purge_all_page_seg_map, null_pva);
      jmp$free_ajl_with_lock (ijle_p, jmc$swapping_ajl);
      rb.ajo := jmc$null_ajl_ordinal;
      tmp$clear_lock (tmv$ptl_lock);
      RETURN; {----->
    IFEND;
    xcb_p^.global_task_id := rb.jmtr_taskid;
    tmv$total_task_count := tmv$total_task_count + 1;

{ Initialize the IJL entry and the JCB for the job.
    jcb_p := #ADDRESS (1, rb.ajo + mtc$job_fixed_segment, 0);
    jcb_p^.jcb_identifier := 0ff00(16);
    jcb_p^.job_monitor_id := rb.jmtr_taskid;
    jcb_p^.last_execution_time := #FREE_RUNNING_CLOCK (0);
    jcb_p^.ijle_p := ijle_p;
    jcb_p^.ijl_ordinal := ijl_ordinal;
    ijle_p^.swap_status := jmc$iss_executing;
    ijle_p^.sfd_p := NIL;
    ijle_p^.job_fixed_contiguous_pages := 0;
    ijle_p^.statistics.ready_task_count := 1;
    ijle_p^.statistics.tasks_not_in_long_wait := 1;
    ijle_p^.job_monitor_taskid := rb.jmtr_taskid;
    jmp$change_ijl_entry_status (ijle_p, jmc$ies_job_in_memory_non_swap);
    IF syv$perf_keypoints_enabled.swapping_keypoints THEN
      ktt.s := ijle_p^.system_supplied_name (16, 4);
      #KEYPOINT (osk$performance, osk$m * ktt.f1, ptk$new_job_name_1);
      #KEYPOINT (osk$performance, osk$m * ((ktt.f2 * 256) + rb.ajo), ptk$new_job_name_2);
    IFEND;
    jm := $ost$keypoint_mask [];
    IF (osv$keypoint_control.environment = osc$system_keypoints) OR
          (osv$keypoint_control.environment = osc$system_sample_keypoints) THEN
      jm := osv$keypoint_control.jm;
      xcb_p^.keypoint_register_enable := TRUE;
    IFEND;
    IF jm <> $ost$keypoint_mask [] THEN
      xcb_p^.xp.flags := xcb_p^.xp.flags + $ost$flags [osc$keypoint_enable];
    ELSE
      xcb_p^.xp.flags := xcb_p^.xp.flags - $ost$flags [osc$keypoint_enable];
    IFEND;
    xcb_p^.xp.keypoint_mask := jm;

{  Set up the new job's segment table from calling task's segment table.  The xcb segment in calling
{  task will be put in the proper place in the new job's segment table.

    mmp$create_job (rb.ajo, job_segnum, cst_p^.xcb_p, xcb_p);

{ Set the processor selections to the set of currently available cpus.
    IF ijle_p^.job_scheduler_data.job_class = jmc$maintenance_job_class THEN
      xcb_p^.processor_selections := mtv$scb.cpus.logically_on;
    ELSE
      xcb_p^.processor_selections := mtv$scb.cpus.available_for_use;
    IFEND;

{ Insert the PTL entry for the new job into the Dispatch Tables.
    xcb_p^.timeslice := jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
          dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].dispatching_timeslice;
    attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
    p$dct_ready_task (xcb_p, ijle_p, rb.jmtr_taskid.index, attempt_preselection);

{ Increment the count of initiated jobs that scheduler checks. This count must be changed in
{ monitor with the ptl lock set.

    jmv$job_counts.service_class_counts [ijle_p^.job_scheduler_data.service_class].scheduler_initiated_jobs :=
          jmv$job_counts.service_class_counts [ijle_p^.job_scheduler_data.service_class].
          scheduler_initiated_jobs + 1;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$create_job;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CREATE_TASK', EJECT ??

  PROCEDURE [XDCL] tmp$create_task
    (VAR rb: tmt$rb_initiate_task;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$create_task

    VAR
      attempt_preselection: boolean,
      ijle_p: ^jmt$initiated_job_list_entry,
      jm: ost$keypoint_mask,
      wrb: tmt$rb_delay,
      offset: integer,
      xcb_p: ^ost$execution_control_block;

    offset := #OFFSET (rb.xcb_p);
    xcb_p := #ADDRESS (1, cst_p^.ajlo + mtc$job_fixed_segment, offset);
    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.subcode := mtc$sc_creating_task;
    p$assign_ptl (xcb_p, cst_p^.ijl_ordinal, rb.taskid, rb.status);
    IF NOT rb.status.normal THEN
      tmp$clear_lock (tmv$ptl_lock);
      RETURN; {----->
    IFEND;

{ Initialize last lpid to 7 so that segment maps will be purged the first time a task executes.
{ The purge is in task_switch (xcb.last_lpid_for_task <> cst.cst_index).
{ If 8 processors are ever supported in NOS/VE, a new method of ensuring the purge will need to
{ be devised.

    xcb_p^.last_lpid_for_task := 7;

    ijle_p := cst_p^.ijle_p;
    IF tmv$ptl_p^ [cst_p^.taskid.index].idle_status = tmc$is_idle_initiated THEN
      tmv$ptl_p^ [rb.taskid.index].idle_status := tmc$is_idled_sched_notified;
      tmv$ptl_p^ [rb.taskid.index].status := tmc$ts_ready_but_swapped;
      jmp$ready_task_in_swapped_job (cst_p^.ijl_ordinal, ijle_p);
    ELSE
      IF cst_p^.ijl_ordinal = jmv$system_ijl_ordinal THEN
        ijle_p^.job_scheduler_data.service_class := 1;
      IFEND;
      xcb_p^.subsystem_lock_priority_count := 0;
      xcb_p^.dispatching_priority := cst_p^.xcb_p^.dispatching_priority;
      xcb_p^.timeslice := jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
            dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].dispatching_timeslice;
      attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
      IF tmv$tables_initialized THEN
        p$dct_ready_task (xcb_p, ijle_p, rb.taskid.index, attempt_preselection);
      IFEND;
    IFEND;

    IF tmv$tables_initialized THEN
      p$insert_ijl (rb.taskid, cst_p);
    ELSE
      tmv$tables_initialized := TRUE;
    IFEND;

    tmv$total_task_count := tmv$total_task_count + 1;

    ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
    ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
    ijle_p^.task_created_after_last_swap := TRUE;

    xcb_p^.global_task_id := rb.taskid;
    xcb_p^.parent_global_task_id := cst_p^.taskid;

{ Each task inherits its parents keypoint_enable flag.
    xcb_p^.keypoint_enable := cst_p^.xcb_p^.keypoint_enable;

    IF (osv$keypoint_control.environment = osc$system_keypoints) OR
          (osv$keypoint_control.environment = osc$system_sample_keypoints) THEN
      jm := osv$keypoint_control.jm;
      xcb_p^.keypoint_register_enable := TRUE;
    ELSE { check if correct job
      IF xcb_p^.keypoint_enable = TRUE THEN { correct - update masks
        jm := osv$keypoint_control.jm;
        xcb_p^.keypoint_register_enable := TRUE;
      ELSE { different - clear masks
        jm := $ost$keypoint_mask [];
        xcb_p^.keypoint_register_enable := FALSE;
      IFEND;
    IFEND;
    IF jm <> $ost$keypoint_mask [] THEN
      xcb_p^.xp.flags := xcb_p^.xp.flags + $ost$flags [osc$keypoint_enable];
    ELSE
      xcb_p^.xp.flags := xcb_p^.xp.flags - $ost$flags [osc$keypoint_enable];
    IFEND;
    xcb_p^.xp.keypoint_mask := jm;

    mmp$create_task (cst_p^.xcb_p, xcb_p, ijle_p);

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$create_task;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$CYCLE', EJECT ??

  PROCEDURE [XDCL] tmp$cycle
    (VAR rb: tmt$rb_cycle;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$cycle

    VAR
      cst_xcb_p: ^ost$execution_control_block,
      ijle_p: ^jmt$initiated_job_list_entry,
      lock_ptlo: ost$task_index,
      new_scheduling_priority: jmt$dispatching_priority,
      ptlo: ost$task_index,
      state: tmt$find_next_xcb_state,
      xcb_p: ^ost$execution_control_block;

    ptlo := cst_p^.taskid.index;
    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});

    IF NOT tmv$tables_initialized THEN
    ELSE
      cst_xcb_p := cst_p^.xcb_p;
      IF (cst_xcb_p^.system_table_lock_count > 0) AND (cst_xcb_p^.system_table_lock_count < 256) AND
            (cst_xcb_p^.system_give_up_cpu) THEN
        cst_xcb_p^.system_give_up_cpu := FALSE;

      ELSEIF (cst_xcb_p^.system_table_lock_count <= 0) AND
            (cst_xcb_p^.system_give_up_cpu OR cst_xcb_p^.subsystem_give_up_cpu) THEN

        cst_xcb_p^.subsystem_give_up_cpu := FALSE;
        cst_xcb_p^.system_give_up_cpu := FALSE;

{  Reset the task to it's original priority. Also, reset the subsystem lock priority
{  which is maintained in the PTL.

        tmv$ptl_p^ [ptlo].dispatching_priority := cst_xcb_p^.dispatching_priority;
        tmv$ptl_p^ [ptlo].readying_task_priority := 0;

        new_scheduling_priority := cst_p^.ijle_p^.dispatching_control.dispatching_priority;
        p$find_next_xcb_init_non_system (tmc$fnx_job, cst_p^.ijle_p, cst_p^.ijl_ordinal, state, xcb_p);
        WHILE xcb_p <> NIL DO
          IF tmv$ptl_p^ [xcb_p^.global_task_id.index].readying_task_priority > new_scheduling_priority THEN
            new_scheduling_priority := tmv$ptl_p^ [xcb_p^.global_task_id.index].readying_task_priority;
          IFEND;
          p$get_next_xcb_from_next_ptlo (state, xcb_p);
        WHILEND;
        cst_p^.ijle_p^.scheduling_dispatching_priority := new_scheduling_priority;
        cst_xcb_p^.subsystem_lock_priority_count := 0;
        tmv$ptl_p^ [ptlo].ptl_flags.subsystem_locks_set := FALSE;
      ELSEIF tmv$cycle_delay_time > 0 THEN
        tmv$ptl_p^ [ptlo].new_task_status := tmc$ts_timeout_reqexp_shortshrt;
        tmv$ptl_p^ [ptlo].end_of_wait_time := #FREE_RUNNING_CLOCK (0) + tmv$cycle_delay_time;
      IFEND;
    IFEND;

    cst_p^.dispatch_control.call_dispatcher := TRUE;
    IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
      cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
    IFEND;

*if $true(tmc$debug_cycle_requests)
    IF (osv$debug > 0) THEN
      tmv$cycle_trace [ti].code := rb.code;
      tmv$cycle_trace [ti].p1 := rb.p1;
      tmv$cycle_trace [ti].p2 := rb.p2;
      tmv$cycle_trace [ti].time := #FREE_RUNNING_CLOCK (0);
      tmv$cycle_trace [ti].xtask := ptlo;
      lock_ptlo := rb.lock_value DIV 256;
      tmv$cycle_trace [ti].gtid := lock_ptlo;
      tmv$cycle_trace [ti].status := tmv$ptl_p^ [lock_ptlo].status;
      IF tmv$cycle_trace [ti].status = tmc$ts_page_wait THEN
        ijle_p := jmf$ijle_p (tmv$ptl_p^ [lock_ptlo].ijl_ordinal);
        xcb_p := #ADDRESS (1, ijle_p^.ajl_ordinal + mtc$job_fixed_segment, tmv$ptl_p^ [lock_ptlo].xcb_offset);
        tmv$cycle_trace [ti].utp := xcb_p^.page_wait_info.pva;
        tmv$cycle_trace [ti].p := xcb_p^.xp.p_register.pva;
      IFEND;
      ti := ti + 1;
      IF ti > 10000 THEN
        mtp$error_stop ('TM - trace buffer full');
      IFEND;
    IFEND;
*ifend
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$cycle;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$DELAY', EJECT ??

  PROCEDURE [XDCL] tmp$delay
    (VAR rb: tmt$rb_delay;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$delay

    VAR
      ptle_p: ^tmt$primary_task_list_entry;

    IF NOT tmv$tables_initialized THEN
      cst_p^.max_cptime := 20000;
      RETURN; {----->
    IFEND;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
    ptle_p := ^tmv$ptl_p^ [cst_p^.taskid.index];

    IF ptle_p^.monitor_flags <> $syt$monitor_flags [] THEN
      cst_p^.xcb_p^.xp.user_condition_register := cst_p^.xcb_p^.xp.user_condition_register +
            $ost$user_conditions [osc$free_flag];
      cst_p^.xcb_p^.monitor_flags := cst_p^.xcb_p^.monitor_flags + ptle_p^.monitor_flags;
      cst_p^.xcb_p^.system_flags := cst_p^.xcb_p^.system_flags + ptle_p^.system_flags;

      ptle_p^.monitor_flags := $syt$monitor_flags [];
      ptle_p^.system_flags := $tmt$system_flags [];
      tmp$clear_lock (tmv$ptl_lock);
      RETURN; {----->
    IFEND;

    IF rb.requested_wait_time < UPPERVALUE (ost$free_running_clock) THEN
      IF (rb.expected_wait_time < tmv$long_wait_swap_time) OR (cst_p^.xcb_p^.system_table_lock_count > 0) THEN
        ptle_p^.new_task_status := tmc$ts_timeout_reqexp_longlong;
      ELSEIF (rb.expected_wait_time < tmv$timed_wait_not_queued) THEN
        ptle_p^.new_task_status := tmc$ts_timeout_reqexp_longvlong;
      ELSE
        ptle_p^.new_task_status := tmc$ts_timed_wait_not_queued;
      IFEND;
    ELSE
      IF (rb.expected_wait_time < tmv$long_wait_swap_time) OR (cst_p^.xcb_p^.system_table_lock_count > 0) THEN
        ptle_p^.new_task_status := tmc$ts_timeout_reqexp_inflong;
      ELSE
        ptle_p^.new_task_status := tmc$ts_timeout_reqexp_infvlong;
      IFEND;
    IFEND;
    ptle_p^.end_of_wait_time := rb.requested_wait_time;
    tmp$clear_lock (tmv$ptl_lock);
    cst_p^.dispatch_control.call_dispatcher := TRUE;
    IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
      cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
    IFEND;

  PROCEND tmp$delay;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$DEQUEUE_HIGH_PRIORITY_TASK', EJECT ??

  PROCEDURE [XDCL] tmp$dequeue_high_priority_task
    (VAR queue_link: tmt$task_queue_link;
     VAR taskid: ost$global_task_id);

    VAR
      attempt_preselection: boolean,
      ijle_p: ^jmt$initiated_job_list_entry,
      ptl_p: ^tmt$primary_task_list_entry,
      xcb_p: ^ost$execution_control_block;

?? NEWTITLE := '[INLINE] P$FIND_HIGH_PRIORITY_TASK_IN_Q', EJECT ??

    PROCEDURE [INLINE] p$find_high_priority_task_in_q
      (    queue_head: tmt$task_queue_link;
       VAR task_index: ost$task_index);

      VAR
        highest_dispatching_priority: jmt$dispatching_priority,
        queue_link: tmt$task_queue_link;

      highest_dispatching_priority := 0;
      task_index := 0;

      queue_link := queue_head;
      WHILE queue_link.head <> 0 DO
        IF tmv$ptl_p^ [queue_link.head].dispatching_priority > highest_dispatching_priority THEN
          highest_dispatching_priority := tmv$ptl_p^ [queue_link.head].dispatching_priority;
          task_index := queue_link.head;
        IFEND;

        queue_link := tmv$ptl_p^ [queue_link.head].queue_link;
      WHILEND;

    PROCEND p$find_high_priority_task_in_q;
?? OLDTITLE ??
?? EJECT ??

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
    p$find_high_priority_task_in_q (queue_link, taskid.index);

    ptl_p := ^tmv$ptl_p^ [taskid.index];
    taskid.seqno := ptl_p^.sequence_number;
    p$stop_if_bad_taskid (taskid);

{   mtv$ptl_recovery_info.taskid := taskid;
{   mtv$ptl_recovery_info.subcode := mtc$sc_queue_link_fixup;

    ijle_p := jmf$ijle_p (ptl_p^.ijl_ordinal);
    p$remove_task_from_q (ptl_p, queue_link);

    IF ptl_p^.status < tmc$ts_first_external_queue THEN
      IF (ptl_p^.status <> tmc$ts_executing) OR (ptl_p^.new_task_status < tmc$ts_first_external_queue) THEN
        mtp$error_stop ('TM92 - task not queued');
      IFEND;
      tmv$wait_queue_statistics [ptl_p^.new_task_status] :=
            tmv$wait_queue_statistics [ptl_p^.new_task_status] - 1;
      ptl_p^.new_task_status := tmc$ts_null;
    ELSE
      tmv$wait_queue_statistics [ptl_p^.status] := tmv$wait_queue_statistics [ptl_p^.status] - 1;
      IF ptl_p^.idle_status = tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready_but_swapped;
        ptl_p^.idle_status := tmc$is_idled_sched_notified;
        jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
      ELSEIF ptl_p^.idle_status < tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready;
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);
        attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
        p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);
      IFEND;
    IFEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$dequeue_high_priority_task;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$DEQUEUE_TASK', EJECT ??

  PROCEDURE [XDCL] tmp$dequeue_task
    (VAR queue_link: tmt$task_queue_link;
     VAR taskid: ost$global_task_id);

*copyc tmh$dequeue_task

    VAR
      attempt_preselection: boolean,
      ijle_p: ^jmt$initiated_job_list_entry,
      ptl_p: ^tmt$primary_task_list_entry,
      xcb_p: ^ost$execution_control_block;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
    taskid.index := queue_link.head;
    ptl_p := ^tmv$ptl_p^ [taskid.index];
    taskid.seqno := ptl_p^.sequence_number;
    p$stop_if_bad_taskid (taskid);

{   mtv$ptl_recovery_info.taskid := taskid;
{   mtv$ptl_recovery_info.subcode := mtc$sc_queue_link_fixup;

    ijle_p := jmf$ijle_p (ptl_p^.ijl_ordinal);

    IF queue_link.head = queue_link.tail THEN
      queue_link.head := 0;
      queue_link.tail := 0;
    ELSE
      queue_link.head := ptl_p^.queue_link.head;
      tmv$ptl_p^ [queue_link.head].queue_link.tail := 0;
      ptl_p^.queue_link.head := 0;
    IFEND;

    IF ptl_p^.status < tmc$ts_first_external_queue THEN
      IF (ptl_p^.status <> tmc$ts_executing) OR (ptl_p^.new_task_status < tmc$ts_first_external_queue) THEN
        mtp$error_stop ('TM92 - task not queued');
      IFEND;
      tmv$wait_queue_statistics [ptl_p^.new_task_status] :=
            tmv$wait_queue_statistics [ptl_p^.new_task_status] - 1;
      ptl_p^.new_task_status := tmc$ts_null;
    ELSE
      tmv$wait_queue_statistics [ptl_p^.status] := tmv$wait_queue_statistics [ptl_p^.status] - 1;
      IF ptl_p^.idle_status = tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready_but_swapped;
        ptl_p^.idle_status := tmc$is_idled_sched_notified;
        jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
      ELSEIF ptl_p^.idle_status < tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready;
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);
        attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
        p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);
      IFEND;
    IFEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$dequeue_task;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$EXIT_JOB', EJECT ??

  PROCEDURE [XDCL] tmp$exit_job
    (VAR rb: tmt$rb_exit_job;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$exit_job

    VAR
      xcb_p: ^ost$execution_control_block;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.subcode := mtc$sc_job_exiting;
    IF tmv$ptl_p^ [cst_p^.taskid.index].idle_status = tmc$is_idled THEN
      mtp$error_stop ('TM04 - swapped job exiting');
    IFEND;
    IF tmv$ptl_p^ [cst_p^.taskid.index].ijl_thread <> 0 THEN
      mtp$error_stop ('TM - exit job with active task(s).');
    IFEND;

{ Free the PTL entry for the task.
    tmv$total_task_count := tmv$total_task_count - 1;
    cst_p^.ijle_p^.executing_task_count := cst_p^.ijle_p^.executing_task_count - 1;
    p$free_ptl (cst_p^.taskid.index);

{ Decrement the job count that scheduler uses.  This count must be changed in monitor with the ptl lock set.
    jmv$job_counts.service_class_counts [cst_p^.ijle_p^.job_scheduler_data.service_class].
          scheduler_initiated_jobs := jmv$job_counts.service_class_counts
          [cst_p^.ijle_p^.job_scheduler_data.service_class].scheduler_initiated_jobs - 1;

    tmp$clear_lock (tmv$ptl_lock);

{ Delete the current task from the ready string and cause a task switch.
    xcb_p := cst_p^.xcb_p;
    cst_p^.xcb_p := NIL;
    cst_p^.dispatch_control.call_dispatcher := TRUE;
    IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
      cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
    IFEND;

{  Free memory resources of any segments still in jobs address space that are unique to the job.
{  Deletes the job fixed segment from monitor's address space too, can no longer reference the job's xcb.

    mmp$exit_job (xcb_p);

{ Update the service class statistics for the service class this job belongs to.

    jmp$update_service_class_stats (cst_p^.ijle_p);

{ Free the AJL and notify scheduler that the job has terminated.

    jmp$free_ajl_entry (cst_p^.ijle_p, jmc$swapping_ajl);
    jmp$set_job_terminated (cst_p^.ijl_ordinal, cst_p^.ijle_p);

  PROCEND tmp$exit_job;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$FETCH_TASK_STATISTICS', EJECT ??

  PROCEDURE [XDCL] tmp$fetch_task_statistics
    (VAR rb: tmt$rb_fetch_task_statistics;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$fetch_task_statistics

    VAR
      current_pit_value: integer;

    rb.status.normal := TRUE;
    rb.monitor_cptime := cst_p^.xcb_p^.cp_time.time_spent_in_mtr_mode + 0ffffffff(16) -
          #READ_REGISTER (osc$pr_process_interval_timer);

    current_pit_value := cst_p^.xcb_p^.xp.process_interval_timer_1 *
          10000(16) + cst_p^.xcb_p^.xp.process_interval_timer_2;
    IF current_pit_value > 7fffffff(16) THEN
      current_pit_value := current_pit_value - 100000000(16);
    IFEND;
    rb.job_cptime := cst_p^.accumulated_job_cptime - current_pit_value +
          cst_p^.xcb_p^.cp_time.time_spent_in_job_mode;

  PROCEND tmp$fetch_task_statistics;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$FIND_NEXT_QUEUED_TASK', EJECT ??

  PROCEDURE [XDCL] tmp$find_next_queued_task
    (VAR taskid: ost$global_task_id);

    VAR
      ptl_p: ^tmt$primary_task_list_entry;

    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    p$stop_if_bad_taskid (taskid);
    ptl_p := ^tmv$ptl_p^ [taskid.index];
    taskid.index := ptl_p^.queue_link.head;
    taskid.seqno := tmv$ptl_p^ [ptl_p^.queue_link.head].sequence_number;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$find_next_queued_task;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$FIND_NEXT_XCB', EJECT ??

  PROCEDURE [XDCL] tmp$find_next_xcb
    (    search: tmt$fnx_search_type;
         ijle_p: ^jmt$initiated_job_list_entry;
         ijl_ordinal: jmt$ijl_ordinal;
     VAR state: tmt$find_next_xcb_state;
     VAR xcb_p: ^ost$execution_control_block);

*copyc tmhfnx

    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    CASE search OF
    = tmc$fnx_continue =
      p$find_next_xcb_continue (state, xcb_p);
    = tmc$fnx_job, tmc$fnx_swapping_job =
      p$find_next_xcb_init_non_system (search, ijle_p, ijl_ordinal, state, xcb_p);
    = tmc$fnx_system =
      p$find_next_xcb_init_system (state, xcb_p);
    CASEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$find_next_xcb;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$FIND_XCB', EJECT ??

  PROCEDURE [XDCL] tmp$find_xcb
    (    taskid: ost$global_task_id;
     VAR xcb_p: ^ost$execution_control_block;
     VAR ijle_p: ^jmt$initiated_job_list_entry;
     VAR status: syt$monitor_status);

*copyc tmh$find_xcb

    VAR
      inhibit_access: boolean;

    status.normal := TRUE;
    tmp$set_lock (tmv$ptl_lock{, mtc$fixup_ajl});
{   mtv$ptl_recovery_info.taskid := taskid;
{   mtv$ptl_recovery_info.subcode := mtc$sc_unlock_ajl;

    p$check_taskid_with_lock_set (taskid, status);
    IF NOT status.normal THEN
      tmp$clear_lock (tmv$ptl_lock);
      RETURN; {----->
    IFEND;

    ijle_p := jmf$ijle_p (tmv$ptl_p^ [taskid.index].ijl_ordinal);
    tmp$get_xcb_access_status (ijle_p, tmv$ptl_p^ [taskid.index].ijl_ordinal, inhibit_access);
    IF inhibit_access THEN
      mtp$set_status_abnormal ('TM', tme$job_swapped_out, status);
    ELSE
      xcb_p := #ADDRESS (1, ijle_p^.ajl_ordinal + mtc$job_fixed_segment, tmv$ptl_p^ [taskid.index].
            xcb_offset);
    IFEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$find_xcb;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$FREE_UNRECOVERED_TASKS', EJECT ??

{ PURPOSE:
{   This procedure frees the PTL entries for the tasks of a job that is being terminated
{   because it cannot be recoverd.  The total task count is decremented; it was incremented
{   earlier during job recovery when the PTL entries were made.
{   The caller of this procedure MUST set the PTL lock.

  PROCEDURE [XDCL] tmp$free_unrecovered_tasks
    (    ijle_p: ^jmt$initiated_job_list_entry);

    VAR
      next_index: ost$task_index,
      task_index: ost$task_index;

    task_index := ijle_p^.job_monitor_taskid.index;
    WHILE task_index <> 0 DO
      next_index := tmv$ptl_p^ [task_index].ijl_thread;
      IF tmv$ptl_p^ [task_index].ptl_thread <> 0 THEN
        mtp$error_stop ('Unrecovered task--PTL thread not zero');
      IFEND;

{ The procedure p$free_ptl does not clear the ijl thread. Not clearing the field
{ causes a potential problem for the next task using the ptl entry.

      tmv$ptl_p^ [task_index].ijl_thread := 0;
      p$free_ptl (task_index);
      tmv$total_task_count := tmv$total_task_count - 1;
      task_index := next_index;
    WHILEND;

  PROCEND tmp$free_unrecovered_tasks;
?? OLDTITLE ??
?? NEWTITLE := 'TMP$GET_TOP_OF_STACK', EJECT ??

{ PURPOSE:
{   This procedure is used to fetch the value of the TOP-OF-STACK pointer for a specified
{   ring of a specified task.
{
{ DESIGN:
{   The value of the TOS register is determined from the exchange package as follows:
{   If the value of TOS cannot be determined because the task is executing on another
{   processor of a dual CPU system, TOS cannot be determined; a value of 2**31-1 is
{   returned.

  PROCEDURE [XDCL] tmp$get_top_of_stack
    (    taskid: ost$global_task_id;
         ring: ost$valid_ring;
     VAR tos: integer);

    VAR
      ijle_p: ^jmt$initiated_job_list_entry,
      inhibit_access: boolean,
      xcb_p: ^ost$execution_control_block;

    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    p$stop_if_bad_taskid (taskid);
    ijle_p := jmf$ijle_p (tmv$ptl_p^ [taskid.index].ijl_ordinal);

    tmp$get_xcb_access_status (ijle_p, tmv$ptl_p^ [taskid.index].ijl_ordinal, inhibit_access);
    IF inhibit_access THEN
      mtp$error_stop ('TM - XCB not accessible');
    ELSE
      xcb_p := #ADDRESS (1, ijle_p^.ajl_ordinal + mtc$job_fixed_segment, tmv$ptl_p^ [taskid.index].
            xcb_offset);
    IFEND;

    IF ((tmv$ptl_p^ [taskid.index].status = tmc$ts_executing) AND (mtf$cst_p () ^.taskid <> taskid)) OR
          (xcb_p^.stack_pages_saved [ring] = TRUE) THEN
      tos := 7fffffff(16); { TOS cannot be determined if executing on another processor.}
    ELSEIF xcb_p^.xp.p_register.pva.ring > ring THEN
      tos := 0; { TOS is zero if executing in a higher ring.}
    ELSEIF xcb_p^.xp.p_register.pva.ring = ring THEN
      tos := #OFFSET (xcb_p^.xp.a0_dynamic_space_pointer); {TOS in XP.A0  is correct if in same ring.}
    ELSE
      tos := xcb_p^.xp.tos_registers [ring].pva.offset; {TOS in XP.TOS is correct if in lower ring.}
    IFEND;

    jmp$unlock_ajl_with_lock (ijle_p);
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$get_top_of_stack;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$GET_XCB_P', EJECT ??

  PROCEDURE [XDCL] tmp$get_xcb_p
    (    taskid: ost$global_task_id;
     VAR xcb_p: ^ost$execution_control_block;
     VAR ijle_p: ^jmt$initiated_job_list_entry);

*copyc tmh$get_xcb_p

{ NOTE:
{   This procedure will increment the ajl in use count or assign an ajl if xcb access is possible.
{   It is the callers responsibility to decrement it with a call to jmp$free_ajl_entry.

    VAR
      inhibit_access: boolean;

    tmp$set_lock (tmv$ptl_lock{, mtc$fixup_ajl});
{   mtv$ptl_recovery_info.taskid := taskid;
{   mtv$ptl_recovery_info.subcode := mtc$sc_delete_ajl;
    p$stop_if_bad_taskid (taskid);
    ijle_p := jmf$ijle_p (tmv$ptl_p^ [taskid.index].ijl_ordinal);

    tmp$get_xcb_access_status (ijle_p, tmv$ptl_p^ [taskid.index].ijl_ordinal, inhibit_access);
    IF inhibit_access THEN
      xcb_p := NIL;
    ELSE
      xcb_p := #ADDRESS (1, ijle_p^.ajl_ordinal + mtc$job_fixed_segment, tmv$ptl_p^ [taskid.index].
            xcb_offset);
    IFEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$get_xcb_p;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$IDLE_NON_DISPATCHABLE_JOB', EJECT ??

{ PURPOSE:
{   Idles a job whose dispatching priority is currently too low to be dispatched.
{
{ DESIGN:
{   This procedure is called from mmp$periodic when a job is discovered to be non-dispatchable.  The job is
{   swapped out only if all tasks can be idled.

  PROCEDURE [XDCL] tmp$idle_non_dispatchable_job
    (    ajl_ordinal: jmt$ajl_ordinal);

    VAR
      ijle_p: ^jmt$initiated_job_list_entry,
      status: syt$monitor_status;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});

    ijle_p := jmv$ajl_p^ [ajl_ordinal].ijle_p;
    IF ijle_p^.entry_status = jmc$ies_job_in_memory THEN
      tmp$idle_tasks_in_job (ajl_ordinal, jmc$sr_idle_dispatching, status);
      IF status.normal THEN
        jmp$swap_non_dispatchable_job (ajl_ordinal);
      IFEND;
    IFEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$idle_non_dispatchable_job;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$IDLE_TASKS_IN_JOB', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to idle all tasks in a job.
{   NOTE!!! The caller of this procedure MUST set the PTL lock.

  PROCEDURE [XDCL] tmp$idle_tasks_in_job
    (    ajl_ordinal: jmt$ajl_ordinal;
         swapout_reason: jmt$swapout_reasons;
     VAR status: syt$monitor_status);

    VAR
      attempt_preselection: boolean,
      end_ptlo: ost$task_index,
      ijle_p: ^jmt$initiated_job_list_entry,
      jcb_p: ^jmt$job_control_block,
      ptlo: ost$task_index,
      ready_task_count: integer,
      tasks_not_swappable_count: 0 .. osc$max_tasks,
      temp_next_cyclic_aging: integer,
      xcb_p: ^ost$execution_control_block;

    status.normal := TRUE;
    ijle_p := jmv$ajl_p^ [ajl_ordinal].ijle_p;

    jcb_p := #ADDRESS (1, mtc$job_fixed_segment + ajl_ordinal, 0);

{ Reject the request if the job is non-swappable.
    IF jmv$ajl_p^ [ajl_ordinal].ijle_p^.entry_status = jmc$ies_job_in_memory_non_swap THEN
      mtp$set_status_abnormal ('JS', jse$job_executing_non_swappable, status);
      RETURN; {----->
    IFEND;

{ Scan the IJL thread and mark the entries swapped.  If the swapout reason is idle dispatching and ALL
{ tasks cannot be idled, then do not idle any tasks.

    ptlo := ijle_p^.job_monitor_taskid.index;
    ready_task_count := 0;
    tasks_not_swappable_count := 0;

    WHILE ptlo <> 0 DO
      xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ajl_ordinal, tmv$ptl_p^ [ptlo].xcb_offset);
      IF (xcb_p^.system_table_lock_count >= osc$system_table_lock_set) OR
            (tmv$ptl_p^ [ptlo].status = tmc$ts_executing) OR (tmv$ptl_p^ [ptlo].status =
            tmc$ts_ready_and_selected) OR (xcb_p^.system_table_lock_count > 0) AND
            ((tmv$ptl_p^ [ptlo].status < tmc$ts_timeout_reqexp_longlong) OR
            (tmv$ptl_p^ [ptlo].status > tmc$ts_timeout_reqexp_infvlong)) THEN
        IF swapout_reason <> jmc$sr_idle_dispatching THEN
          tasks_not_swappable_count := tasks_not_swappable_count + 1;
          tmv$ptl_p^ [ptlo].idle_status := tmc$is_idle_initiated;
        ELSE
          end_ptlo := ptlo;
          ptlo := ijle_p^.job_monitor_taskid.index;
          WHILE (ptlo <> end_ptlo) DO
            IF (tmv$ptl_p^ [ptlo].idle_status >= tmc$is_idled) THEN
              IF tmv$ptl_p^ [ptlo].status = tmc$ts_ready_but_swapped THEN
                tmv$ptl_p^ [ptlo].status := tmc$ts_ready;
              IFEND;
              IF tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_dct THEN
                attempt_preselection := (ijle_p^.multiprocessing_allowed) OR
                      (ijle_p^.executing_task_count = 0);
                p$dct_ready_task (xcb_p, ijle_p, ptlo, attempt_preselection);
              IFEND;
            IFEND;
            tmv$ptl_p^ [ptlo].idle_status := tmc$is_not_idled;
            ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
          WHILEND;
          mtp$set_status_abnormal ('JS', jse$unable_to_idle_all_tasks, status);
          RETURN; {----->
        IFEND;

      ELSEIF tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_dct THEN
        p$remove_task_from_dct (ptlo);
        tmv$ptl_p^ [ptlo].status := tmc$ts_ready_but_swapped;
        ready_task_count := ready_task_count + 1;
        tmv$ptl_p^ [ptlo].idle_status := tmc$is_idled_sched_notified;
      ELSE
        tmv$ptl_p^ [ptlo].idle_status := tmc$is_idled;
      IFEND;

      IF xcb_p^.system_table_lock_count > 0 THEN
        tmv$ptl_p^ [ptlo].ptl_flags.subsystem_locks_set := TRUE;
      IFEND;

      ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
    WHILEND;

    IF tasks_not_swappable_count <> 0 THEN
      mtp$set_status_abnormal ('JS', jse$unable_to_idle_all_tasks, status);
    ELSE
      temp_next_cyclic_aging := jcb_p^.next_cyclic_aging_time - #FREE_RUNNING_CLOCK (0);
      IF temp_next_cyclic_aging < 0 THEN
        jcb_p^.next_cyclic_aging_time := 0;
      ELSE
        jcb_p^.next_cyclic_aging_time := temp_next_cyclic_aging;
      IFEND;
    IFEND;

  PROCEND tmp$idle_tasks_in_job;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$JOB_RECOVERY_REQUESTS', EJECT ??
*copyc syt$rb_job_recovery

  PROCEDURE [XDCL] tmp$job_recovery_requests
    (VAR rb: syt$rb_job_recovery;
         cst_p: ^ost$cpu_state_table);

    VAR
      j,
      i: integer,
      gtid: ost$global_task_id,
      jmtr_ptlo,
      ptlo: ost$task_index,
      ijle_p: ^jmt$initiated_job_list_entry,
      ptl_p: ^tmt$primary_task_list_entry,
      service_class: jmt$service_class_index;

    rb.status.normal := TRUE;
    CASE rb.subreq OF
    = syc$recover_ptl =
      tmp$set_lock (tmv$ptl_lock{, mtc$abandon});

      FOR i := 1 TO rb.count DO
        IF tmv$ptl_p^ [rb.task_list_p^ [i].gtid.index].dispatching_priority <>
              jmc$null_dispatching_priority THEN
          rb.status.normal := FALSE;
          rb.status.condition := tme$ptl_full;
          tmp$clear_lock (tmv$ptl_lock);
          RETURN; {----->
        IFEND;
      FOREND;

      jmtr_ptlo := jmv$ijl_p.block_p^ [rb.ijlo.block_number].index_p^ [rb.ijlo.block_index].
            job_monitor_taskid.index;
      FOR i := 1 TO rb.count DO
        ptlo := rb.task_list_p^ [i].gtid.index;
        p$remove_task_from_free_queue (ptlo);
        ptl_p := ^tmv$ptl_p^ [ptlo];
        ptl_p^.ptl_thread := 0;
        ptl_p^.status := tmc$ts_timeout_reqexp_inflong;
        ptl_p^.ijl_ordinal := rb.ijlo;
        ptl_p^.xcb_offset := rb.task_list_p^ [i].xcb_offset;
        ptl_p^.dispatching_priority := rb.task_list_p^ [i].dispatching_priority;
        ptl_p^.monitor_flags := $syt$monitor_flags [];
        ptl_p^.system_flags := $tmt$system_flags [];
        ptl_p^.sequence_number := rb.task_list_p^ [i].gtid.seqno;
        ptl_p^.idle_status := tmc$is_idled;
        ptl_p^.queue_link.head := 0;
        ptl_p^.queue_link.tail := 0;
        ptl_p^.end_of_wait_time := 0;

{ Emulate p$insert_ijl here - note special case for first task (jmtr).

        IF ptlo <> jmtr_ptlo THEN
          tmv$ptl_p^ [ptlo].ijl_thread := tmv$ptl_p^ [jmtr_ptlo].ijl_thread;
          tmv$ptl_p^ [jmtr_ptlo].ijl_thread := ptlo;
        IFEND;
        gtid.index := ptlo;
        gtid.seqno := ptl_p^.sequence_number;
        tmp$set_task_ready (gtid, 0 {readying_task_priority} , tmc$rc_ready_conditional_wi);
      FOREND;
      tmp$clear_lock (tmv$ptl_lock);

{ Get an ijl pointer - we need to reset some ijl fields and straighten out some counts.

      ijle_p := jmf$ijle_p (rb.ijlo);

{ Set the swap status of the job to swapout complete; clear the swap queue link fields and
{ relink the job into the swapped_out swap queue.

      ijle_p^.swap_status := jmc$iss_swapout_complete;
      ijle_p^.swap_queue_link.queue_id := jsc$isqi_null;
      ijle_p^.swap_queue_link.backward_link := jmv$null_ijl_ordinal;
      ijle_p^.swap_queue_link.forward_link := jmv$null_ijl_ordinal;
      jsp$relink_swap_queue (rb.ijlo, ijle_p, jsc$isqi_swapped_out);

{ Increment the total task count by the number of tasks in the recovered job.

      tmv$total_task_count := tmv$total_task_count + rb.count;

{ Increment the scheduler initiated job count so that scheduler knows how many jobs of this class
{ there are; this count is normally incremented in jmp$initiate_job_from_scheduler, but for job
{ recovery we'll do it here.

      service_class := ijle_p^.job_scheduler_data.service_class;
      jmv$job_counts.service_class_counts [service_class].scheduler_initiated_jobs :=
            jmv$job_counts.service_class_counts [service_class].scheduler_initiated_jobs + 1;

{ Increment swapped job count so that scheduler knows how many swapped jobs there are.

      jmp$increment_swapped_job_count (ijle_p);

    ELSE

{ unsupported subrequest

    CASEND;

  PROCEND tmp$job_recovery_requests;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$MTR_BEGIN_LOCK_ACTIVITY', EJECT ??

  PROCEDURE [XDCL] tmp$mtr_begin_lock_activity
    (    xcb_p: ^ost$execution_control_block;
         activity: 1 .. 256);

    IF activity = 1 THEN
      IF ((xcb_p^.system_table_lock_count MOD 256) = 255) THEN
        mtp$error_stop ('TM--subsystem table lock count exceeded');
      IFEND;
    IFEND;
    xcb_p^.system_table_lock_count := xcb_p^.system_table_lock_count + activity;

  PROCEND tmp$mtr_begin_lock_activity;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$MTR_END_LOCK_ACTIVITY', EJECT ??

  PROCEDURE [XDCL] tmp$mtr_end_lock_activity
    (    cst_p: ^ost$cpu_state_table;
         activity: 1 .. 256;
     VAR xcb_p: ^ost$execution_control_block);

    VAR
      ijle_p: ^jmt$initiated_job_list_entry,
      new_scheduling_priority: jmt$dispatching_priority,
      ptlo: ost$task_index,
      state: tmt$find_next_xcb_state,
      status: syt$monitor_status,
      temp_xcb_p: ^ost$execution_control_block;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.xcb_p := xcb_p;
{   mtv$ptl_recovery_info.subcode := mtc$sc_adjust_st_locks;

*if false
{ Debug code--verify the lock count.

    IF activity = 256 THEN
      IF xcb_p^.system_table_lock_count < 256 THEN
        mtp$error_stop ('TM--system_table_lock_count 1');
      IFEND;
    ELSEIF activity = 1 THEN
      IF ((xcb_p^.system_table_lock_count MOD 256) = 0) THEN
        mtp$error_stop ('TM--system_table_lock_count 2');
      IFEND;
    ELSE
      mtp$error_stop ('TM--system_table_lock_count 3');
    IFEND;

{ End debug code.
*ifend

    xcb_p^.system_table_lock_count := xcb_p^.system_table_lock_count - activity;
    ptlo := cst_p^.taskid.index;

    IF (xcb_p^.system_give_up_cpu) AND (xcb_p^.system_table_lock_count < 256) AND
          (xcb_p^.system_table_lock_count > 0) THEN

{  Reset the task to it's original priority. If the task has subsystem locks set
{  its correct PTL dispatching priority will be determined when the task is readied.
{  The TMP$DCT_READY_TASK procedure will sort out the priorities.

      tmv$ptl_p^ [ptlo].dispatching_priority := xcb_p^.dispatching_priority;
      xcb_p^.system_give_up_cpu := FALSE;
      cst_p^.dispatch_control.call_dispatcher := TRUE;
      IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
        cst_p^.dispatching_priority_integer := tmv$dispatch_priority_integer [xcb_p^.dispatching_priority];
      IFEND;

    ELSEIF (xcb_p^.system_table_lock_count <= 0) AND (xcb_p^.system_give_up_cpu OR
          xcb_p^.subsystem_give_up_cpu) THEN

      xcb_p^.subsystem_give_up_cpu := FALSE;
      xcb_p^.system_give_up_cpu := FALSE;
      cst_p^.dispatch_control.call_dispatcher := TRUE;
      IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
        cst_p^.dispatching_priority_integer := tmv$dispatch_priority_integer [xcb_p^.dispatching_priority];
      IFEND;

{  Reset the task to it's original priority. Also, reset the subsystem lock priority
{  which is maintained in the PTL.

      tmv$ptl_p^ [ptlo].dispatching_priority := xcb_p^.dispatching_priority;
      tmv$ptl_p^ [ptlo].readying_task_priority := 0;

      ijle_p := jmf$ijle_p (tmv$ptl_p^ [xcb_p^.global_task_id.index].ijl_ordinal);
      new_scheduling_priority := ijle_p^.dispatching_control.dispatching_priority;
      p$find_next_xcb_init_non_system (tmc$fnx_job, ijle_p,
            tmv$ptl_p^ [xcb_p^.global_task_id.index].ijl_ordinal, state, temp_xcb_p);
      WHILE temp_xcb_p <> NIL DO
        IF tmv$ptl_p^ [temp_xcb_p^.global_task_id.index].readying_task_priority > new_scheduling_priority THEN
          new_scheduling_priority := tmv$ptl_p^ [temp_xcb_p^.global_task_id.index].readying_task_priority;
        IFEND;
        p$get_next_xcb_from_next_ptlo (state, temp_xcb_p);
      WHILEND;
      ijle_p^.scheduling_dispatching_priority := new_scheduling_priority;
      xcb_p^.subsystem_lock_priority_count := 0;
      tmv$ptl_p^ [ptlo].ptl_flags.subsystem_locks_set := FALSE;
    IFEND;

    IF xcb_p^.stlc_allocation THEN
      xcb_p^.stlc_allocation := FALSE;
      tmp$set_monitor_flag (xcb_p^.global_task_id, mmc$mf_segment_mgr_flag, status);
    IFEND;

*if $true(tmc$debug_cycle_requests)
    IF (osv$debug > 0) THEN
      tmp$set_lock (tmv$ptl_lock);
      tmv$cycle_trace [ti].code := tmc$cyc_mtr_end_sys_activity;
      tmv$cycle_trace [ti].time := #FREE_RUNNING_CLOCK (0);
      ti := ti + 1;
      IF ti > 10000 THEN
        mtp$error_stop ('TM - trace buffer full');
      IFEND;
      tmp$clear_lock (tmv$ptl_lock);
    IFEND;
*ifend
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$mtr_end_lock_activity;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$MTR_UPDATE_JOB_TASK_ENVIRO', EJECT ??

  PROCEDURE [XDCL] tmp$mtr_update_job_task_enviro
    (VAR rb: tmt$rb_update_job_task_enviro;
         cst_p: ^ost$cpu_state_table);

    VAR
      current_pit_value: integer,
      dispatching_controls: jmt$dispatching_controls,
      i: integer,
      ijle_p: ^jmt$initiated_job_list_entry,
      new_max_ptlo: ost$task_index,
      old_max_ptlo: ost$task_index,
      service_used: integer;

    rb.status.normal := TRUE;
    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    CASE rb.subcode OF
    = tmc$ujte_xp_register =
      CASE rb.register_id OF
      = osc$pr_process_interval_timer =
        current_pit_value := cst_p^.xcb_p^.xp.process_interval_timer_1 *
              10000(16) + cst_p^.xcb_p^.xp.process_interval_timer_2;
        IF current_pit_value > 7fffffff(16) THEN
          current_pit_value := current_pit_value - 100000000(16);
        IFEND;
        cst_p^.accumulated_job_cptime := cst_p^.accumulated_job_cptime + rb.pit_value - current_pit_value;
        cst_p^.xcb_p^.pit_count := cst_p^.xcb_p^.pit_count + rb.pit_value - current_pit_value;
        cst_p^.xcb_p^.xp.process_interval_timer_1 := rb.pit_value DIV 10000(16);
        cst_p^.xcb_p^.xp.process_interval_timer_2 := rb.pit_value MOD 10000(16);
      ELSE
      CASEND;

    = tmc$ujte_dispatching_priority =
      ijle_p := jmf$ijle_p (rb.ijl_ordinal);
      IF ijle_p <> NIL THEN { Verify that the same job is still using this ijl ordinal.
        IF ijle_p^.system_supplied_name <> rb.system_supplied_name THEN
          tmp$clear_lock (tmv$ptl_lock);
          mtp$set_status_abnormal ('JM', jme$non_existent_job, rb.status);
          RETURN; {----->
        IFEND;

        CASE rb.request_origin OF
        = tmc$cpo_operator, tmc$cpo_recovery =

{ A null dispatching priority indicates the operator specified DEFAULT; the system must determine
{ the correct dispatching control set based on total service the job has used.
{ If the operator has specified a dispatching priority, assign the job that priority.

{ If the null priority is coming from job recovery, we have completed job recovery and must now
{ set the dispatching priority back to its original value.  It had been set up to the system job
{ dispatching priority to guarantee that it would swap in and recover.

          IF rb.dispatching_control_info.dispatching_priority = jmc$null_dispatching_priority THEN

            IF rb.request_origin = tmc$cpo_operator THEN
              ijle_p^.dispatching_control.operator_set_dispatching_prio := jmc$null_dispatching_priority;
            IFEND;
            p$calculate_service_used (ijle_p, service_used);
            tmp$reset_dispatching_control (ijle_p, rb.ijl_ordinal, service_used, FALSE);

          ELSE
            ijle_p^.dispatching_control.operator_set_dispatching_prio :=
                  rb.dispatching_control_info.dispatching_priority;
            ijle_p^.dispatching_control.dispatching_priority :=
                  rb.dispatching_control_info.dispatching_priority;
            ijle_p^.dispatching_control.service_remaining := jmc$dc_maximum_service_limit;
            p$update_job_task_environment (ijle_p, rb.ijl_ordinal);
          IFEND;

          IF (ijle_p^.dispatching_control.dispatching_priority <> ijle_p^.scheduling_dispatching_priority)
                THEN
            ijle_p^.scheduling_dispatching_priority := ijle_p^.dispatching_control.dispatching_priority;
          IFEND;
          jmp$set_scheduler_event (jmc$examine_swapin_queue);

        = tmc$cpo_user =

{ Store the user requested dispatching priority, determine which priority is allowed, and update.

          ijle_p^.dispatching_control.user_requested_dispatching_prio :=
                rb.dispatching_control_info.dispatching_priority;
          p$determine_dispatch_priority (ijle_p);
          p$update_job_task_environment (ijle_p, rb.ijl_ordinal);

        = tmc$cpo_set_job_unswappable =

{ A job is set unswappable during job termination.  The job is given system dispatching priority
{ with unlimited service.

          ijle_p^.dispatching_control.dispatching_control_index := jmc$min_dispatching_control;
          ijle_p^.scheduling_dispatching_priority := jmc$priority_system_job;
          ijle_p^.dispatching_control.dispatching_priority := jmc$priority_system_job;
          ijle_p^.dispatching_control.service_remaining := jmc$dc_maximum_service_limit;
          ijle_p^.dispatching_control.operator_set_dispatching_prio := jmc$null_dispatching_priority;
          ijle_p^.dispatching_control.user_requested_dispatching_prio := jmc$null_dispatching_priority;
          p$update_job_task_environment (ijle_p, rb.ijl_ordinal);

        = tmc$cpo_interactive_command, tmc$cpo_save_swap_file_sfid =

{ A new command line has been scanned for an interactive job or the job is through critical initiation;
{ the first dispatching control set for the class is used.

          IF rb.request_origin = tmc$cpo_interactive_command THEN
            ijle_p^.interactive_task_gtid := tmv$null_global_task_id;
          IFEND;
          ijle_p^.dispatching_control.dispatching_control_index := jmc$min_dispatching_control;
          ijle_p^.dispatching_control.service_remaining := jmv$service_classes
                [ijle_p^.job_scheduler_data.service_class]^.attributes.dispatching_control [1].service_limit;
          ijle_p^.cp_time_last_dc_reset := ijle_p^.statistics.cp_time.time_spent_in_job_mode +
                ijle_p^.statistics.cp_time.time_spent_in_mtr_mode;
          p$determine_dispatch_priority (ijle_p);
          p$update_job_task_environment (ijle_p, rb.ijl_ordinal);

        = tmc$cpo_interrupt_restore =

{ Restore the job's dispatching control information to the values saved from before a user interrupt.
{ If the dispatching_control_index is no longer a valid one for the job's service class (the service class
{ has been changed since the dispatching control info was saved), calculate the correct dispatching_
{ control_index based on the CP service the job has used.

          dispatching_controls := jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
                dispatching_control [rb.dispatching_control_info.dispatching_control_index];
          IF (NOT dispatching_controls.set_defined) OR (dispatching_controls.service_limit <
                rb.dispatching_control_info.service_remaining) OR
                (dispatching_controls.dispatching_priority <> rb.dispatching_control_info.
                dispatching_priority) THEN

            p$calculate_service_used (ijle_p, service_used);
            tmp$reset_dispatching_control (ijle_p, rb.ijl_ordinal, service_used, FALSE);
          ELSE
            ijle_p^.dispatching_control.dispatching_control_index :=
                  rb.dispatching_control_info.dispatching_control_index;
            ijle_p^.dispatching_control.service_remaining := rb.dispatching_control_info.service_remaining;
            p$determine_dispatch_priority (ijle_p);
            p$update_job_task_environment (ijle_p, rb.ijl_ordinal);
          IFEND;
        ELSE

        CASEND;

      IFEND;

    = tmc$ujte_set_non_swappable =
      IF tmv$ptl_p^ [cst_p^.taskid.index].idle_status = tmc$is_not_idled THEN
        jmp$change_ijl_entry_status (cst_p^.ijle_p, jmc$ies_job_in_memory_non_swap);
      ELSE
        tmp$reissue_monitor_request;
        cst_p^.dispatch_control.call_dispatcher := TRUE;
      IFEND;

    = tmc$ujte_idle_other_sys_tasks =
      p$idle_tasks_in_system_job (tmc$ir_other_system_tasks, rb.status);

    = tmc$ujte_restart_other_systasks =
      p$restart_tasks_in_system_job (tmc$ir_other_system_tasks, rb.status);

    = tmc$ujte_idle_dm_sys_tasks =
      p$idle_tasks_in_system_job (tmc$ir_dm_system_tasks, rb.status);

    = tmc$ujte_restart_dm_systasks =
      p$restart_tasks_in_system_job (tmc$ir_dm_system_tasks, rb.status);

    = tmc$ujte_expand_ptl =

{   Copy the entries from the old PTL to the new PTL.  Then link the new PTL entries into the free queue.
{   Reset tmv$ptl_p to point to the new expanded ptl.

      old_max_ptlo := UPPERBOUND (tmv$ptl_p^);
      new_max_ptlo := UPPERBOUND (rb.ptl_p^);
      i#move (tmv$ptl_p, rb.ptl_p, #SIZE (tmv$ptl_p^));
      FOR i := old_max_ptlo + 1 TO new_max_ptlo - 1 DO
        rb.ptl_p^ [i].ptl_thread := i + 1;
      FOREND;
      rb.ptl_p^ [new_max_ptlo].ptl_thread := 0;
      tmv$ptl_p := rb.ptl_p;

      IF tmv$dct [jmc$null_dispatching_priority].queue_head = 0 THEN
        tmv$dct [jmc$null_dispatching_priority].queue_head := old_max_ptlo + 1;
      ELSE
        tmv$ptl_p^ [tmv$dct [jmc$null_dispatching_priority].queue_tail].ptl_thread := old_max_ptlo + 1;
      IFEND;
      tmv$dct [jmc$null_dispatching_priority].queue_tail := new_max_ptlo;

    = tmc$ujte_update_debug_masks =
      p$update_debug_registers;

    = tmc$ujte_set_task_terminating =

{ The free_flag is not set here because immediately after the return to job mode,
{ all of the outstanding signals and flags are processed.

      cst_p^.xcb_p^.task_is_terminating := TRUE;
      cst_p^.xcb_p^.monitor_flags := cst_p^.xcb_p^.monitor_flags +
            tmv$ptl_p^ [cst_p^.taskid.index].monitor_flags;
      cst_p^.xcb_p^.system_flags := cst_p^.xcb_p^.system_flags + tmv$ptl_p^ [cst_p^.taskid.index].
            system_flags;
      tmv$ptl_p^ [cst_p^.taskid.index].system_flags := $tmt$system_flags [];
      tmv$ptl_p^ [cst_p^.taskid.index].monitor_flags := $syt$monitor_flags [];

    = tmc$ujte_update_cpu_selections =
      tmp$update_job_task_cpu_selects;

    ELSE

      tmp$clear_lock (tmv$ptl_lock);
      mtp$error_stop ('TM - unimplemented subcode');

    CASEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$mtr_update_job_task_enviro;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$MTR_WAIT', EJECT ??

  PROCEDURE [XDCL] tmp$mtr_wait
    (VAR rb {input, output} : tmt$rb_wait_signal;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$mtr_wait

    VAR
      new_task_status: tmt$task_status,
      ptle_p: ^tmt$primary_task_list_entry,
      readied_ijle_p: ^jmt$initiated_job_list_entry,
      readying_task_priority: jmt$dispatching_priority,
      service_class_p: ^jmt$service_class_attributes;


{ If the request was PMP$READY_TASK_AND_WAIT, the rb.global_taskid contains the taskid of the task
{ to be readied.  That taskid must be a valid taskid.

    rb.status.normal := TRUE;
    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
    IF rb.global_taskid <> tmv$null_global_task_id THEN
      p$check_taskid_with_lock_set (rb.global_taskid, rb.status);
      IF NOT rb.status.normal THEN
        tmp$clear_lock (tmv$ptl_lock);
        RETURN; {----->
      IFEND;
    IFEND;

{ Determine the new task status based on the length of time the task wants to wait.
    IF rb.requested_wait_time < UPPERVALUE (ost$free_running_clock) THEN
      IF (rb.expected_wait_time < tmv$long_wait_swap_time) OR (cst_p^.xcb_p^.system_table_lock_count > 0) THEN
        new_task_status := tmc$ts_timeout_reqexp_longlong;
      ELSEIF (rb.expected_wait_time < tmv$timed_wait_not_queued) THEN
        new_task_status := tmc$ts_timeout_reqexp_longvlong;
      ELSE
        new_task_status := tmc$ts_timed_wait_not_queued;
      IFEND;
    ELSE
      IF (rb.expected_wait_time < tmv$long_wait_swap_time) OR (cst_p^.xcb_p^.system_table_lock_count > 0) THEN
        new_task_status := tmc$ts_timeout_reqexp_inflong;
      ELSE
        new_task_status := tmc$ts_timeout_reqexp_infvlong;
      IFEND;
    IFEND;


{ If this WAIT request will cause the job to go into long wait then do the
{ cyclic aging that is done as part of swapout. Note: long wait aging may cause tasks of the job to go ready
{ to assign backing files to transient segments. In this case the NEXT long wait should NOT
{ do LONG WAIT aging.

    ptle_p := ^tmv$ptl_p^ [cst_p^.taskid.index];
    ptle_p^.new_task_status := new_task_status;

    IF ((new_task_status = tmc$ts_timeout_reqexp_infvlong)
{  } OR (new_task_status = tmc$ts_timeout_reqexp_longvlong)
{  } OR (new_task_status = tmc$ts_timed_wait_not_queued))
{ } AND (cst_p^.ijle_p^.statistics.tasks_not_in_long_wait = 1)
{ } AND NOT cst_p^.ijle_p^.long_wait_aging_complete
{ } AND (cst_p^.ajlo > 0)
{ } AND (ptle_p^.monitor_flags = $syt$monitor_flags [])
{ } AND NOT (cst_p^.xcb_p^.wait_inhibited OR (ptle_p^.ptl_flags.wait_inhibited = tmc$wi_wait_inhibited)) THEN

      jsp$long_wait_aging (cst_p^.ijle_p);
      cst_p^.ijle_p^.long_wait_aging_complete := TRUE;
    IFEND;


{ If the task has pending monitor flags or has wait inhibited, let it keep running.
{ If long wait aging has readied this task then PTL.NEW_TASK_STAUS will be null.

    new_task_status := ptle_p^.new_task_status;
    IF (ptle_p^.monitor_flags <> $syt$monitor_flags []) OR (new_task_status = tmc$ts_null) THEN
      cst_p^.xcb_p^.xp.user_condition_register := cst_p^.xcb_p^.xp.user_condition_register +
            $ost$user_conditions [osc$free_flag];
      cst_p^.xcb_p^.monitor_flags := cst_p^.xcb_p^.monitor_flags + ptle_p^.monitor_flags;
      cst_p^.xcb_p^.system_flags := cst_p^.xcb_p^.system_flags + ptle_p^.system_flags;
      ptle_p^.monitor_flags := $syt$monitor_flags [];
      ptle_p^.system_flags := $tmt$system_flags [];
      new_task_status := tmc$ts_null;
    ELSEIF cst_p^.xcb_p^.wait_inhibited OR (ptle_p^.ptl_flags.wait_inhibited = tmc$wi_wait_inhibited) THEN
      new_task_status := tmc$ts_null;
    IFEND;

    IF new_task_status <> tmc$ts_null THEN
      IF cst_p^.xcb_p^.xp.p_register.pva.ring <= osc$tsrv_ring THEN
        ptle_p^.ptl_flags.wait_inhibited := tmc$wi_wait_selected_r3;
      ELSE
        ptle_p^.ptl_flags.wait_inhibited := tmc$wi_wait_selected;
      IFEND;
      ptle_p^.end_of_wait_time := rb.requested_wait_time;
      cst_p^.dispatch_control.call_dispatcher := TRUE;
      IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
        cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
      IFEND;
    ELSE
      cst_p^.xcb_p^.wait_inhibited := FALSE;
      ptle_p^.ptl_flags.wait_inhibited := tmc$wi_null;
      ptle_p^.new_task_status := tmc$ts_null;
    IFEND;

{ If user request was PMP$READY_TASK_AND_WAIT, the rb.global_taskid is the taskid of the task to
{ be readied.

    IF rb.global_taskid <> tmv$null_global_task_id THEN
      IF cst_p^.xcb_p^.dispatching_priority >= tmv$ptl_p^ [cst_p^.xcb_p^.global_task_id.index].
            readying_task_priority THEN
        readying_task_priority := cst_p^.xcb_p^.dispatching_priority;
      ELSE
        readying_task_priority := tmv$ptl_p^ [cst_p^.xcb_p^.global_task_id.index].readying_task_priority;
      IFEND;
      tmp$set_task_ready (rb.global_taskid, readying_task_priority, tmc$rc_ready_conditional_wi);
      readied_ijle_p := jmf$ijle_p (tmv$ptl_p^ [rb.global_taskid.index].ijl_ordinal);
      IF readied_ijle_p^.entry_status = jmc$ies_job_swapped THEN
        service_class_p := ^jmv$service_classes [cst_p^.ijle_p^.job_scheduler_data.service_class]^.attributes;
        cst_p^.ijle_p^.job_scheduler_data.service_accumulator_since_swap :=
              service_class_p^.guaranteed_service_quantum;
        IF readied_ijle_p^.job_scheduler_data.priority > service_class_p^.scheduling_priority.minimum THEN
          IF cst_p^.ijle_p^.job_scheduler_data.priority >= readied_ijle_p^.job_scheduler_data.priority THEN
            cst_p^.ijle_p^.job_scheduler_data.priority := readied_ijle_p^.job_scheduler_data.priority - 1;
          IFEND;
        ELSEIF readied_ijle_p^.job_scheduler_data.priority = service_class_p^.scheduling_priority.minimum THEN
          cst_p^.ijle_p^.job_scheduler_data.priority := readied_ijle_p^.job_scheduler_data.priority;
        IFEND;
      IFEND;
    IFEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$mtr_wait;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] tmp$obtain_ijl_ordinal_for_ptl ', EJECT ??

  PROCEDURE [XDCL] tmp$obtain_ijl_ordinal_from_ptl
    (    global_task_id: ost$global_task_id;
     VAR ijl_ordinal: jmt$ijl_ordinal);

    ijl_ordinal := tmv$ptl_p^ [global_task_id.index].ijl_ordinal;

  PROCEND tmp$obtain_ijl_ordinal_from_ptl;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$QUEUE_TASK', EJECT ??

  PROCEDURE [XDCL] tmp$queue_task
    (    taskid: ost$global_task_id;
         task_status: tmt$task_status;
     VAR queue_link: tmt$task_queue_link);

*copyc tmh$queue_task

    VAR
      cst_p: ^ost$cpu_state_table,
      ptl_p: ^tmt$primary_task_list_entry;

    ptl_p := ^tmv$ptl_p^ [taskid.index];

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.taskid := taskid;
{   mtv$ptl_recovery_info.subcode := mtc$sc_queue_link_fixup;

    p$stop_if_bad_taskid (taskid);

    IF (ptl_p^.queue_link.head <> 0) OR (ptl_p^.queue_link.tail <> 0) OR (queue_link.tail = taskid.index) THEN
      mtp$error_stop ('TM02 - already queued');
    IFEND;
    IF (task_status < tmc$ts_first_external_queue) OR (ptl_p^.new_task_status > tmc$ts_null) THEN
      mtp$error_stop ('TM49 - bad call to queue_task');
    IFEND;

    IF queue_link.tail = 0 THEN
      queue_link.head := taskid.index;
      queue_link.tail := taskid.index;
    ELSE
      tmv$ptl_p^ [queue_link.tail].queue_link.head := taskid.index;
      ptl_p^.queue_link.tail := queue_link.tail;
      queue_link.tail := taskid.index;
    IFEND;

    cst_p := mtf$cst_p ();
    cst_p^.dispatch_control.call_dispatcher := TRUE;
    IF cst_p^.next_ptlo_to_dispatch = 0 THEN
      cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
    IFEND;
    IF taskid <> cst_p^.taskid THEN
      mtp$error_stop ('TM - attempt to queue task not xtask');
    IFEND;

    tmv$wait_queue_statistics [task_status] := tmv$wait_queue_statistics [task_status] + 1;

    ptl_p^.new_task_status := task_status;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$queue_task;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$REISSUE_MONITOR_REQUEST', EJECT ??

  PROCEDURE [XDCL] tmp$reissue_monitor_request;

*copyc tmh$reissue_monitor_request

    VAR
      cst_p: ^ost$cpu_state_table;

    cst_p := mtf$cst_p ();
    cst_p^.xcb_p^.xp.p_register.pva.offset := cst_p^.xcb_p^.xp.p_register.pva.offset - 2;

  PROCEND tmp$reissue_monitor_request;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$RESET_DISPATCHING_CONTROLS', EJECT ??

{ PURPOSE:
{   This procedure is called to reset the dispatching control set for a job.
{
{ DESIGN:
{   If expired_dispatching_control is TRUE, the procedure has been called because a
{   a task switch determined that the job has used all the service allowed for the
{   current dispatching control index.  The next index needs to be assigned.
{   Otherwise the procedure needs to determine the correct index based on
{   the total amount of service the job has used.
{   The procedure finds the correct dispatching control index, determines the
{   dispatching priority, and makes a call to update the dispatching priority
{   in the XCB.

  PROCEDURE [XDCL] tmp$reset_dispatching_control
    (    ijle_p: ^jmt$initiated_job_list_entry;
         ijl_ordinal: jmt$ijl_ordinal;
         excess_service_used: integer;
         expired_dispatching_control: boolean);

    VAR
      dispatching_control_p: ^jmt$dispatching_control,
      next_index: integer,
      service_used: integer;

    dispatching_control_p := ^jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
          dispatching_control;

    service_used := excess_service_used;

    IF expired_dispatching_control THEN
      next_index := ijle_p^.dispatching_control.dispatching_control_index + 1;
    ELSE
      next_index := jmc$min_dispatching_control;
    IFEND;

  /find_dispatching_control_set/
    WHILE service_used >= 0 DO
      IF (next_index <= jmc$max_dispatching_control) AND (dispatching_control_p^ [next_index].set_defined)
            THEN
        IF dispatching_control_p^ [next_index].service_limit > service_used THEN
          ijle_p^.dispatching_control.service_remaining := dispatching_control_p^ [next_index].service_limit -
                service_used;
          ijle_p^.dispatching_control.dispatching_control_index := next_index;
          p$determine_dispatch_priority (ijle_p);
          tmp$update_job_task_environment (ijle_p, ijl_ordinal, tmc$fnx_job);
          EXIT /find_dispatching_control_set/; {----->
        ELSE
          service_used := service_used - dispatching_control_p^ [next_index].service_limit;
          next_index := next_index + 1;
        IFEND;
      ELSE
        next_index := jmc$min_dispatching_control;
      IFEND;
    WHILEND /find_dispatching_control_set/;

  PROCEND tmp$reset_dispatching_control;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$RESTART_IDLED_TASKS', EJECT ??

  PROCEDURE [XDCL] tmp$restart_idled_tasks
    (    ajl_ordinal: jmt$ajl_ordinal);

    VAR
      attempt_preselection: boolean,
      cst_p: ^ost$cpu_state_table,
      ijle_p: ^jmt$initiated_job_list_entry,
      ready_task_count: integer,
      xcb_p: ^ost$execution_control_block,
      ptlo: ost$task_index;

    ijle_p := jmf$ijle_p (jmv$ajl_p^ [ajl_ordinal].ijl_ordinal);

    IF jmc$dsw_update_keypoint_masks IN ijle_p^.delayed_swapin_work THEN
      osp$update_job_keypoint_mask (ijle_p, jmv$ajl_p^ [ajl_ordinal].ijl_ordinal);
    IFEND;

    ptlo := ijle_p^.job_monitor_taskid.index;

{ Scan the IJL thread and mark the entries swapped in.
    ready_task_count := 0;
    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
    WHILE ptlo <> 0 DO
      xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ajl_ordinal, tmv$ptl_p^ [ptlo].xcb_offset);
      IF (tmv$ptl_p^ [ptlo].idle_status >= tmc$is_idled) THEN
        IF tmv$ptl_p^ [ptlo].status = tmc$ts_ready_but_swapped THEN
          tmv$ptl_p^ [ptlo].status := tmc$ts_ready;
          ready_task_count := ready_task_count + 1;
        IFEND;
        IF tmv$ptl_p^ [ptlo].status <= tmc$ts_last_status_in_dct THEN
          attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
          p$dct_ready_task (xcb_p, ijle_p, ptlo, attempt_preselection);
        IFEND;
      IFEND;
      tmv$ptl_p^ [ptlo].idle_status := tmc$is_not_idled;
      ptlo := tmv$ptl_p^ [ptlo].ijl_thread;
    WHILEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$restart_idled_tasks;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SET_NAMVE_TASK_READY', EJECT ??

  PROCEDURE [XDCL] tmp$set_namve_task_ready
    (    taskid: ost$global_task_id;
     VAR task_id_valid: boolean);

    VAR
      attempt_preselection: boolean,
      ijle_p: ^jmt$initiated_job_list_entry,
      null_dispatching_info: jmt$dispatching_control_info,
      old_dispatching_priority: jmt$dispatching_priority,
      ptl_p: ^tmt$primary_task_list_entry,
      task_priority_changed: boolean,
      xcb_p: ^ost$execution_control_block;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.taskid := taskid;
    IF (taskid = tmv$null_global_task_id) OR (taskid.index > UPPERBOUND (tmv$ptl_p^)) OR
          (tmv$ptl_p^ [taskid.index].sequence_number <> taskid.seqno) OR
          (tmv$ptl_p^ [taskid.index].status = tmc$ts_null) THEN
      task_id_valid := FALSE;
      tmp$clear_lock (tmv$ptl_lock);
      RETURN; {----->
    IFEND;

    task_id_valid := TRUE;
    ptl_p := ^tmv$ptl_p^ [taskid.index];
    ijle_p := jmf$ijle_p (ptl_p^.ijl_ordinal);
    xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);

    IF ijle_p^.interactive_task_gtid = taskid THEN
      old_dispatching_priority := ijle_p^.dispatching_control.dispatching_priority;
      p$reset_dispatching_priority (ijle_p, ptl_p^.ijl_ordinal);
      IF (ijle_p^.dispatching_control.dispatching_priority <> old_dispatching_priority) AND
            (ijle_p^.entry_status = jmc$ies_swapin_candidate) THEN
        jmv$subsystem_priority_changes [ijle_p^.job_scheduler_data.service_class] := TRUE;
        jmp$set_scheduler_event (jmc$subsystem_priority_change);
      IFEND;
      ijle_p^.interactive_task_gtid := tmv$null_global_task_id;
    IFEND;

    IF (ptl_p^.status = tmc$ts_executing) OR (ptl_p^.status = tmc$ts_ready_and_selected) THEN
      IF ptl_p^.new_task_status < tmc$ts_first_ready_uncond THEN
        ptl_p^.new_task_status := tmc$ts_null;
      IFEND;

    ELSEIF ptl_p^.status = tmc$ts_ready THEN
      ;

    ELSEIF ptl_p^.status < tmc$ts_ready_but_swapped THEN

{ If the task is in the timed wait queue, take it out.  Adjust the tasks_not_in_long_wait count based upon
{ the task status.  If the job the task belongs to is swapped, call scheduler to swap the job in.  If the
{ job is in memory, insert the task into the DCT.

      IF ptl_p^.status <= tmc$ts_last_status_in_wait_q THEN
        p$remove_task_from_q (ptl_p, tmv$timed_wait_queue);
        IF (ptl_p^.status = tmc$ts_timeout_reqexp_longvlong) THEN
          ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
        IFEND;
      ELSE
        IF (ptl_p^.status = tmc$ts_timeout_reqexp_infvlong) OR
              (ptl_p^.status = tmc$ts_timed_wait_not_queued) THEN
          ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
        IFEND;
      IFEND;

      IF ptl_p^.idle_status = tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready_but_swapped;
        ptl_p^.idle_status := tmc$is_idled_sched_notified;
        jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
      ELSEIF ptl_p^.idle_status < tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready;
        jmv$ajl_p^ [ijle_p^.ajl_ordinal].job_is_good_swap_candidate := FALSE;
        attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
        p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);
      IFEND;

    ELSEIF ptl_p^.status = tmc$ts_ready_but_swapped THEN
      jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
    IFEND;

{Does this have to be another IF block? Can it really happen, that we end here and also
{took another action above that brought us here? I can't see how. But why do we crash then all the time?
    IF ptl_p^.status = tmc$ts_segment_lock_wait THEN
      p$remove_task_from_seg_lock_q (taskid, ijle_p, ptl_p);
{I'll take the following lines out again to see, if we fix that shitty problem again
{   ELSEIF ptl_p^.status = tmc$ts_avail_mod_q_full_wait THEN
{     p$remove_task_from_external_q (taskid, ijle_p, ptl_p);
    IFEND;

{ The 'wait_inhibited' flag in the PTL is set to tmc$wi_wait_selected only after the successful completion
{ of a wait request. This prevents potential timing conflicts between ready_task and wait requests.

    IF (NOT (ptl_p^.ptl_flags.wait_inhibited = tmc$wi_wait_selected) AND
          NOT (ptl_p^.ptl_flags.wait_inhibited = tmc$wi_wait_selected_r3)) THEN
      ptl_p^.ptl_flags.wait_inhibited := tmc$wi_wait_inhibited;
    IFEND;
    ijle_p^.long_wait_aging_complete := FALSE;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$set_namve_task_ready;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SET_TASK_LIST_READY', EJECT ??

  PROCEDURE [XDCL] tmp$set_task_list_ready
    (    highest_index: integer;
         taskid_list: pmt$ready_task_list;
         task_response_list: pmt$ready_task_response_list;
         readying_task_priority: jmt$dispatching_priority);

    VAR
      attempt_preselection: boolean,
      i: integer,
      ijle_p: ^jmt$initiated_job_list_entry,
      preselect_count_per_call: integer,
      ptl_p: ^tmt$primary_task_list_entry,
      task_priority_changed: boolean,
      taskid: ost$global_task_id,
      xcb_p: ^ost$execution_control_block;

    preselect_count_per_call := 0;
    tmv$ready_task_list_statistics.calls := tmv$ready_task_list_statistics.calls + 1;
    tmv$ready_task_list_statistics.task_list_size := tmv$ready_task_list_statistics.task_list_size +
          highest_index + 1;

    FOR i := 0 TO highest_index DO
      IF task_response_list [i] = pmc$rtr_ready_task_successful THEN
        taskid := taskid_list [i];

        ptl_p := ^tmv$ptl_p^ [taskid.index];
        ijle_p := jmf$ijle_p (ptl_p^.ijl_ordinal);
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);


{ Tasks with subsystem locks set will execute with the higher of the task's or the "readying" task's
{ priority, after it has run for the subsystem lock threshold with a priority of P9.

        task_priority_changed := FALSE;

        IF (readying_task_priority <> 0)
{        } AND ((ptl_p^.ptl_flags.subsystem_locks_set)
{            } OR ((ptl_p^.idle_status < tmc$is_idled) AND (xcb_p^.system_table_lock_count > 0))) THEN

          IF readying_task_priority > ptl_p^.readying_task_priority THEN
            ptl_p^.readying_task_priority := readying_task_priority;
            task_priority_changed := TRUE;
          IFEND;
          IF ijle_p^.scheduling_dispatching_priority < readying_task_priority THEN
            tmv$ready_task_list_statistics.subsystem_priotity_change_count :=
                  tmv$ready_task_list_statistics.subsystem_priotity_change_count + 1;
            ijle_p^.scheduling_dispatching_priority := readying_task_priority;
            jmp$subsystem_priority_change (ijle_p);
          IFEND;
        IFEND;

        IF (ptl_p^.status = tmc$ts_executing) OR (ptl_p^.status = tmc$ts_ready_and_selected) THEN
          tmv$ready_task_list_statistics.executing_count := tmv$ready_task_list_statistics.executing_count +
                1;
          IF ptl_p^.new_task_status < tmc$ts_first_ready_uncond THEN
            ptl_p^.new_task_status := tmc$ts_null;
          IFEND;

        ELSEIF ptl_p^.status = tmc$ts_ready THEN

{ If the task being readied has subsystem locks set, it must be removed from the ready string and
{ reinserted. It is possible that the task will execute at a different priority depending on how long
{ the task has had subsystem locks set, and the priority of the readying task.

          IF task_priority_changed AND (xcb_p^.system_table_lock_count > 0) AND
                (xcb_p^.system_table_lock_count < osc$system_table_lock_set) AND
                (xcb_p^.subsystem_lock_priority_count >= tmv$subsystem_prior_threshold) THEN
            p$remove_task_from_dct (taskid.index);
            attempt_preselection := tmv$rtl_attempt_preselection AND
{               } ((ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0));
            preselect_count_per_call := preselect_count_per_call + $INTEGER (attempt_preselection);
            tmv$ready_task_list_statistics.ready_task_priority_changed [attempt_preselection] :=
                  tmv$ready_task_list_statistics.ready_task_priority_changed [attempt_preselection] + 1;
            p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);
          ELSE
            tmv$ready_task_list_statistics.ready_count := tmv$ready_task_list_statistics.ready_count + 1;
          IFEND;

        ELSEIF ptl_p^.status < tmc$ts_ready_but_swapped THEN

{ If the task is in the timed wait queue, take it out.  Adjust the tasks_not_in_long_wait count based upon
{ the task status.  If the job the task belongs to is swapped, call scheduler to swap the job in.  If the
{ job is in memory, insert the task into the DCT.


          IF ptl_p^.status <= tmc$ts_last_status_in_wait_q THEN
            p$remove_task_from_q (ptl_p, tmv$timed_wait_queue);
            IF (ptl_p^.status = tmc$ts_timeout_reqexp_longvlong) THEN
              ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
            IFEND;
          ELSE
            IF (ptl_p^.status = tmc$ts_timeout_reqexp_infvlong) OR
                  (ptl_p^.status = tmc$ts_timed_wait_not_queued) THEN
              ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
            IFEND;
          IFEND;

          IF ptl_p^.idle_status = tmc$is_idled THEN
            ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
            ptl_p^.status := tmc$ts_ready_but_swapped;
            ptl_p^.idle_status := tmc$is_idled_sched_notified;
            tmv$ready_task_list_statistics.task_in_wait_idled :=
                  tmv$ready_task_list_statistics.task_in_wait_idled + 1;
            jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
          ELSEIF ptl_p^.idle_status < tmc$is_idled THEN
            ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
            ptl_p^.status := tmc$ts_ready;
            jmv$ajl_p^ [ijle_p^.ajl_ordinal].job_is_good_swap_candidate := FALSE;
            attempt_preselection := tmv$rtl_attempt_preselection AND
{               } ((ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0));
            preselect_count_per_call := preselect_count_per_call + $INTEGER (attempt_preselection);
            tmv$ready_task_list_statistics.task_in_wait_not_idled [attempt_preselection] :=
                  tmv$ready_task_list_statistics.task_in_wait_not_idled [attempt_preselection] + 1;
            p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);

          ELSE {ptl_p^.idle_status = tmc$is_idled_sched_notified
{ Does this state exist - we are not swapped but idled and the scheduler is notified? If this happens,
{ then we would lose the ready.

            tmv$ready_task_list_statistics.task_in_wait_swapping :=
                  tmv$ready_task_list_statistics.task_in_wait_swapping + 1;
          IFEND;

        ELSEIF ptl_p^.status = tmc$ts_ready_but_swapped THEN
          tmv$ready_task_list_statistics.ready_swapped_count :=
                tmv$ready_task_list_statistics.ready_swapped_count + 1;
          jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);

        ELSE { ptl_p^.status > tmc$ts_ready_but_swapped
{ We are queued for some external event and therefore not process the ready.
          tmv$ready_task_list_statistics.external_event_wait [ptl_p^.status] :=
                tmv$ready_task_list_statistics.external_event_wait [ptl_p^.status] + 1;
        IFEND;

{The 'wait_inhibited' flag in the PTL is set to tmc$wi_wait_selected only after the successful completion
{of a wait request.  This prevents potential timing conflicts between ready_task and wait requests.

        IF (NOT (ptl_p^.ptl_flags.wait_inhibited = tmc$wi_wait_selected) AND
              NOT (ptl_p^.ptl_flags.wait_inhibited = tmc$wi_wait_selected_r3)) THEN
          ptl_p^.ptl_flags.wait_inhibited := tmc$wi_wait_inhibited;
        IFEND;
        ijle_p^.long_wait_aging_complete := FALSE;
      ELSE
        tmv$ready_task_list_statistics.unsuccessful_ready_count :=
              tmv$ready_task_list_statistics.unsuccessful_ready_count + 1;
      IFEND;
    FOREND;

    IF preselect_count_per_call > 1 THEN
      tmv$ready_task_list_statistics.calls_with_multiple_preselects :=
            tmv$ready_task_list_statistics.calls_with_multiple_preselects + 1;
    IFEND;

  PROCEND tmp$set_task_list_ready;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SET_TASK_READY', EJECT ??

  PROCEDURE [XDCL] tmp$set_task_ready
    (    taskid: ost$global_task_id;
         readying_task_priority: jmt$dispatching_priority;
         ready_condition: tmt$ready_condition);

*copyc tmh$set_task_ready

    VAR
      attempt_preselection: boolean,
      ijle_p: ^jmt$initiated_job_list_entry,
      null_dispatching_info: jmt$dispatching_control_info,
      old_dispatching_priority: jmt$dispatching_priority,
      ptl_p: ^tmt$primary_task_list_entry,
      task_priority_changed: boolean,
      xcb_p: ^ost$execution_control_block;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.taskid := taskid;
    p$stop_if_bad_taskid (taskid);
    ptl_p := ^tmv$ptl_p^ [taskid.index];
    ijle_p := jmf$ijle_p (ptl_p^.ijl_ordinal);
    xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);

    IF ijle_p^.interactive_task_gtid = taskid THEN
      old_dispatching_priority := ijle_p^.dispatching_control.dispatching_priority;
      p$reset_dispatching_priority (ijle_p, ptl_p^.ijl_ordinal);
      IF (ijle_p^.dispatching_control.dispatching_priority <> old_dispatching_priority) AND
            (ijle_p^.entry_status = jmc$ies_swapin_candidate) THEN
        jmv$subsystem_priority_changes [ijle_p^.job_scheduler_data.service_class] := TRUE;
        jmp$set_scheduler_event (jmc$subsystem_priority_change);
      IFEND;
      ijle_p^.interactive_task_gtid := tmv$null_global_task_id;
    IFEND;

{ Tasks with subsystem locks set will execute with the higher of the task's or the "readying" task's
{ priority, after it has run for the subsystem lock threshold with a priority of P9.

    task_priority_changed := FALSE;

    IF (readying_task_priority <> 0) AND ((ptl_p^.ptl_flags.subsystem_locks_set) OR
          ((ptl_p^.idle_status < tmc$is_idled) AND (xcb_p^.system_table_lock_count > 0))) THEN
      IF readying_task_priority > ptl_p^.readying_task_priority THEN
        ptl_p^.readying_task_priority := readying_task_priority;
        task_priority_changed := TRUE;
      IFEND;
      IF ijle_p^.scheduling_dispatching_priority < readying_task_priority THEN
        ijle_p^.scheduling_dispatching_priority := readying_task_priority;
        jmp$subsystem_priority_change (ijle_p);
      IFEND;
    IFEND;

    IF (ptl_p^.status = tmc$ts_executing) OR (ptl_p^.status = tmc$ts_ready_and_selected) THEN
      IF ptl_p^.new_task_status < tmc$ts_first_ready_uncond THEN
        ptl_p^.new_task_status := tmc$ts_null;
      IFEND;

    ELSEIF ptl_p^.status = tmc$ts_ready THEN

{ If the task being readied has subsystem locks set, it must be removed from the ready string and
{ reinserted. It is possible that the task will execute at a different priority depending on how long
{ the task has had subsystem locks set, and the priority of the readying task.

      IF task_priority_changed AND (xcb_p^.system_table_lock_count > 0) AND
            (xcb_p^.system_table_lock_count < osc$system_table_lock_set) AND
            (xcb_p^.subsystem_lock_priority_count >= tmv$subsystem_prior_threshold) THEN
        p$remove_task_from_dct (taskid.index);
        attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
        p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);
      IFEND;

    ELSEIF ptl_p^.status < tmc$ts_ready_but_swapped THEN

{ If the task is in the timed wait queue, take it out.  Adjust the tasks_not_in_long_wait count based upon
{ the task status.  If the job the task belongs to is swapped, call scheduler to swap the job in.  If the
{ job is in memory, insert the task into the DCT.

      IF ptl_p^.status <= tmc$ts_last_status_in_wait_q THEN
        p$remove_task_from_q (ptl_p, tmv$timed_wait_queue);
        IF (ptl_p^.status = tmc$ts_timeout_reqexp_longvlong) THEN
          ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
        IFEND;
      ELSE
        IF (ptl_p^.status = tmc$ts_timeout_reqexp_infvlong) OR
              (ptl_p^.status = tmc$ts_timed_wait_not_queued) THEN
          ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
        IFEND;
      IFEND;

      IF ptl_p^.idle_status = tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready_but_swapped;
        ptl_p^.idle_status := tmc$is_idled_sched_notified;
        jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
      ELSEIF ptl_p^.idle_status < tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready;
        jmv$ajl_p^ [ijle_p^.ajl_ordinal].job_is_good_swap_candidate := FALSE;
        attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
        p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);
      IFEND;

    ELSEIF ptl_p^.status = tmc$ts_ready_but_swapped THEN
      jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
    IFEND;

{Does this have to be another IF block? Can it really happen, that we end here and also
{took another action above that brought us here? I can't see how. But why do we crash then all the time?
    IF ptl_p^.status = tmc$ts_segment_lock_wait THEN
      p$remove_task_from_seg_lock_q (taskid, ijle_p, ptl_p);
{I'll take the following lines out again to see, if we fix that shitty problem again
{   ELSEIF ptl_p^.status = tmc$ts_avail_mod_q_full_wait THEN
{     p$remove_task_from_external_q (taskid, ijle_p, ptl_p);
    IFEND;

{ The 'wait_inhibited' flag in the PTL is set to tmc$wi_wait_selected only after the successful completion
{ of a wait request. This prevents potential timing conflicts between ready_task and wait requests.

    IF (ready_condition = tmc$rc_ready_conditional_wi) AND
          (NOT (ptl_p^.ptl_flags.wait_inhibited = tmc$wi_wait_selected) AND
          NOT (ptl_p^.ptl_flags.wait_inhibited = tmc$wi_wait_selected_r3)) THEN
      ptl_p^.ptl_flags.wait_inhibited := tmc$wi_wait_inhibited;
    IFEND;
    ijle_p^.long_wait_aging_complete := FALSE;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$set_task_ready;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SET_TASK_READY_UNCOND', EJECT ??

  PROCEDURE [XDCL] tmp$set_task_ready_uncond
    (    taskid: ost$global_task_id;
         task_status: tmt$task_status);

*copyc tmh$set_task_ready_uncond

    VAR
      attempt_preselection: boolean,
      ijle_p: ^jmt$initiated_job_list_entry,
      xcb_p: ^ost$execution_control_block,
      ptl_p: ^tmt$primary_task_list_entry;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.subcode := mtc$null;
{   mtv$ptl_recovery_info.taskid := taskid;
    p$stop_if_bad_taskid (taskid);
    ptl_p := ^tmv$ptl_p^ [taskid.index];
    ijle_p := jmf$ijle_p (ptl_p^.ijl_ordinal);
    IF (task_status = tmc$ts_io_wait_not_queued) THEN
      tmv$wait_queue_statistics [tmc$ts_io_wait_queued] :=
            tmv$wait_queue_statistics [tmc$ts_io_wait_queued] - 1;
    IFEND;
    IF ptl_p^.status <> task_status THEN
      IF (ptl_p^.status <> tmc$ts_executing) OR (ptl_p^.new_task_status <> task_status) THEN
        mtp$error_stop ('TM96 - task not queued');
      IFEND;
      ptl_p^.new_task_status := tmc$ts_null;
    ELSE
      IF ptl_p^.idle_status = tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready_but_swapped;
        ptl_p^.idle_status := tmc$is_idled_sched_notified;
        jmp$ready_task_in_swapped_job (ptl_p^.ijl_ordinal, ijle_p);
      ELSEIF ptl_p^.idle_status < tmc$is_idled THEN
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
        ptl_p^.status := tmc$ts_ready;
        attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptl_p^.xcb_offset);
        p$dct_ready_task (xcb_p, ijle_p, taskid.index, attempt_preselection);
      IFEND;
    IFEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$set_task_ready_uncond;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SET_TASK_WAIT', EJECT ??

  PROCEDURE [XDCL] tmp$set_task_wait
    (    task_status: tmt$task_status);

*copyc tmh$set_task_wait

    VAR
      cst_p: ^ost$cpu_state_table,
      taskid: ost$global_task_id;

    cst_p := mtf$cst_p ();
    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    IF (task_status >= tmc$ts_first_external_queue) OR (tmv$ptl_p^ [cst_p^.taskid.index].new_task_status >
          tmc$ts_null) THEN
      mtp$error_stop ('TM37 - bad call to set_task_wait');
    IFEND;
    IF (task_status = tmc$ts_io_wait_not_queued) THEN
      tmv$wait_queue_statistics [tmc$ts_io_wait_queued] :=
            tmv$wait_queue_statistics [tmc$ts_io_wait_queued] + 1;
    IFEND;
    tmv$ptl_p^ [cst_p^.taskid.index].new_task_status := task_status;
    tmp$clear_lock (tmv$ptl_lock);
    cst_p^.dispatch_control.call_dispatcher := TRUE;
    IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
      cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
    IFEND;

  PROCEND tmp$set_task_wait;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SET_UP_DEBUG_REGISTERS', EJECT ??

{ PURPOSE:
{   This procedure is called during the first swapin for job recovery to straighten out the
{   debug list and mask in the exchange package of recovering jobs.

  PROCEDURE [XDCL] tmp$set_up_debug_registers
    (    ptlo: ost$task_index;
         ijle_p: ^jmt$initiated_job_list_entry;
         xcb_p: ^ost$execution_control_block);

    VAR
      null_debug_mask: [STATIC, READ] ost$debug_mask := [FALSE, FALSE, [REP 5 of FALSE]];

    IF (xcb_p^.xp.debug_list_pointer <> NIL) AND (#RING (xcb_p^.xp.debug_list_pointer) = 1) THEN
      xcb_p^.xp.debug_list_pointer := NIL;
      xcb_p^.xp.debug_mask_register := null_debug_mask;

      xcb_p^.xp.debug_index := 0;
      IF osc$debug IN xcb_p^.xp.user_mask THEN
        xcb_p^.xp.user_mask := xcb_p^.xp.user_mask - $ost$user_conditions [osc$debug];
        xcb_p^.monitor_flags := xcb_p^.monitor_flags + $syt$monitor_flags [syc$mf_system_debugger];
        IF tmv$ptl_p^ [ptlo].ptl_flags.wait_inhibited <> tmc$wi_wait_selected_r3 THEN
          xcb_p^.xp.user_condition_register := xcb_p^.xp.user_condition_register +
                $ost$user_conditions [osc$free_flag];
        IFEND;
      IFEND;
    IFEND;

  PROCEND tmp$set_up_debug_registers;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SWITCH_TASK', EJECT ??

  PROCEDURE [XDCL] tmp$switch_task
    (    dummy: ^cell;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$switch_task

    VAR
      attempt_preselection: boolean,
      clock: integer,
      dispatching_priority: jmt$dispatching_priority_set,
      idle_time: integer,
      integer_dp_sets: integer,
      local_set: tmt$dispatching_control_sets,
      priority: t$dp_trick_conversion,
      ptle_p: ^tmt$primary_task_list_entry,
      ptlo: ost$task_index,
      time: integer,
      xcb_p: ^ost$execution_control_block;

?? NEWTITLE := 'P$PROCESS_SYSTEM_LOCKS_SET', EJECT ??

{Note:
{  This request was inline, but it kills optimization and is probably less often called than tmp$switch_task

    PROCEDURE p$process_system_locks_set
      (    ptle_p: ^tmt$primary_task_list_entry;
           xcb_p: ^ost$execution_control_block;
           cst_p: ^ost$cpu_state_table);

      VAR
        ijle_p: ^jmt$initiated_job_list_entry,
        next_ptlo_to_dispatch: ost$task_index,
        next_task_ijle_p: ^jmt$initiated_job_list_entry,
        next_task_xcb_p: ^ost$execution_control_block,
        locked_dp_integer: integer;

      IF (ptle_p^.new_task_status = tmc$ts_null) AND (cst_p^.cpu_state.next_state <> osc$cpu_stepped) AND
            (cst_p^.next_processor_state = cmc$on) THEN
        IF (xcb_p^.system_table_lock_count >= osc$system_table_lock_set) THEN
          IF cst_p^.dispatching_priority < jmc$prior_system_tbls_locked THEN
            cst_p^.dispatching_priority := jmc$prior_system_tbls_locked;
            locked_dp_integer := tmv$dispatch_priority_integer [jmc$prior_system_tbls_locked];
          IFEND;
          xcb_p^.system_give_up_cpu := TRUE;
        ELSEIF (xcb_p^.subsystem_lock_priority_count <= tmv$subsystem_prior_threshold) THEN
          xcb_p^.subsystem_lock_priority_count := xcb_p^.subsystem_lock_priority_count + 1;
          IF cst_p^.dispatching_priority < jmc$prior_subsystem_tbls_locked THEN
            cst_p^.dispatching_priority := jmc$prior_subsystem_tbls_locked;
            locked_dp_integer := tmv$dispatch_priority_integer [jmc$prior_subsystem_tbls_locked];
          IFEND;
          xcb_p^.subsystem_give_up_cpu := TRUE;
        ELSE
          RETURN; {----->
        IFEND;

        ijle_p := cst_p^.ijle_p;
        cst_p^.max_cptime := jmv$service_classes [ijle_p^.job_scheduler_data.service_class]^.attributes.
              dispatching_control [ijle_p^.dispatching_control.dispatching_control_index].
              dispatching_timeslice.minor;

{ If this processor was being interrupted to switch to a higher priority task, the task must be inserted
{ in the DCT because this processor cannot be interrupted now.  Do not change the dispatching priority
{ integer to the locks-set value until after checking/removing a pre-selected task.  When the task was
{ pre-selcted the dispatching priority integer for the CPU was changed to the pre-selected task's priority.
{ If it is changed, the task may be pre_selected for this processor again.
{ Example:  A P6 task is executing; a P10 task has been pre_selected (so dispatching priority integer
{ is P10).  The P6 task has sub-system locks set, so its priority is raised to P9.  Changing the dispatching
{ priority integer to P9 before calling dct_ready_task again for the pre-selected P10 task could cause
{ this CPU to be pre-selected again.

        IF cst_p^.next_ptlo_to_dispatch <> 0 THEN
          next_ptlo_to_dispatch := cst_p^.next_ptlo_to_dispatch;
          next_task_ijle_p := jmf$ijle_p (tmv$ptl_p^ [next_ptlo_to_dispatch].ijl_ordinal);
          next_task_ijle_p^.executing_task_count := next_task_ijle_p^.executing_task_count - 1;
          tmv$ptl_p^ [next_ptlo_to_dispatch].status := tmc$ts_ready;
          next_task_xcb_p := #ADDRESS (1, next_task_ijle_p^.ajl_ordinal + mtc$job_fixed_segment,
                tmv$ptl_p^ [next_ptlo_to_dispatch].xcb_offset);
          cst_p^.next_ptlo_to_dispatch := 0;
          p$dct_ready_task (next_task_xcb_p, next_task_ijle_p, next_ptlo_to_dispatch,
                {attempt_preselection =} TRUE);
        IFEND;

        cst_p^.dispatching_priority_integer := locked_dp_integer;

        tmp$clear_lock (tmv$ptl_lock);
        EXIT tmp$switch_task; {----->

      IFEND;

    PROCEND p$process_system_locks_set;
?? OLDTITLE ??
?? NEWTITLE := 'P$UPDATE_TIMED_WAIT_QUEUE', EJECT ??

{Note:
{  This request was inline, but it kills optimization and is probably less often called than tmp$switch_task

    PROCEDURE p$update_timed_wait_queue
      (    free_running_clock: integer;
       VAR timed_wait_queue: tmt$task_queue_link);

{ Called during task switch to remove tasks from the timed wait queue if the wait time has expired.
{ NOTE: this routine is called with the PTL lock set.

      VAR
        attempt_preselection: boolean,
        ijle_p: ^jmt$initiated_job_list_entry,
        xcb_p: ^ost$execution_control_block,
        ptlo: ost$task_index,
        ptle_p: ^tmt$primary_task_list_entry;

      WHILE (tmv$ptl_p^ [timed_wait_queue.head].end_of_wait_time <= free_running_clock) AND
            (timed_wait_queue.head <> 0) DO
        ptlo := timed_wait_queue.head;
        ptle_p := ^tmv$ptl_p^ [ptlo];
        timed_wait_queue.head := ptle_p^.queue_link.head;
        tmv$ptl_p^ [ptle_p^.queue_link.head].queue_link.tail := 0;
        ptle_p^.queue_link.head := 0;
        IF (ptle_p^.status <= tmc$ts_last_status_in_dct) OR
              (ptle_p^.status > tmc$ts_last_status_in_wait_q) THEN
          mtp$error_stop ('TM36 - task not in wait queue');
        IFEND;
        ijle_p := jmf$ijle_p (ptle_p^.ijl_ordinal);
        IF ptle_p^.idle_status = tmc$is_idled THEN
          ptle_p^.idle_status := tmc$is_idled_sched_notified;
          IF ptle_p^.status = tmc$ts_timeout_reqexp_longvlong THEN
            ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
          IFEND;
          ptle_p^.status := tmc$ts_ready_but_swapped;
          jmp$ready_task_in_swapped_job (ptle_p^.ijl_ordinal, ijle_p);
          ijle_p^.long_wait_aging_complete := FALSE;
        ELSE
          IF ptle_p^.status = tmc$ts_timeout_reqexp_longvlong THEN
            ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait + 1;
            jmv$ajl_p^ [ijle_p^.ajl_ordinal].job_is_good_swap_candidate := FALSE;
          IFEND;
          ptle_p^.status := tmc$ts_ready;
          xcb_p := #ADDRESS (1, mtc$job_fixed_segment + ijle_p^.ajl_ordinal, ptle_p^.xcb_offset);
          xcb_p^.timeslice.minor := 0;
          xcb_p^.timeslice.major := 0;
          attempt_preselection := (ijle_p^.multiprocessing_allowed) OR (ijle_p^.executing_task_count = 0);
          p$dct_ready_task (xcb_p, ijle_p, ptlo, attempt_preselection);
        IFEND;
        ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count + 1;
      WHILEND;

{ Update the queue's tail.

      IF timed_wait_queue.head = 0 THEN
        timed_wait_queue.tail := 0;
      IFEND;

    PROCEND p$update_timed_wait_queue;
?? OLDTITLE ??
?? EJECT ??
{ Update task accounting info.
    IF NOT tmv$tables_initialized THEN
      cst_p^.max_cptime := 20000;
      RETURN; {----->
    IFEND;

{ If the CPU is not idle (cst_p^.xcb_p is not NIL), update the executing tasks's status.
    xcb_p := cst_p^.xcb_p;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
    clock := #FREE_RUNNING_CLOCK (0);

    IF xcb_p <> NIL THEN
      IF cst_p^.accumulated_job_cptime <> 0 THEN
        p$update_cp_statistics (cst_p);
      IFEND;

      xcb_p^.last_lpid_for_task := cst_p^.cst_index;
      cst_p^.jcb_p^.last_lpid_for_job := cst_p^.cst_index;
      cst_p^.jcb_p^.last_execution_time := clock;
      ptlo := cst_p^.taskid.index;
      ptle_p := ^tmv$ptl_p^ [ptlo];

      IF xcb_p^.system_table_lock_count > 0 THEN
        p$process_system_locks_set (ptle_p, xcb_p, cst_p);
      ELSEIF (ptle_p^.idle_status = tmc$is_idle_initiated) THEN
        ptle_p^.idle_status := tmc$is_idled;
        cst_p^.xcb_p := NIL;
        p$initiate_swap_if_possible (cst_p);
      IFEND;

{ The current task will be removed from the CPU. Decrement this task's executing_task_
{ count.  If a task has not been pre_selected for this CPU, set dispatching_priority_integer
{ equal to the highest priority task in the DCT for the pre-select code in
{ dct_ready_task (which will be called if tasks are readied from the timed wait queue).

      cst_p^.ijle_p^.executing_task_count := cst_p^.ijle_p^.executing_task_count - 1;
      IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
        cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
      IFEND;

{ Update the timed wait queue.  This must be done before considering the status of the task
{ that is currently executing (if there is one); tasks being readied from the timed wait queue
{ should be considered for pre-selection (in p$dct_ready_task) before the task that is
{ currently executing.

      IF (tmv$timed_wait_queue.head <> 0)
{   } AND (tmv$ptl_p^ [tmv$timed_wait_queue.head].end_of_wait_time <= clock) THEN
        p$update_timed_wait_queue (clock, tmv$timed_wait_queue);
      IFEND;

{ Check new status of executing job.
      IF ptle_p^.new_task_status > tmc$ts_last_status_in_dct THEN
        ptle_p^.status := ptle_p^.new_task_status;
        ptle_p^.new_task_status := tmc$ts_null;
        cst_p^.ijle_p^.statistics.ready_task_count := cst_p^.ijle_p^.statistics.ready_task_count - 1;
        IF ptle_p^.status <= tmc$ts_last_status_in_wait_q THEN
          p$insert_timed_wait_queue (ptlo);
        IFEND;
        IF (ptle_p^.status = tmc$ts_timeout_reqexp_longvlong) OR
              (ptle_p^.status = tmc$ts_timed_wait_not_queued) OR
              (ptle_p^.status = tmc$ts_timeout_reqexp_infvlong) THEN
          cst_p^.ijle_p^.statistics.tasks_not_in_long_wait :=
                cst_p^.ijle_p^.statistics.tasks_not_in_long_wait - 1;
          IF (cst_p^.ijle_p^.statistics.tasks_not_in_long_wait = 0) AND
                (cst_p^.ijle_p^.entry_status = jmc$ies_job_in_memory) AND
                (ptle_p^.idle_status = tmc$is_not_idled) THEN
            cst_p^.xcb_p := NIL;
            p$set_swapout_candidate (cst_p^.ajlo);
          IFEND;
        IFEND;

      ELSEIF ptle_p^.idle_status <> tmc$is_idled THEN
        ptle_p^.status := tmc$ts_ready;
        attempt_preselection := (cst_p^.next_ptlo_to_dispatch = 0) AND
              ((cst_p^.ijle_p^.multiprocessing_allowed) OR (cst_p^.ijle_p^.statistics.ready_task_count = 1));
        p$dct_ready_task (xcb_p, cst_p^.ijle_p, ptlo, attempt_preselection);
      ELSE
        ptle_p^.status := tmc$ts_ready_but_swapped;
        ptle_p^.idle_status := tmc$is_idled_sched_notified;
        jmp$ready_task_in_swapped_job (cst_p^.ijl_ordinal, cst_p^.ijle_p);
      IFEND;

    ELSEIF (tmv$timed_wait_queue.head <> 0) { XCB_P is nil, so we have no executing job.
{    } AND (tmv$ptl_p^ [tmv$timed_wait_queue.head].end_of_wait_time <= clock) THEN
      p$update_timed_wait_queue (clock, tmv$timed_wait_queue);
    IFEND;

    IF (cst_p^.cpu_state.next_state = osc$cpu_stepped) THEN
      ptlo := 0;
      tmp$clear_lock (tmv$ptl_lock);
      mtp$error_stop ('terminated through the dispatcher path');
      { Any processor which follows this path is NOT the one driving the system into STEP mode.  THEREFORE,
      { the call above is valid because the driving processor has the correct reason for calling STEP.
      tmp$set_lock (tmv$ptl_lock{, mtc$ignore});

    ELSE

{ Select next task for execution.
{ If cst_p^.next_ptlo_to_dispatch is non-zero, that task has already been selected to
{ execute on this CPU through the ready task path, so switch to it.
{ NOTE: The variable local_set must be initialized to use later to determine the
{ dual state priority.  Tmv$dual_state_prio_mask contains dispatching priorities for
{ tasks that would have been dispatched, but could not be because the job the task belonged
{ to did not allow multi-processing.  Those priorities should not be considered when
{ determining the dual state priority.
{
{ If the next_ptlo_to_dispatch field is zero, a new task to execute needs to be selected now.
{ Empty the tmv$dual_state_prio_mask set; the select code will determine which priorities
{ can not be dispatched because the tasks queued in the DCT for that priority belong to jobs
{ which do not allow multi-processing.
{ Tmv$dispatching_control_sets contains the following dispatching priority sets:
{ enforce_maximums--priorities which cannot use more than the specified maximum % of the CPU.
{ minimums_to_satisfy--priorities which have not received the specified minimum % of the CPU.
{ (System priorities can use 100% of the CPU, so they are always in minimums_to_satisfy.)
{ ready_tasks--priorities with tasks in the DCT.
{ maximums_exceeded--priorities that have exceeded the specified maximum % of the CPU.
{ For select_next_task, priorities which have exceeded maximum and for which the maximum is
{ enforced are removed from the sets; they cannot execute for the rest of the interval.
{ The remaining priorities with ready tasks are manipulated so that each priority is set
{ only once in any of the three sets (which are ordered, left to right) : minimums_to_satisfy,
{ ready_tasks, maximums_exceeded.  The conversion process pulls off the leftmost bit set in the sets.
{ Thus, priorities with a minimum percentage to satisfy are selected first, followed by priorities
{ with ready tasks that have not exceeded the maximum percentage.  Priorities which have exceeded
{ the maximum but are not prevented from executing by enforce maximum are selected last.
{ When the dispatching priority has been selected, tasks from that DCT queue are considered,
{ until one is found that can execute.
{
{ NOTE:  --PURGE BUFFERS--  If the task or the job the task belongs to did not last execute
{ on this CPU, then cache must be purged.  If multiprocessing is allowed, the last processor
{ for the task is checked.
{ For non-multiprocessing jobs, the last processor for the job is checked.  The task can
{ execute only if the job has no other tasks executing.  If a task has been pre_selected to execute,
{ the executing_task_count was checked and incremented by the pre-selection code.
{ If the task is being selected from the DCT, the task is selected and cache purged if the
{ executing_task_count = 0.

      IF cst_p^.next_ptlo_to_dispatch <> 0 THEN
        ptlo := cst_p^.next_ptlo_to_dispatch;
        ptle_p := ^tmv$ptl_p^ [ptlo];
        cst_p^.next_ptlo_to_dispatch := 0;
        cst_p^.ijl_ordinal := ptle_p^.ijl_ordinal;
        cst_p^.ijle_p := jmf$ijle_p (cst_p^.ijl_ordinal);
        cst_p^.ajlo := cst_p^.ijle_p^.ajl_ordinal;
        cst_p^.jcb_p := #ADDRESS (1, cst_p^.ajlo + mtc$job_fixed_segment, 0);
        xcb_p := #ADDRESS (1, mtc$job_fixed_segment + cst_p^.ajlo, ptle_p^.xcb_offset);
        local_set.enforce_maximums := $jmt$dispatching_priority_set [];
        local_set.minimums_to_satisfy := $jmt$dispatching_priority_set [];
        local_set.ready_tasks := (tmv$dispatching_control_sets.ready_tasks) +
              $jmt$dispatching_priority_set [jmc$dp_conversion - ptle_p^.dispatching_priority];
        local_set.maximums_exceeded := $jmt$dispatching_priority_set [];

        IF osv$cpus_logically_on > 1 THEN
          IF cst_p^.ijle_p^.multiprocessing_allowed THEN
            IF xcb_p^.last_lpid_for_task <> cst_p^.cst_index THEN
              { NOTE: The second parameter on the #purge_buffer command is just a dummy pointer.
              #PURGE_BUFFER (osc$purge_all_cache, xcb_p);
              #PURGE_BUFFER (osc$purge_all_page_seg_map, xcb_p);
            IFEND;
          ELSE
            IF cst_p^.jcb_p^.last_lpid_for_job <> cst_p^.cst_index THEN
              #PURGE_BUFFER (osc$purge_all_cache, xcb_p);
              #PURGE_BUFFER (osc$purge_all_page_seg_map, xcb_p);
            IFEND;
          IFEND;
        IFEND;

      ELSE { Select a new task to execute. }

        local_set := tmv$dispatching_control_sets;
        local_set.ready_tasks := local_set.ready_tasks - (local_set.enforce_maximums *
              local_set.maximums_exceeded);
        local_set.enforce_maximums := $jmt$dispatching_priority_set [];
        local_set.minimums_to_satisfy := local_set.minimums_to_satisfy * local_set.ready_tasks;
        local_set.maximums_exceeded := local_set.maximums_exceeded * local_set.ready_tasks;
        local_set.ready_tasks := local_set.ready_tasks XOR (local_set.minimums_to_satisfy +
              local_set.maximums_exceeded);

        #UNCHECKED_CONVERSION (local_set, integer_dp_sets);
        priority.r := $REAL (integer_dp_sets);

        ptlo := 0;

      /find_next_task/
        WHILE priority.dp_mask.dp <> 0 DO
          ptlo := tmv$dct [priority.dp_mask.dp].queue_head;

          WHILE ptlo <> 0 DO
            ptle_p := ^tmv$ptl_p^ [ptlo];
            cst_p^.ijl_ordinal := ptle_p^.ijl_ordinal;
            cst_p^.ijle_p := jmf$ijle_p (cst_p^.ijl_ordinal);
            cst_p^.ajlo := cst_p^.ijle_p^.ajl_ordinal;
            cst_p^.jcb_p := #ADDRESS (1, cst_p^.ajlo + mtc$job_fixed_segment, 0);
            xcb_p := #ADDRESS (1, mtc$job_fixed_segment + cst_p^.ajlo, ptle_p^.xcb_offset);

            IF osv$cpus_logically_on > 1 THEN
              IF cst_p^.cst_index IN xcb_p^.processor_selections THEN
                IF cst_p^.ijle_p^.multiprocessing_allowed THEN
                  IF xcb_p^.last_lpid_for_task <> cst_p^.cst_index THEN
                    { NOTE: The second parameter on the #purge_buffer command is just a dummy pointer.
                    #PURGE_BUFFER (osc$purge_all_cache, xcb_p);
                    #PURGE_BUFFER (osc$purge_all_page_seg_map, xcb_p);
                  IFEND;
                  EXIT /find_next_task/; {----->
                ELSEIF cst_p^.ijle_p^.executing_task_count = 0 THEN
                  IF cst_p^.jcb_p^.last_lpid_for_job <> cst_p^.cst_index THEN
                    #PURGE_BUFFER (osc$purge_all_cache, xcb_p);
                    #PURGE_BUFFER (osc$purge_all_page_seg_map, xcb_p);
                  IFEND;
                  EXIT /find_next_task/; {----->
                IFEND;
              IFEND;
            ELSE
              EXIT /find_next_task/; {----->
            IFEND;
            ptlo := tmv$ptl_p^ [ptlo].ptl_thread;
          WHILEND;

{ No task of the priority selected could execute.  Remove the priority from the sets and select
{ another priority.  Add the priority to tmv$dual_state_prio_mask so that the priority is not
{ considered when determining the dual state priority on subsequent pre-select task switches.

          dispatching_priority := $jmt$dispatching_priority_set [jmc$dp_conversion - priority.dp_mask.dp];
          local_set.minimums_to_satisfy := local_set.minimums_to_satisfy - dispatching_priority;
          local_set.ready_tasks := local_set.ready_tasks - dispatching_priority;
          local_set.maximums_exceeded := local_set.maximums_exceeded - dispatching_priority;

          #UNCHECKED_CONVERSION (local_set, integer_dp_sets);
          priority.r := $REAL (integer_dp_sets);
        WHILEND /find_next_task/;

        IF ptlo <> 0 THEN
          cst_p^.dispatching_priority_integer := integer_dp_sets;
          p$remove_task_from_dct (ptlo);
          cst_p^.ijle_p^.executing_task_count := cst_p^.ijle_p^.executing_task_count + 1;
        IFEND;
      IFEND;
    IFEND;

{Update the next time to ready a task from the timed wait queue.
    IF (tmv$timed_wait_queue.head = 0) THEN
      time := 0ffffffffffff(16);
    ELSE
      time := tmv$ptl_p^ [tmv$timed_wait_queue.head].end_of_wait_time;
    IFEND;
    tmv$time_to_call_dispatcher := time;

{  Set up the CPU STATE TABLE.
    IF ptlo = 0 THEN
      IF cst_p^.cpu_idle_statistics.idle_type = osc$not_idle THEN
        cst_p^.cpu_idle_statistics.idle_start_time := clock;
        IF (tmv$swapin_in_progress <> 0) OR (tmv$wait_queue_statistics [tmc$ts_page_wait] <> 0)
{     } OR (tmv$wait_queue_statistics [tmc$ts_io_wait_queued] <> 0) THEN
          cst_p^.cpu_idle_statistics.idle_type := osc$idle_with_io_active;
        ELSE
          cst_p^.cpu_idle_statistics.idle_type := osc$idle_no_io_active;
        IFEND;
      IFEND;
      cst_p^.dispatching_priority := 0;
      cst_p^.dispatching_priority_integer := 0;
      cst_p^.xcb_p := NIL;
      cst_p^.taskid.index := 0;
      time := time - clock; {Time was calculated above to define next dispatcher run.
      IF time < 10 THEN
        time := 10;
      ELSEIF time > 50000 THEN
        time := 50000;
      IFEND;
      cst_p^.max_cptime := time;

    ELSE { A new task has been selected.  Update the cpu_idle_statistics.
      IF cst_p^.cpu_idle_statistics.idle_type <> osc$not_idle THEN
        idle_time := clock - cst_p^.cpu_idle_statistics.idle_start_time;
        IF cst_p^.cpu_idle_statistics.idle_type = osc$idle_with_io_active THEN
          cst_p^.cpu_idle_statistics.idle_io_active := cst_p^.cpu_idle_statistics.idle_io_active + idle_time;
        ELSE
          cst_p^.cpu_idle_statistics.idle_no_io_active := cst_p^.cpu_idle_statistics.idle_no_io_active +
                idle_time;
        IFEND;
        IF tmv$dispatching_controls.controls_defined THEN
          p$update_dispatching_controls (idle_time, jmc$null_dispatching_priority);
        IFEND;
        cst_p^.cpu_idle_statistics.idle_type := osc$not_idle;
        cst_p^.cpu_idle_statistics.idle_count := cst_p^.cpu_idle_statistics.idle_count + 1;
      IFEND;

{ Set task status to executing and set up the rest of the CST fields.

      ptle_p^.status := tmc$ts_executing;

      cst_p^.taskid.index := ptlo;
      cst_p^.taskid.seqno := ptle_p^.sequence_number;
      cst_p^.xcb_p := xcb_p;
      cst_p^.max_cptime := xcb_p^.timeslice.minor;
      cst_p^.dispatching_priority := ptle_p^.dispatching_priority;

{ To prevent NOS-NOS/VE problems when VE dispatching allocation is used, the dual state priority has to
{ equal the highest priority ready task on VE (which is the task that would have been selected on VE if
{ dispatching allocation was not being used).  If the dual state priority of a low priority VE task that
{ was selected over a higher priority VE task because of dispatching allocation is used, NOS can shut out
{ VE.  The dispatching allocation interval will never expire, and the higher priority VE task will never
{ get to execute.

      local_set.ready_tasks := local_set.ready_tasks + local_set.minimums_to_satisfy +
            local_set.maximums_exceeded;
      local_set.minimums_to_satisfy := $jmt$dispatching_priority_set [];
      #UNCHECKED_CONVERSION (local_set, integer_dp_sets);
      priority.r := $REAL (integer_dp_sets);

      IF ptle_p^.monitor_flags <> $syt$monitor_flags [] THEN
        xcb_p^.xp.user_condition_register := xcb_p^.xp.user_condition_register +
              $ost$user_conditions [osc$free_flag];
        xcb_p^.monitor_flags := xcb_p^.monitor_flags + ptle_p^.monitor_flags;
        ptle_p^.monitor_flags := $syt$monitor_flags [];
      IFEND;
      IF ptle_p^.system_flags <> $tmt$system_flags [] THEN
        xcb_p^.system_flags := xcb_p^.system_flags + ptle_p^.system_flags;
        ptle_p^.system_flags := $tmt$system_flags [];
      IFEND;

      IF (ptle_p^.ptl_flags.wait_inhibited = tmc$wi_wait_inhibited) THEN
        xcb_p^.wait_inhibited := TRUE;
      IFEND;
      ptle_p^.ptl_flags.wait_inhibited := tmc$wi_null;

{Set keypoint mask & keypoint enable flag in job exchange package. Set the value for monitor's keypoint mask.
      #WRITE_REGISTER (osc$pr_set_keypoint_enable, $INTEGER (xcb_p^.keypoint_register_enable));
    IFEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$switch_task;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$SWITCH_TASK_FROM_FAILING_CP', EJECT ??

  PROCEDURE [XDCL] tmp$switch_task_from_failing_cp
    (VAR cst_p: ^ost$cpu_state_table);

    VAR
      next_task_ijle_p: ^jmt$initiated_job_list_entry,
      next_task_xcb_p: ^ost$execution_control_block,
      ptle_p: ^tmt$primary_task_list_entry,
      ptlo: ost$task_index,
      xcb_p: ^ost$execution_control_block;

?? NEWTITLE := '[inline] TMP$GET_XCB_P_FROM_PTLO', EJECT ??

    FUNCTION [INLINE] f$xcb_p_from_ptlo
      (    ptlo: ost$task_index;
           ajl_ordinal: jmt$ajl_ordinal): ^ost$execution_control_block;

      f$xcb_p_from_ptlo := #ADDRESS (1, ajl_ordinal + mtc$job_fixed_segment, tmv$ptl_p^ [ptlo].xcb_offset);

    FUNCEND f$xcb_p_from_ptlo;
?? OLDTITLE ??
?? EJECT ??
    xcb_p := cst_p^.xcb_p;

    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});

    IF xcb_p <> NIL THEN
      xcb_p^.timeslice := jmv$service_classes [cst_p^.ijle_p^.job_scheduler_data.service_class]^.attributes.
            dispatching_control [cst_p^.ijle_p^.dispatching_control.dispatching_control_index].
            dispatching_timeslice;
      xcb_p^.last_lpid_for_task := cst_p^.cst_index;
      cst_p^.jcb_p^.last_lpid_for_job := cst_p^.cst_index;
      cst_p^.jcb_p^.last_execution_time := #FREE_RUNNING_CLOCK (0);
      ptlo := cst_p^.taskid.index;
      ptle_p := ^tmv$ptl_p^ [ptlo];
      cst_p^.ijle_p^.executing_task_count := cst_p^.ijle_p^.executing_task_count - 1;
      IF ptle_p^.new_task_status > tmc$ts_last_status_in_dct THEN
        ptle_p^.status := ptle_p^.new_task_status;
        ptle_p^.new_task_status := tmc$ts_null;
        cst_p^.ijle_p^.statistics.ready_task_count := cst_p^.ijle_p^.statistics.ready_task_count - 1;
        IF ptle_p^.status <= tmc$ts_last_status_in_wait_q THEN
          p$insert_timed_wait_queue (ptlo);
        IFEND;
        IF (ptle_p^.status = tmc$ts_timeout_reqexp_longvlong) OR
              (ptle_p^.status = tmc$ts_timed_wait_not_queued) OR
              (ptle_p^.status = tmc$ts_timeout_reqexp_infvlong) THEN
          cst_p^.ijle_p^.statistics.tasks_not_in_long_wait :=
                cst_p^.ijle_p^.statistics.tasks_not_in_long_wait - 1;
          IF (cst_p^.ijle_p^.statistics.tasks_not_in_long_wait = 0) AND
                (cst_p^.ijle_p^.entry_status = jmc$ies_job_in_memory) AND
                (ptle_p^.idle_status = tmc$is_not_idled) THEN
            cst_p^.xcb_p := NIL;
            p$set_swapout_candidate (cst_p^.ajlo);
          IFEND;
        IFEND;
      ELSE
        ptle_p^.status := tmc$ts_ready;
        p$dct_ready_task (xcb_p, cst_p^.ijle_p, ptlo, TRUE);
      IFEND;
      cst_p^.dispatching_priority := 0;
      cst_p^.dispatching_priority_integer := 0;
      cst_p^.xcb_p := NIL;
      cst_p^.taskid.index := 0;
    IFEND;

{ If a task has been pre-selected to run on this CPU, that task needs to be inserted in the DCT.

    IF cst_p^.next_ptlo_to_dispatch <> 0 THEN
      next_task_ijle_p := jmf$ijle_p (tmv$ptl_p^ [cst_p^.next_ptlo_to_dispatch].ijl_ordinal);
      next_task_ijle_p^.executing_task_count := next_task_ijle_p^.executing_task_count - 1;
      tmv$ptl_p^ [cst_p^.next_ptlo_to_dispatch].status := tmc$ts_ready;
      next_task_xcb_p := f$xcb_p_from_ptlo (cst_p^.next_ptlo_to_dispatch, next_task_ijle_p^.ajl_ordinal);
      p$dct_ready_task (next_task_xcb_p, next_task_ijle_p, cst_p^.next_ptlo_to_dispatch, TRUE);
      cst_p^.next_ptlo_to_dispatch := 0;
    IFEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$switch_task_from_failing_cp;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$TASK_EXIT', EJECT ??

  PROCEDURE [XDCL] tmp$task_exit
    (VAR rb: tmt$rb_task_exit;
         cst_p: ^ost$cpu_state_table);

*copyc tmh$task_exit

    VAR
      osv$trap_task_errors: [XDCL, #GATE] boolean := FALSE;

    VAR
      ijle_p: ^jmt$initiated_job_list_entry,
      pit_value: integer;

    rb.status.normal := TRUE;
    IF rb.parent_global_task_id <> cst_p^.xcb_p^.parent_global_task_id THEN
      mtp$set_status_abnormal ('TM', tme$invalid_global_taskid, rb.status);
      RETURN; {----->
    IFEND;

*if false
    IF osv$trap_task_errors AND ((cst_p^.xcb_p^.system_table_lock_count DIV 256) <> 0) THEN
      mtp$error_stop (' Task exit with system tables locked ');
    IFEND;
*ifend

    tmp$update_system_task_list (cst_p^.xcb_p);

{  Send signal to the parent task.
    tmp$send_signal (rb.parent_global_task_id, rb.signal, rb.status);
    IF NOT rb.status.normal THEN
      RETURN; {----->
    IFEND;

    mmp$exit_task (cst_p^.xcb_p);
    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
{   mtv$ptl_recovery_info.subcode := mtc$sc_exiting_task;
    ijle_p := cst_p^.ijle_p;
    ijle_p^.maxws_aio_slowdown_display := 0;
    ijle_p^.statistics.ready_task_count := ijle_p^.statistics.ready_task_count - 1;
    ijle_p^.statistics.tasks_not_in_long_wait := ijle_p^.statistics.tasks_not_in_long_wait - 1;
    ijle_p^.task_created_after_last_swap := FALSE;
    cst_p^.accumulated_monitor_cptime := 0ffffffff(16) - #READ_REGISTER (osc$pr_process_interval_timer);
    pit_value := cst_p^.xcb_p^.xp.process_interval_timer_1 *
          10000(16) + cst_p^.xcb_p^.xp.process_interval_timer_2;
    IF pit_value > 7fffffff(16) THEN
      pit_value := pit_value - 100000000(16);
    IFEND;

    cst_p^.accumulated_job_cptime := cst_p^.accumulated_job_cptime - pit_value;
    p$update_cp_statistics (cst_p);
    ijle_p^.executing_task_count := ijle_p^.executing_task_count - 1;
    p$free_ptl (cst_p^.taskid.index);
    p$remove_ijl (cst_p^.taskid, cst_p);
    cst_p^.xcb_p^.task_has_terminated := TRUE;
    cst_p^.jcb_p^.last_lpid_for_job := cst_p^.cst_index;
    cst_p^.xcb_p := NIL;
    cst_p^.dispatch_control.call_dispatcher := TRUE;
    IF (cst_p^.next_ptlo_to_dispatch = 0) THEN
      cst_p^.dispatching_priority_integer := tmv$dct_priority_integer;
    IFEND;

    tmv$total_task_count := tmv$total_task_count - 1;

    IF tmv$ptl_p^ [cst_p^.taskid.index].idle_status = tmc$is_idle_initiated THEN
      p$initiate_swap_if_possible (cst_p);
    IFEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$task_exit;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl] TMP$TEST_GET_XCB_P', EJECT ??

  PROCEDURE [XDCL] tmp$test_get_xcb_p
    (    taskid: ost$global_task_id;
     VAR xcb_p: ^ost$execution_control_block;
     VAR ijle_p: ^jmt$initiated_job_list_entry);

{ NOTE:
{   This procedure will increment the ajl in use count or assign an ajl if xcb access is possible.
{   It is the callers responsibility to decrement it with a call to jmp$free_ajl_entry.

    VAR
      inhibit_access: boolean;

    tmp$set_lock (tmv$ptl_lock{, mtc$fixup_ajl});

    IF (taskid = tmv$null_global_task_id) OR (taskid.index > UPPERBOUND (tmv$ptl_p^)) OR
          (tmv$ptl_p^ [taskid.index].sequence_number <> taskid.seqno) OR
          (tmv$ptl_p^ [taskid.index].status = tmc$ts_null) THEN
      xcb_p := NIL;
      ijle_p := NIL;
    ELSE
      ijle_p := jmf$ijle_p (tmv$ptl_p^ [taskid.index].ijl_ordinal);

      tmp$get_xcb_access_status (ijle_p, tmv$ptl_p^ [taskid.index].ijl_ordinal, inhibit_access);
      IF inhibit_access THEN
        xcb_p := NIL;
      ELSE
        xcb_p := #ADDRESS (1, ijle_p^.ajl_ordinal + mtc$job_fixed_segment,
              tmv$ptl_p^ [taskid.index].xcb_offset);
      IFEND;
    IFEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$test_get_xcb_p;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] tmp$update_job_task_cpu_selects', EJECT ??

{ PURPOSE:
{   This procedure changes the processor selections in the XCB for all tasks in the system.
{
{ DESIGN:
{   The knowledge of the cpus which are still logically on is contained in the SCB.  If the XCB of the job can
{   be referenced (ie, the job is NOT swapped out) changes to the XCB are made.  If the job is swapped out,
{   the delayed swapin work bit is set, which causes the changes to the XCB to be made when the job swaps back
{   in.

  PROCEDURE [XDCL] tmp$update_job_task_cpu_selects;

    VAR
      delayed_swapin_work_record: jmt$delayed_swapin_work_record,
      state: tmt$find_next_xcb_state,
      xcb_p: ^ost$execution_control_block;

{ Set the delayed swapin work bit in the ijl for all jobs.  Only swapped jobs will look at it.
    delayed_swapin_work_record.delayed_swapin_work := $jmt$delayed_swapin_work
          [jmc$dsw_adjust_cpu_selections];
    jsp$set_delayed_swapin_work_mtr (delayed_swapin_work_record);

{ Update the XCB in active jobs.
    tmp$set_lock (tmv$ptl_lock{, mtc$abandon});
    p$find_next_xcb_init_system (state, xcb_p);

    mtv$scb.cpus.available_for_use := mtv$scb.cpus.logically_on;

    WHILE xcb_p <> NIL DO
      IF xcb_p^.requested_processor_selections * mtv$scb.cpus.available_for_use = $ost$processor_id_set
            [] THEN
        xcb_p^.processor_selections := mtv$scb.cpus.available_for_use;
      ELSE
        xcb_p^.processor_selections := xcb_p^.requested_processor_selections * mtv$scb.cpus.available_for_use;
      IFEND;
      p$find_next_xcb_continue (state, xcb_p);
    WHILEND;

    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$update_job_task_cpu_selects;
?? OLDTITLE ??
?? NEWTITLE := 'TMP$UPDATE_JOB_TASK_ENVIRONMENT', EJECT ??

{ Changes the dispatching priority and timeslice in the XCB for all tasks of a job.
{
{ DESIGN:
{   The caller has stored the new dispatching priority in the IJL.
{   If the XCB of the job can be referenced (ie, the job is NOT swapped out)
{   changes to the XCB are made.  If the job is swapped out, the delayed
{   swapin work bit is set, which causes this procedure to be called again
{   when the job swaps back in.

  PROCEDURE [XDCL] tmp$update_job_task_environment
    (    ijle_p: ^jmt$initiated_job_list_entry;
         ijl_ordinal: jmt$ijl_ordinal;
         xcb_search: tmt$fnx_search_type);

    VAR
      xcb_p: ^ost$execution_control_block,
      state: tmt$find_next_xcb_state;

    tmp$set_lock (tmv$ptl_lock{, mtc$ignore});
    IF xcb_search = tmc$fnx_system THEN
      p$find_next_xcb_init_system (state, xcb_p);
    ELSE
      p$find_next_xcb_init_non_system (xcb_search, ijle_p, ijl_ordinal, state, xcb_p);
    IFEND;

    IF xcb_p = NIL THEN
      ijle_p^.delayed_swapin_work := ijle_p^.delayed_swapin_work +
            $jmt$delayed_swapin_work [jmc$dsw_update_job_task_enviro];
    ELSE
      p$i_update_job_task_environment (ijle_p, state, xcb_p);
    IFEND;
    tmp$clear_lock (tmv$ptl_lock);

  PROCEND tmp$update_job_task_environment;
?? OLDTITLE ??
MODEND tmm$dispatcher;
