?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE: Program Management - Preemptive Communications' ??
MODULE tmm$dispose_preemptive_commo;

{ PURPOSE:
{   The purpose of this module is to package contained procedures so
{   that they execute with the privileges necessary to read the structures
{   in the execution control block that support signals and system flags.
{
{ DESIGN:
{   The procedures contained in the module have an execution bracket
{   of 2, 3 and a call bracket of 13.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc osc$processor_defined_registers
*copyc oss$job_paged_literal
*copyc oss$task_private
*copyc ost$caller_identifier
*copyc ost$execution_control_block
*copyc pmt$condition
*copyc pmt$task_control_block
*copyc tmc$execution_ring_constants
*copyc tmt$allocated_execution_rings
*copyc tmt$preempted_reason
*copyc tmt$rb_update_job_task_enviro
?? POP ??
*copyc i#call_monitor
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$verify_system_privilege
*copyc pmp$continue_to_cause
*copyc pmp$find_executing_task_xcb
*copyc tmp$allocate_execution_rings
*copyc tmp$dispose_of_ring2_flags
*copyc tmp$dispose_of_ring2_signals
*copyc tmp$dispose_of_ring3_flags
*copyc tmp$dispose_of_ring3_signals
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] tmp$dispose_preemptive_commo', EJECT ??
*copy tmh$dispose_preemptive_commo

  PROCEDURE [XDCL, #GATE] tmp$dispose_preemptive_commo
    (    preempted_reason: tmt$preempted_reason);

    TYPE
      valid_preempted_reasons = set of tmt$preempted_reason,
      signals_present = set of tmt$signal_buffers;

    VAR
      allocated_execution_rings: tmt$allocated_execution_rings,
      execution_ring: tmt$handler_execution_ring,
      preempted: ost$caller_identifier,
      signals_to_process: ^signals_present,
      tcb_p: ^pmt$task_control_block,
      valid_reasons: [STATIC, READ, oss$job_paged_literal] valid_preempted_reasons :=
            $valid_preempted_reasons [tmc$free_flag, tmc$recognition_ring_delay, tmc$x_bracket_delay,
            tmc$task_termination],
      xcb_p: ^ost$execution_control_block;

?? NEWTITLE := 'dispose_of_nonlocal_exit' ??

{ PURPOSE:
{   This procedure ensures that all preemptive communications are processed
{   before a nonlocal exit is premitted to complete or the task is permitted
{   to terminate.

    PROCEDURE dispose_of_nonlocal_exit
      (    condition: pmt$condition;
           condition_descriptor: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR status: ost$status);

      tmp$dispose_preemptive_commo (preempted_reason);
    PROCEND dispose_of_nonlocal_exit;
?? OLDTITLE ??
?? EJECT ??

    osp$verify_system_privilege;
    #CALLER_ID (preempted);
    IF (preempted_reason IN valid_reasons) THEN
      pmp$find_executing_task_xcb (xcb_p);
      tcb_p := xcb_p^.task_control_block;
      signals_to_process := #LOC (xcb_p^.signals.present);
      IF (signals_to_process^ <> $signals_present []) OR (tcb_p^.task_local_signal_list.delink <> NIL) OR
            (xcb_p^.system_flags <> $tmt$system_flags []) THEN
        osp$establish_block_exit_hndlr (^dispose_of_nonlocal_exit);
        IF (signals_to_process^ <> $signals_present []) OR (tcb_p^.task_local_signal_list.delink <> NIL) THEN
          tmp$allocate_execution_rings (preempted.ring, preempted_reason, tmc$signal,
                allocated_execution_rings);
          FOR execution_ring := tmc$lowest_signal_flag_ring TO tmc$highest_signal_flag_ring DO
            IF execution_ring IN allocated_execution_rings THEN
              CASE execution_ring OF
              = tmc$task_monitor2_ring =
                tmp$dispose_of_ring2_signals;
              = tmc$task_services_ring =
                tmp$dispose_of_ring3_signals;
              CASEND;
            IFEND;
          FOREND;
        IFEND;
        IF (xcb_p^.system_flags <> $tmt$system_flags []) THEN
          tmp$allocate_execution_rings (preempted.ring, preempted_reason, tmc$system_flag,
                allocated_execution_rings);
          FOR execution_ring := tmc$lowest_signal_flag_ring TO tmc$highest_signal_flag_ring DO
            IF execution_ring IN allocated_execution_rings THEN
              CASE execution_ring OF
              = tmc$task_monitor2_ring =
                tmp$dispose_of_ring2_flags;
              = tmc$task_services_ring =
                tmp$dispose_of_ring3_flags;
              CASEND;
            IFEND;
          FOREND;
        IFEND;
        osp$disestablish_cond_handler;
      IFEND;
    IFEND;
  PROCEND tmp$dispose_preemptive_commo;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] tmp$dispose_of_inserted_preempt', EJECT ??
*copy tmh$dispose_of_inserted_preempt

  PROCEDURE [XDCL] tmp$dispose_of_inserted_preempt;

    tmp$dispose_preemptive_commo (tmc$x_bracket_delay);
  PROCEND tmp$dispose_of_inserted_preempt;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] tmp$disable_preemptive_commo', EJECT ??
*copy tmh$disable_preemptive_commo

  PROCEDURE [XDCL] tmp$disable_preemptive_commo;

    VAR
      rb: tmt$rb_update_job_task_enviro;

{ Disable preemptive communication then process outstanding signals and flags.
{ Ignore the status on the monitor request.

    rb.reqcode := syc$rc_update_job_task_enviro;
    rb.subcode := tmc$ujte_set_task_terminating;
    i#call_monitor (#LOC (rb), #SIZE (rb));

    tmp$dispose_preemptive_commo (tmc$task_termination);
  PROCEND tmp$disable_preemptive_commo;
?? OLDTITLE ??
MODEND tmm$dispose_preemptive_commo;
