?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE job_management initialize job environment' ??
?? NEWTITLE := '  JMM$INITIALIZE_JOB_ENVIRONMENT', EJECT ??
MODULE jmm$initialize_job_environment;

{ Purpose: This module contains the code necessary to initialize the
{          initial job environment.

?? NEWTITLE := '    Global Declarations Referenced by this Module', EJECT ??

?? PUSH (LISTEXT := ON) ??
*copyc oss$job_pageable
*copyc oss$task_private
*copyc pmc$default_user_stack_size
*copyc osd$virtual_address
*copyc ost$heap
*copyc ost$status
*copyc pmt$program_description
*copyc pmt$program_parameters
?? POP ??
*copyc i#call_monitor
*copyc i#disable_traps
*copyc i#move
*copyc i#program_error
*copyc jmp$initialize_jcb
*copyc mmp$delete_non_inherited_segs
*copyc mmp$init_system_privilege_map
*copyc mmp$job_delete_inherited_sdt
*copyc osp$initialize_sc_debugger
*copyc osp$reset_heap_ext
*copyc osp$system_error
*copyc pmp$delay
*copyc syp$initialize_job_template
*copyc jmv$executing_within_system_job
*copyc jmv$jcb
*copyc jmv$job_attributes
*copyc jmv$kjl_p
*copyc jmv$system_job_template_p
*copyc osv$system_privilege_map
*copyc syv$nosve_job_template

  VAR
    osv$jp_heap_min_frag_alloc_size: [XREF] integer,
    osv$ts_heap_min_frag_alloc_size: [XREF] integer;

?? TITLE := '    JMP$DELETE_NON_INHERITED_SEGS', EJECT ??

  PROCEDURE [XDCL, #GATE] jmp$delete_non_inherited_segs (VAR status: ost$status);

    mmp$delete_non_inherited_segs (status);

  PROCEND jmp$delete_non_inherited_segs;
?? TITLE := '    JMP$EXIT_JOB', EJECT ??

  PROCEDURE [XDCL, #GATE] jmp$exit_job;

    VAR
      old_trap_enable: 0 .. 3,
      status: ost$status;

{  Disable traps for the remainder of job termination.  Do not want to be interrupted by monitor flags.

    i#disable_traps (old_trap_enable);

{  Delete all inherited segments in the job environment except for those needed to exit the job.
{  Call ring 1 interface to delete remainder of the job environment.  This
{  procedure call is not expected to return.

    mmp$job_delete_inherited_sdt;

  PROCEND jmp$exit_job;

?? TITLE := '    JMP$INITIALIZE_JOB_ENVIRONMENT', EJECT ??

  PROCEDURE [XDCL, #GATE] jmp$initialize_job_environment (VAR jmtr_initial_ring: ost$ring;
    VAR jmtr_program_description_p: ^pmt$program_description;
    VAR jmtr_program_parameters_p: ^pmt$program_parameters;
    VAR status: ost$status);

    VAR
      osv$job_pageable_heap: [XDCL, oss$job_pageable] ^ost$heap,

      osv$task_private_heap: [XDCL, #GATE, oss$job_pageable] ^ost$heap,

      osv$task_shared_heap: [XDCL, #GATE, oss$job_pageable] ^ost$heap;

    VAR
      jp_seg_p: ^cell,
      ts_seg_p: ^cell,
      te: 0 .. 3,
      lfn: ost$name,
      zero_length_sequence: [oss$job_pageable] SEQ (REP 0 of cell),
      dest_pva: ^cell,
      templ_entry_p: ^jmt$job_templ_segment,
      max_segs: ost$segment,
      scan: ost$segment,
      p: ^ost$pva;

    status.normal := TRUE;

    IF NOT jmv$executing_within_system_job THEN
      { Move job templates into their respective segments.

      IF syv$nosve_job_template THEN
      max_segs := UPPERBOUND (jmv$system_job_template_p^.job_template);
      FOR scan := 1 TO max_segs DO
        templ_entry_p := ^jmv$system_job_template_p^.job_template [scan];
        IF templ_entry_p^.writeable_segment AND NOT templ_entry_p^.tasking_segment THEN
          dest_pva := #address (1, templ_entry_p^.seg_no, 0);
          i#move (templ_entry_p^.static_data_p, dest_pva, #SIZE (templ_entry_p^.static_data_p^));
        IFEND;
      FOREND;
      ELSE
        syp$initialize_job_template (FALSE, NIL);
        osp$initialize_sc_debugger;
      IFEND;
    ELSE

      { This code is entered once per deadstart.  Make the call to initialize
      { the system privilege bit map. This call goes to ring 1.

      mmp$init_system_privilege_map (#offset(#loc(osv$system_privilege_map)));

    IFEND;

{ CAUTION: The following check is to assure that the job scheduler has
{          notified queued files that this job has been initiated.
{          Presumably, this should never loop!?  Do NOT remove unless
{          timing window has been removed.  See also the note in
{          JMM$QUEUE_FILE_SCHED_INTERFACES dealing with the relink.

    WHILE jmv$kjl_p^ [jmv$jcb.job_id].entry_kind <> jmc$kjl_initiated_entry DO
      pmp$delay (100, status);
      IF NOT status.normal THEN
        i#program_error;
      IFEND;
    WHILEND;

{ Initialize the Job Control Block

    jmp$initialize_jcb;

{ Set up job Pageable and task shared heaps.

    osp$reset_heap_ext (osv$job_pageable_heap, 100000000, TRUE, 1, osv$jp_heap_min_frag_alloc_size,
          osv$jp_heap_min_frag_alloc_size, osv$jp_heap_min_frag_alloc_size);
    osp$reset_heap_ext (osv$task_shared_heap, 100000000, TRUE, 1, osv$ts_heap_min_frag_alloc_size,
          osv$ts_heap_min_frag_alloc_size, osv$ts_heap_min_frag_alloc_size);

{ Build packet of job monitor information needed for task manager.

    jmtr_program_description_p := ^zero_length_sequence;
    jmtr_program_parameters_p := ^zero_length_sequence;
    jmtr_initial_ring := osc$user_ring;

  PROCEND jmp$initialize_job_environment;


?? TITLE := '    JMP$SYSTEM_ERROR', EJECT ??

  PROCEDURE [XDCL, #GATE] jmp$system_error (error_message: string ( * );
        status: ^ost$status);

    osp$system_error (error_message, status);
  PROCEND jmp$system_error;
MODEND jmm$initialize_job_environment;
