?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE: Program Control - Program Conditions' ??
MODULE tmm$broken_task_fault_processor;
{ PURPOSE:
{   This module contains and restricts the knowledge necessary to dispose
{   of the broken task monitor fault.
{
{ DESIGN:
{   The procedure in this module are designed to have an execute bracket
{   of 1, 13 and a call bracket of 13.
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc osc$processor_defined_registers
*copyc osd$registers
*copyc osd$virtual_address
*copyc ost$monitor_fault
*copyc ost$stack_frame_save_area
*copyc ost$status
*copyc tmt$broken_task_monitor_fault
*copyc pme$condition_exceptions
?? POP ??
*copyc clp$convert_integer_to_rjstring
*copyc osp$generate_log_message
*copyc osp$monitor_fault_to_status
*copyc osp$system_error
*copyc pmp$push_task_debug_mode
*copyc pmp$exit
*copyc pmp$abort
*copyc pmp$debug_logging_enabled
*copyc pmp$log_ascii
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] tmp$dispose_of_broken_task', EJECT ??
*copy tmh$dispose_of_broken_task

  PROCEDURE [XDCL] tmp$dispose_of_broken_task
    (    fault: ost$monitor_fault;
         sfsa: ^ost$stack_frame_save_area);

    CONST
      empty_p_register_string = 'P = 0 000 00000000';

    VAR
      broken_task: ^tmt$broken_task_monitor_fault,
      ignore_status: ost$status,
      inhibit_frame: ^ost$stack_frame_save_area,
      logset: pmt$ascii_logset,
      minimum_save_area_p: ^ost$minimum_save_area,
      p_register_text: string (18),
      status: ost$status;

    logset := $pmt$ascii_logset [pmc$job_log];
    IF pmp$debug_logging_enabled (true {=broken_task}) THEN
      logset := logset + $pmt$ascii_logset [pmc$system_log];
    IFEND;
    p_register_text := empty_p_register_string;

{ Truncate the stack to inhibit PMP$EXIT from popping stack frames.  This allows
{ for the "problem area" of the stack to remain entact for a dump.  The stack is
{ truncated when the procedure causing the monitor fault is reached.

    minimum_save_area_p := ^sfsa^.minimum_save_area;
    inhibit_frame := #PREVIOUS_SAVE_AREA ();
    WHILE (inhibit_frame^.minimum_save_area.a2_previous_save_area <> NIL) DO
      IF inhibit_frame^.minimum_save_area.a2_previous_save_area = sfsa THEN
        inhibit_frame^.minimum_save_area.a2_previous_save_area := NIL;
      ELSE
        inhibit_frame := inhibit_frame^.minimum_save_area.a2_previous_save_area;
      IFEND;
    WHILEND;

    broken_task := #LOC (fault.contents);
    CASE broken_task^.broken_task_condition OF
    = tmc$btc_mntr_fault_buffer_full =
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);

    = tmc$btc_mf_traps_disabled =
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);

    = tmc$btc_invalid_a0 =
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);
      IF status.condition = pme$inconsistent_stack THEN
        pmp$push_task_debug_mode (pmc$debug_mode_off, ignore_status);
        pmp$abort (status);
      IFEND;

    = tmc$btc_invalid_p =
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);

    = tmc$btc_mcr_traps_disabled =
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);

    = tmc$btc_ucr_traps_disabled =
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);

    = tmc$btc_system_error =
      pmp$log_ascii ('* * * SYSTEM ERROR * * *', logset, pmc$msg_origin_system, ignore_status);
      clp$convert_integer_to_rjstring (broken_task^.caller_p_register.pva.ring, 16, FALSE, '0',
            p_register_text (5), status);
      clp$convert_integer_to_rjstring (broken_task^.caller_p_register.pva.seg, 16, FALSE, '0',
            p_register_text (7, 3), status);
      clp$convert_integer_to_rjstring (broken_task^.caller_p_register.pva.offset, 16, FALSE, '0',
            p_register_text (11, 8), status);
      pmp$log_ascii (p_register_text, logset, pmc$msg_origin_system, ignore_status);
      pmp$log_ascii (broken_task^.text_p^, logset, pmc$msg_origin_system, ignore_status);
      IF (broken_task^.trap_enable = osc$traps_disabled) THEN
        pmp$log_ascii ('TRAPS DISABLED', logset, pmc$msg_origin_system, ignore_status);
      IFEND;
      IF (broken_task^.status_p <> NIL) AND (NOT broken_task^.status_p^.normal) THEN
        osp$generate_log_message (logset, broken_task^.status_p^, ignore_status);
      IFEND;
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);

    ELSE
      osp$monitor_fault_to_status (fault, minimum_save_area_p, status);
    CASEND;
    pmp$push_task_debug_mode (pmc$debug_mode_off, ignore_status);

    osp$generate_log_message (logset, status, ignore_status);
    pmp$exit (status);
  PROCEND tmp$dispose_of_broken_task;
?? POP ??
MODEND tmm$broken_task_fault_processor;
