?? RIGHT := 110 ??
MODULE sym$service_routines_113;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains service routines that run in ring 1.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc syc$monitor_request_codes
*copyc pmf$executing_task_xcb
*copyc osd$virtual_address
*copyc jmt$system_supplied_name
*copyc jmt$user_supplied_name
*copyc mmt$rb_lock_ring_1_stack
*copyc tmt$rb_cycle
*copyc tmt$rb_exit_job
?? POP ??
*copyc cmp$check_foreign_io
*copyc mmp$invalidate_segment
*copyc mmp$mfh_for_segment_manager
*copyc mmp$validate_segment_number
*copyc osp$fatal_system_error
*copyc osp$free_heap_pages
*copyc osp$system_error
*copyc pmp$get_job_names
*copyc syp$wait
*copyc dmv$mainframe_recovered
*copyc jmv$jcb
*copyc mtv$cst0
*copyc mtv$request_table
*copyc osv$job_fixed_heap
*copyc osv$mainframe_wired_heap
*copyc syv$halt_on_exit_with_io
*copyc i#call_monitor
?? OLDTITLE ??
?? NEWTITLE := 'SYP$RETURN_JOBS_R1_RESOURCES', EJECT ??

  PROCEDURE [XDCL, #GATE] syp$return_jobs_r1_resources;

*copy syh$return_jobs_r1_resources

    VAR
      exit_job_rb: tmt$rb_exit_job,
      r1_stack_rb: mmt$rb_lock_ring_1_stack,
      sdt_entry_p: ^mmt$segment_descriptor,
      sdtx_entry_p: ^mmt$segment_descriptor_extended,
      status: ost$status,
      xcb_p: ^ost$execution_control_block;

{ Issue monitor request to change the ring 1 stack to a transient segment for the remainder of
{ job termination.

    r1_stack_rb.request_code := syc$rc_lock_ring_1_stack;
    REPEAT
      i#call_monitor (#LOC (r1_stack_rb), #SIZE (r1_stack_rb));
    UNTIL r1_stack_rb.status.normal;

{ Check the job's active io count; if it is non-zero the job must wait for the io to complete or the
{ system will crash later when it does.  Foreign PP io is the known case that allows job termination
{ with io still active.

    IF jmv$jcb.ijle_p^.active_io_page_count <> 0 THEN
      syp$job_exit_with_io;
    IFEND;

{  Issue 'exit_job' monitor request.  This request frees memory of remaining segments unique to
{  this job.  This returns the last of this job's resources.

    exit_job_rb.reqcode := syc$rc_exit_job;
    i#call_monitor (#LOC (exit_job_rb), #SIZE (exit_job_rb));
    osp$system_error ('Exit job monitor request returned.', NIL);

  PROCEND syp$return_jobs_r1_resources;
?? OLDTITLE ??
?? NEWTITLE := 'syp$job_exit_with_io', EJECT ??

{ PURPOSE:
{   This procedure checks the job's active io count; if it is non-zero the job must wait for the io
{   to complete or the system will crash later when it does.  Foreign PP io is the known case that
{   allows job termination with io still active.  The system attribute, HALT_ON_EXIT_WITH_IO, determines
{   whether this situation should halt the system or cause the job to wait for the io to complete.
{   If the job waits and the io never completes, the job will be hung in memory.

  PROCEDURE [XDCL] syp$job_exit_with_io;

    CONST
      syc$wait_for_sio_delay = 3, {thirty second delay for subsystem I/O}
      syc$wait_for_io_delay = 180; {18 minute delay to account for the 15 minute DAS diagnostics.

    VAR
      counter: integer,
      user_job_name: jmt$user_supplied_name,
      system_job_name: jmt$system_supplied_name,
      match: boolean,
      status: ost$status;

    pmp$get_job_names (user_job_name, system_job_name, status);
    match := FALSE;
{ If this job is associated with foreign I/O we can elimiate the possibility
{ of DAS diagnostics and terminate now.
    cmp$check_foreign_io (system_job_name, user_job_name, match);
    IF match THEN
{ Wait ten seconds for subsystem I/O to cleanup then terminate.
      counter := 0;
      WHILE (counter < syc$wait_for_sio_delay) AND (jmv$jcb.ijle_p^.active_io_page_count <> 0) DO
        syp$wait (10000);
        counter := counter + 1;
      WHILEND;
      RETURN; {----->
    IFEND;


    counter := 0;
    IF syv$halt_on_exit_with_io THEN
      osp$system_error ('JOB EXIT WITH IO ACTIVE', ^status);
    ELSE
      WHILE (counter < syc$wait_for_io_delay) AND (jmv$jcb.ijle_p^.active_io_page_count <> 0) DO
        syp$wait (10000);
        counter := counter + 1;
      WHILEND;
    IFEND;

  PROCEND syp$job_exit_with_io;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] SYP$RESET_MAXIMUM_TIME', EJECT ??

  PROCEDURE [XDCL, #GATE] syp$reset_maximum_time;

    VAR
      i: integer;

    FOR i := LOWERBOUND (mtv$request_table) TO UPPERBOUND (mtv$request_table) DO
      mtv$request_table [i].max_time := 0;
    FOREND;

  PROCEND syp$reset_maximum_time;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] OSP$BEGIN_SYSTEM_ACTIVITY', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$begin_system_activity;

    VAR
      xcb_p: ^ost$execution_control_block;

    xcb_p:=  pmf$executing_task_xcb ();
    xcb_p^.system_table_lock_count := xcb_p^.system_table_lock_count + 256;

  PROCEND osp$begin_system_activity;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] OSP$END_SYSTEM_ACTIVITY', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$end_system_activity;

    TYPE
      psa_type = record
        fill: 0 .. 0ffff(16),
        p: ^cell,
        a0,
        a1: integer,
        fill2: 0 .. 0ffff(16),
        a2: ^psa_type,
      recend;

    VAR
      xcb_p: ^ost$execution_control_block,
      rb: tmt$rb_cycle,
      psa: ^psa_type,
      cycle_task: tmt$rb_cycle;

    xcb_p:=  pmf$executing_task_xcb ();

{ Debug code.

    IF xcb_p^.system_table_lock_count < 256 THEN
      osp$system_error ('END_SYSTEM_ACTIVITY error', NIL);
    IFEND;

{ End debug code.

    xcb_p^.system_table_lock_count := xcb_p^.system_table_lock_count - 256;
    IF (xcb_p^.system_table_lock_count < 256) AND xcb_p^.system_give_up_cpu THEN
      rb.reqcode := syc$rc_cycle;
      rb.code := tmc$cyc_end_system_activity;
      psa := #PREVIOUS_SAVE_AREA ();
      rb.p1 := psa^.p;
      IF psa^.a2 = NIL THEN
        rb.p2 := NIL;
      ELSE
        rb.p2 := psa^.a2^.p;
      IFEND;
      rb.lock_value := 0;
      i#call_monitor (#LOC (rb), #SIZE (rb));
    IFEND;

    IF xcb_p^.stlc_allocation AND (xcb_p^.system_table_lock_count < 256) THEN
      xcb_p^.stlc_allocation := FALSE;
      mmp$mfh_for_segment_manager;
    IFEND;

  PROCEND osp$end_system_activity;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] OSP$BEGIN_SUBSYSTEM_ACTIVITY', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$begin_subsystem_activity;

    VAR
      xcb_p: ^ost$execution_control_block;

    xcb_p:=  pmf$executing_task_xcb ();
    IF ((xcb_p^.system_table_lock_count MOD 256) = 255) THEN
      osp$system_error ('SUBSYSTEM TABLE LOCK COUNT EXCEEDED', NIL);
    IFEND;
    xcb_p^.system_table_lock_count := xcb_p^.system_table_lock_count + 1;

  PROCEND osp$begin_subsystem_activity;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] OSP$END_SUBSYSTEM_ACTIVITY', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$end_subsystem_activity;

    TYPE
      psa_type = record
        fill: 0 .. 0ffff(16),
        p: ^cell,
        a0,
        a1: integer,
        fill2: 0 .. 0ffff(16),
        a2: ^psa_type,
      recend;

    VAR
      psa: ^psa_type,
      rb: tmt$rb_cycle,
      xcb_p: ^ost$execution_control_block;


    xcb_p:=  pmf$executing_task_xcb ();
{ Debug code.

    IF ((xcb_p^.system_table_lock_count MOD 256) = 0) THEN
      osp$system_error ('END_SUBSYSTEM_ACTIVITY error', NIL);
    IFEND;

{ End debug code.

    xcb_p^.system_table_lock_count := xcb_p^.system_table_lock_count - 1;
    IF (xcb_p^.system_table_lock_count <= 0) AND xcb_p^.subsystem_give_up_cpu THEN
      rb.reqcode := syc$rc_cycle;
      rb.code := tmc$cyc_end_system_activity;
      psa := #PREVIOUS_SAVE_AREA ();
      rb.p1 := psa^.p;
      IF psa^.a2 = NIL THEN
        rb.p2 := NIL;
      ELSE
        rb.p2 := psa^.a2^.p;
      IFEND;
      rb.lock_value := 0;
      i#call_monitor (#LOC (rb), #SIZE (rb));
    IFEND;

  PROCEND osp$end_subsystem_activity;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] SYP$CLEANUP_HEAP_PAGES', EJECT ??

  PROCEDURE [XDCL, #GATE] syp$cleanup_heap_pages;

    osp$free_heap_pages (osv$mainframe_wired_heap);

  PROCEND syp$cleanup_heap_pages;
?? OLDTITLE ??
?? NEWTITLE := '[xdcl, #gate] SYP$SET_MAINFRAME_RECOVERED', EJECT ??

  PROCEDURE [XDCL, #GATE] syp$set_mainframe_recovered
    (    mainframe_recovered: boolean);

    dmv$mainframe_recovered := mainframe_recovered;

  PROCEND syp$set_mainframe_recovered;
?? OLDTITLE ??
MODEND sym$service_routines_113;
