?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Job Management: Deadstart Initialization' ??
MODULE jmm$job_deadstart;

{ PURPOSE:
{   This module contains the code to initialize the Job Management mainframe global tables
{ at system deadstart.

{ DESIGN:
{   The procedures contained in this module are used to create the ring one tables that are used by
{ the Job Management area of NOS/VE.  The tables include the Active Job List (AJL), the Initiated
{ Job List (IJL), the Known Job List (KJL), the Known Output List (KOL), the Known Qfile List (KQL),
{ and the job attribute defaults.  These tables are allocated
{ and initialized during NOS/VE deadstart.
{
{   The procedures used to initialize the NOS/VE CPU dependent names are resident in this module.  The
{ names that are CPU dependent are the mainframe id and the system supplied names assigned to NOS/VE queue
{ files.  These names are assigned as early in NOS/VE deadstart as is possible.
{
{   The procedures to save the essence of the system job as it is deadstarting reside in this module.
{ As NOS/VE deadstart progresses the Job Fixed, Job Pageable, Task Shared and Task Private segments are
{ saved at various states.  This allows other job and task initiations to initialize these segments by
{ moving the contents of the saved system segments to the their own environment.

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

?? PUSH (LISTEXT := ON) ??
*copyc jmc$ajl_caller
*copyc jmc$class_names
*copyc jmc$default_forms_code
*copyc jmc$kjl_maximum_entries
*copyc jmc$kol_maximum_entries
*copyc jmc$maximum_qfile_count
*copyc jmc$special_dispatch_priorities
*copyc jmc$system_family
*copyc jmt$ijl_ordinal
*copyc jmt$initiated_job_list_entry
*copyc jmt$job_class
*copyc jmt$job_control_block
*copyc jmt$kjl_index
*copyc jmt$service_class_index
*copyc jmt$system_core_template
*copyc mmt$segment_descriptor_table
*copyc mmt$segment_descriptor_table_ex
*copyc osc$nosve_job_scheduler
*copyc osc$processor_defined_registers
*copyc osd$virtual_address
*copyc ost$execution_control_block
*copyc ost$global_task_id
*copyc ost$signature_lock
*copyc ost$status
*copyc sfc$unlimited
*copyc tmt$primary_task_list
?? POP ??
*copyc i#move
*copyc jmp$get_ijle_p
*copyc jmp$job_monitor_xcb
*copyc mmp$get_sdt_for_job_template
*copyc osp$initialize_sig_lock
*copyc osp$system_error
*copyc pmp$get_170_os_type
*copyc pmp$get_compact_date_time
*copyc pmp$get_cpu_attributes
*copyc pmp$get_pseudo_mainframe_id
*copyc pmp$initialize_cpu_attributes
*copyc pmp$zero_out_table
*copyc qfp$relink_kjl_application
*copyc qfp$relink_kjl_client
*copyc qfp$relink_kjl_entry
*copyc qfp$relink_kjl_server
*copyc jmv$ajl_p
*copyc jmv$candidate_queued_jobs
*copyc jmv$default_job_attributes
*copyc jmv$executing_within_system_job
*copyc jmv$ijl_p
*copyc jmv$jcb
*copyc jmv$job_counts
*copyc jmv$job_counts_lock
*copyc jmv$kjl_p
*copyc jmv$kjlx_p
*copyc jmv$known_job_list
*copyc jmv$known_output_list
*copyc jmv$known_qfile_list
*copyc jmv$kol_p
*copyc jmv$kql_p
*copyc jmv$number_free_ajl_entries
*copyc jmv$system_ajl_ordinal
*copyc jmv$system_ijl_ordinal
*copyc jmv$system_job_ssn
*copyc jmv$system_supplied_name
*copyc mtv$cst0
*copyc mtv$mx_ajl_entries
*copyc mtv$xp_initial_value
*copyc osv$cpus_physically_configured
*copyc osv$job_fixed_heap
*copyc osv$mainframe_pageable_heap
*copyc osv$mainframe_wired_heap
*copyc qfv$current_kjl_limit
*copyc qfv$current_kol_limit
*copyc qfv$current_kql_limit
*copyc qfv$kjl_lock
*copyc qfv$kol_lock
*copyc qfv$kql_lock
*copyc syv$all_jobs_selected_for_debug
?? OLDTITLE ??
?? NEWTITLE := 'Global Variables Declared by this Module', EJECT ??

  VAR
    jmv$ajl_lock: [XDCL, STATIC, oss$mainframe_pageable] ost$signature_lock := [0],
    jmv$system_job_kjl_entry: [STATIC, oss$mainframe_pageable] array [1 .. 1] of jmt$known_job_list_entry,
    jmv$system_job_kjlx_entry: [STATIC, oss$mainframe_pageable] array [1 .. 1] of jmt$known_job_list_extended,
    jmv$system_core_template: [XDCL, #GATE] jmt$system_core_template;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] jmp$init_cpu_dependent_names', EJECT ??

  PROCEDURE [XDCL] jmp$init_cpu_dependent_names
    (VAR status: ost$status);

    VAR
      cpu_attributes: pmt$cpu_attributes,
      length: integer;

?? NEWTITLE := '      change_space_to_zero', EJECT ??

{ This procedure converts trailing space into leading zeros and shifts
{ the contents of the string accordingly.

    PROCEDURE change_space_to_zero
      (VAR stng: string ( * ));

      VAR
        index: integer,
        length: integer;

      length := STRLENGTH (stng);
      IF length > 0 THEN
        WHILE stng (length) = ' ' DO
          FOR index := length DOWNTO 2 DO
            stng (index) := stng (index - 1);
          FOREND;
          stng (1) := '0';
        WHILEND;
      IFEND;
    PROCEND change_space_to_zero;

?? OLDTITLE, EJECT ??

    status.normal := TRUE;

    pmp$initialize_cpu_attributes;

    pmp$get_cpu_attributes (cpu_attributes, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    change_space_to_zero (cpu_attributes.cpu [0].model_number);
    change_space_to_zero (cpu_attributes.cpu [0].serial_number);

    STRINGREP (jmv$system_job_ssn, length, '$', cpu_attributes.cpu [0].
          model_number, '_', cpu_attributes.cpu [0].serial_number, '_AAA_0000');
    jmv$system_supplied_name.system_supplied_name := jmv$system_job_ssn;

  PROCEND jmp$init_cpu_dependent_names;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] jmp$initialize_job_tables', EJECT ??
*copy jmh$initialize_job_tables

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

{ Choose values that give the KJL, KOL, and KQL some predefined size but do not
{ use too much at a time since the more disk space that is used here the less
{ that will be available during recovery.

    CONST
      initial_kjl_limit = 100,
      initial_kol_limit = 100,
      initial_kql_limit = 100;

    VAR
      xcb_p: ^ost$execution_control_block,
      i: integer,
      input_application_index: jmt$input_application_index,
      output_application_index: jmt$output_application_index,
      qfile_application_index: jmt$qfile_application_index,
      system_job_kjl_index: jmt$kjl_index;

{ Initialize system parameters.

    status.normal := TRUE;

{ Initialize signature locks

    osp$initialize_sig_lock (jmv$job_counts_lock);
    osp$initialize_sig_lock (qfv$kjl_lock);
    osp$initialize_sig_lock (qfv$kol_lock);
    osp$initialize_sig_lock (qfv$kql_lock);

{ Zero out table for queued job candidates for initiation

    pmp$zero_out_table (^jmv$candidate_queued_jobs, #SIZE (jmv$candidate_queued_jobs));

{ Allocate the known job list (KJL) and the known job list extended (KJLX).

    ALLOCATE jmv$kjl_p: [1 .. jmc$kjl_maximum_entries] IN osv$mainframe_pageable_heap^;
    ALLOCATE jmv$kjlx_p: [1 .. jmc$kjl_maximum_entries] IN osv$mainframe_pageable_heap^;

{  Initialize KJL.

    pmp$zero_out_table (^jmv$known_job_list, #SIZE (jmv$known_job_list));
    jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry := 1;
    jmv$known_job_list.state_data [jmc$kjl_unused_entry].last_entry := initial_kjl_limit;
    jmv$known_job_list.state_data [jmc$kjl_unused_entry].number_of_entries := initial_kjl_limit;
    jmv$known_job_list.kjl_p := jmv$kjl_p;
    jmv$known_job_list.kjlx_p := jmv$kjlx_p;

    FOR i := 1 TO (initial_kjl_limit - 1) DO
      jmv$kjl_p^ [i].forward_link := i + 1;
      jmv$kjl_p^ [i].reverse_link := i - 1;
      jmv$kjl_p^ [i].entry_kind := jmc$kjl_unused_entry;
    FOREND;

    jmv$kjl_p^ [initial_kjl_limit].forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [initial_kjl_limit].reverse_link := initial_kjl_limit - 1;
    jmv$kjl_p^ [initial_kjl_limit].entry_kind := jmc$kjl_unused_entry;
    qfv$current_kjl_limit := initial_kjl_limit;

    FOR input_application_index := LOWERBOUND (jmv$known_job_list.application_table)
          TO UPPERBOUND (jmv$known_job_list.application_table) DO
      jmv$known_job_list.application_table [input_application_index].application_name := osc$null_name;
      jmv$known_job_list.application_table [input_application_index].destination_usage := osc$null_name;
      jmv$known_job_list.application_table [input_application_index].global_task_id.index := 0;
      jmv$known_job_list.application_table [input_application_index].global_task_id.seqno := 0;
      jmv$known_job_list.application_table [input_application_index].queue_file_password := osc$null_name;
    FOREND;

{ Initialize an entry for the job scheduler application in the KJL's input application table.
{ The global task id in this entry is used for the NOS/VE Job Leveler.

    jmv$known_job_list.application_table [jmc$ve_input_application_index].application_name :=
          osc$nosve_job_scheduler;
    jmv$known_job_list.application_table [jmc$ve_input_application_index].destination_usage := jmc$ve_usage;
    jmv$known_job_list.application_table [jmc$ve_input_application_index].global_task_id.index := 0;
    jmv$known_job_list.application_table [jmc$ve_input_application_index].global_task_id.seqno := 0;
    jmv$known_job_list.application_table [jmc$ve_input_application_index].queue_file_password :=
          osc$null_name;

{ Initialize the client mainframe entry in the KJL for this mainframe.  All fields except the mainframe id
{ should be initialized to zeroes (this was done above).

    pmp$get_pseudo_mainframe_id (
          jmv$known_job_list.client_data.state_data [jmc$kjl_client_this_mainframe].mainframe_id);

{ Initialize the server mainframe entry in the KJL for this mainframe.  All fields except the mainframe id
{ should be initialized to zeroes (this was done above).

    jmv$known_job_list.server_data.state_data [jmc$kjl_server_this_mainframe].mainframe_id :=
          jmv$known_job_list.client_data.state_data [jmc$kjl_client_this_mainframe].mainframe_id;

{ Initialize the job counts table.

    pmp$zero_out_table (^jmv$job_counts, #SIZE (jmv$job_counts));
    jmv$job_counts.initiated_jobs := jmv$job_counts.initiated_jobs + 1;
    jmv$job_counts.job_class_counts [jmc$system_job_class].
          initiated_jobs := jmv$job_counts.job_class_counts [jmc$system_job_class].initiated_jobs + 1;

{  Activate an entry for the system job.

    xcb_p := jmp$job_monitor_xcb ();

    system_job_kjl_index := jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry;
    jmv$system_job_kjl_entry [1].forward_link := jmv$kjl_p^ [system_job_kjl_index].forward_link;
    jmv$system_job_kjl_entry [1].reverse_link := jmv$kjl_p^ [system_job_kjl_index].reverse_link;

    jmv$kjl_p^ [system_job_kjl_index] := jmv$system_job_kjl_entry [1];
    jmv$kjlx_p^ [system_job_kjl_index] := jmv$system_job_kjlx_entry [1];

    jmv$kjl_p^ [system_job_kjl_index].entry_kind := jmc$kjl_unused_entry;
    qfp$relink_kjl_entry (system_job_kjl_index, jmv$kjl_p^ [system_job_kjl_index].job_class,
          jmc$kjl_initiated_entry);
    jmv$kjl_p^ [system_job_kjl_index].application_state := jmc$kjl_application_unused;
    qfp$relink_kjl_application (system_job_kjl_index, jmc$ve_input_application_index,
          jmc$kjl_application_initiated);
    qfp$relink_kjl_server (system_job_kjl_index, jmc$kjl_server_this_mainframe);
    qfp$relink_kjl_client (system_job_kjl_index, jmc$kjl_client_this_mainframe);

{ Initialize the system jobs job_id in the JCB.

    jmv$jcb.job_id := system_job_kjl_index;

{  Allocate known output list (KOL).

    ALLOCATE jmv$kol_p: [1 .. jmc$kol_maximum_entries] IN osv$mainframe_pageable_heap^;

{  Initialize KOL.

    pmp$zero_out_table (^jmv$known_output_list, #SIZE (jmv$known_output_list));
    jmv$known_output_list.state_data [jmc$kol_unused_entry].first_entry := 1;
    jmv$known_output_list.state_data [jmc$kol_unused_entry].last_entry := initial_kol_limit;
    jmv$known_output_list.state_data [jmc$kol_unused_entry].number_of_entries := initial_kol_limit;
    jmv$known_output_list.kol_p := jmv$kol_p;

    FOR i := 1 TO (initial_kol_limit - 1) DO
      jmv$kol_p^ [i].forward_link := i + 1;
      jmv$kol_p^ [i].reverse_link := i - 1;
      jmv$kol_p^ [i].entry_kind := jmc$kol_unused_entry;
    FOREND;
    jmv$kol_p^ [initial_kol_limit].forward_link := jmc$kol_undefined_index;
    jmv$kol_p^ [initial_kol_limit].reverse_link := initial_kol_limit - 1;
    jmv$kol_p^ [initial_kol_limit].entry_kind := jmc$kol_unused_entry;
    qfv$current_kol_limit := initial_kol_limit;

    FOR output_application_index := LOWERBOUND (jmv$known_output_list.application_table)
          TO UPPERBOUND (jmv$known_output_list.application_table) DO
      jmv$known_output_list.application_table [output_application_index].application_name := osc$null_name;
      jmv$known_output_list.application_table [output_application_index].destination_usage := osc$null_name;
      jmv$known_output_list.application_table [output_application_index].global_task_id.index := 0;
      jmv$known_output_list.application_table [output_application_index].global_task_id.seqno := 0;
      jmv$known_output_list.application_table [output_application_index].queue_file_password := osc$null_name;
    FOREND;

{  Allocate known qfile list (KQL).

    ALLOCATE jmv$kql_p: [1 .. jmc$maximum_qfile_count] IN osv$mainframe_pageable_heap^;

{  Initialize KQL.

    pmp$zero_out_table (^jmv$known_qfile_list, #SIZE (jmv$known_qfile_list));
    jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry := 1;
    jmv$known_qfile_list.state_data [jmc$kql_unused_entry].last_entry := initial_kql_limit;
    jmv$known_qfile_list.state_data [jmc$kql_unused_entry].number_of_entries := initial_kql_limit;
    jmv$known_qfile_list.kql_p := jmv$kql_p;

    FOR i := 1 TO (initial_kql_limit - 1) DO
      jmv$kql_p^ [i].forward_link := i + 1;
      jmv$kql_p^ [i].reverse_link := i - 1;
      jmv$kql_p^ [i].entry_kind := jmc$kql_unused_entry;
    FOREND;
    jmv$kql_p^ [initial_kql_limit].forward_link := jmc$kql_undefined_index;
    jmv$kql_p^ [initial_kql_limit].reverse_link := initial_kql_limit - 1;
    jmv$kql_p^ [initial_kql_limit].entry_kind := jmc$kql_unused_entry;
    qfv$current_kql_limit := initial_kql_limit;

    FOR qfile_application_index := LOWERBOUND (jmv$known_qfile_list.application_table)
          TO UPPERBOUND (jmv$known_qfile_list.application_table) DO
      jmv$known_qfile_list.application_table [qfile_application_index].application_name := osc$null_name;
      jmv$known_qfile_list.application_table [qfile_application_index].global_task_id.index := 0;
      jmv$known_qfile_list.application_table [qfile_application_index].global_task_id.seqno := 0;
      jmv$known_qfile_list.application_table [qfile_application_index].registration_options.
            notify_on_terminate := FALSE;
      jmv$known_qfile_list.application_table [qfile_application_index].queue_file_password := osc$null_name;
    FOREND;
  PROCEND jmp$initialize_job_tables;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] jmp$initialize_ajl_ijl', EJECT ??
*copy jmh$initialize_ajl_ijl

  PROCEDURE [XDCL] jmp$initialize_ajl_ijl;

    VAR
      ignore_status: ost$status,
      ijle_p: ^jmt$initiated_job_list_entry,
      job_mode: jmt$job_mode,
      job_qualifier_index: 1 .. jmc$maximum_job_qualifiers,
      os_type: ost$170_os_type,
      system_job_kjl_index: jmt$kjl_index,
      xcb_p: ^ost$execution_control_block,
      i: integer;

    pmp$get_170_os_type (os_type, ignore_status);

{ Initialize the default job attributes

    FOR job_mode := jmc$batch TO jmc$interactive_connected DO
      jmv$default_job_attributes [job_mode].cpu_time_limit := sfc$unlimited;
      jmv$default_job_attributes [job_mode].device := 'AUTOMATIC';
      jmv$default_job_attributes [job_mode].external_characteristics := 'NORMAL';
      jmv$default_job_attributes [job_mode].forms_code := jmc$default_forms_code;
      jmv$default_job_attributes [job_mode].job_abort_disposition := jmc$terminate_on_abort;
      IF job_mode = jmc$batch THEN
        jmv$default_job_attributes [job_mode].job_class := jmc$batch_class_name;
        jmv$default_job_attributes [job_mode].job_destination_usage := jmc$ve_qtf_usage;
      ELSE
        jmv$default_job_attributes [job_mode].job_class := jmc$interactive_class_name;
        jmv$default_job_attributes [job_mode].job_destination_usage := jmc$ve_local_usage;
      IFEND;
      jmv$default_job_attributes [job_mode].job_deferred_by_operator := FALSE;
      FOR job_qualifier_index := 1 TO jmc$maximum_job_qualifiers DO
        jmv$default_job_attributes [job_mode].job_qualifier_list [job_qualifier_index] := osc$null_name;
      FOREND;
      jmv$default_job_attributes [job_mode].job_recovery_disposition := jmc$continue_on_recovery;
      jmv$default_job_attributes [job_mode].login_family := jmc$system_family;
      jmv$default_job_attributes [job_mode].magnetic_tape_limit := jmc$unspecified_mag_tape_limit;
      jmv$default_job_attributes [job_mode].maximum_working_set := 1000;
      jmv$default_job_attributes [job_mode].output_class := jmc$normal_class_name;
      jmv$default_job_attributes [job_mode].output_deferred_by_operator := FALSE;
      IF os_type = osc$ot7_none THEN
        jmv$default_job_attributes [job_mode].output_destination_usage := jmc$public_usage;
      ELSE
        jmv$default_job_attributes [job_mode].output_destination_usage := jmc$dual_state_usage;
      IFEND;
      jmv$default_job_attributes [job_mode].output_priority := 'LOW';
      jmv$default_job_attributes [job_mode].purge_delay.specified := FALSE;
      jmv$default_job_attributes [job_mode].qfile_deferred_by_operator := FALSE;
      jmv$default_job_attributes [job_mode].site_information := '';
      jmv$default_job_attributes [job_mode].station := 'AUTOMATIC';
      jmv$default_job_attributes [job_mode].sru_limit := sfc$unlimited;
      jmv$default_job_attributes [job_mode].vertical_print_density := jmc$vertical_print_density_file;
      jmv$default_job_attributes [job_mode].vfu_load_procedure := '';
    FOREND;

{ Build a mini-KJL for the system job to use until we can allocate the full KJL.

    jmv$kjl_p := ^jmv$system_job_kjl_entry;
    jmv$kjlx_p := ^jmv$system_job_kjlx_entry;
    pmp$zero_out_table (jmv$kjl_p, #SIZE (jmv$kjl_p^));

    pmp$zero_out_table (^jmv$known_job_list, #SIZE (jmv$known_job_list));
    jmv$known_job_list.state_data [jmc$kjl_initiated_entry].first_entry := 1;
    jmv$known_job_list.state_data [jmc$kjl_initiated_entry].last_entry := 1;
    jmv$known_job_list.state_data [jmc$kjl_initiated_entry].number_of_entries := 1;
    jmv$known_job_list.kjl_p := jmv$kjl_p;
    jmv$known_job_list.kjlx_p := jmv$kjlx_p;

{ Activate an entry for the system job.

    xcb_p := jmp$job_monitor_xcb ();

    system_job_kjl_index := 1;
    jmv$kjl_p^ [system_job_kjl_index].system_job_name := jmv$system_job_ssn;
    jmv$kjl_p^ [system_job_kjl_index].user_job_name := jmc$system_user;
    jmv$kjl_p^ [system_job_kjl_index].initiated_job_list_ordinal := jmv$system_ijl_ordinal;
    jmv$kjl_p^ [system_job_kjl_index].job_submission_time := jmc$earliest_clock_time;
    jmv$kjl_p^ [system_job_kjl_index].earliest_clock_time_to_initiate := jmc$earliest_clock_time;
    jmv$kjl_p^ [system_job_kjl_index].job_class := jmc$system_job_class;
    jmv$kjl_p^ [system_job_kjl_index].job_category_set := $jmt$job_category_set [];
    jmv$kjl_p^ [system_job_kjl_index].job_priority := 0;
    jmv$kjl_p^ [system_job_kjl_index].job_deferred_by_operator := FALSE;
    jmv$kjl_p^ [system_job_kjl_index].job_deferred_by_user := FALSE;
    jmv$kjl_p^ [system_job_kjl_index].login_family_available := TRUE;
    jmv$kjl_p^ [system_job_kjl_index].destination_usage := jmc$ve_usage;
    jmv$kjl_p^ [system_job_kjl_index].next_destination_usage := jmc$ve_usage;
    jmv$kjl_p^ [system_job_kjl_index].application_state := jmc$kjl_application_initiated;
    jmv$kjl_p^ [system_job_kjl_index].application_forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].application_reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].entry_kind := jmc$kjl_initiated_entry;
    jmv$kjl_p^ [system_job_kjl_index].forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].class_forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].class_reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].client_index := jmc$kjl_client_undefined;
    jmv$kjl_p^ [system_job_kjl_index].client_forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].client_reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].server_index := jmc$kjl_server_undefined;
    jmv$kjl_p^ [system_job_kjl_index].server_forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].server_reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [system_job_kjl_index].server_kjl_index := system_job_kjl_index;

    jmv$kjlx_p^ [system_job_kjl_index].login_user_identification.family := jmc$system_family;
    jmv$kjlx_p^ [system_job_kjl_index].login_user_identification.user := jmc$system_user;
    jmv$kjlx_p^ [system_job_kjl_index].job_controller.family := jmc$system_family;
    jmv$kjlx_p^ [system_job_kjl_index].job_controller.user := jmc$system_user;
    jmv$kjlx_p^ [system_job_kjl_index].originating_ssn := jmv$kjl_p^ [system_job_kjl_index].system_job_name;
    jmv$kjlx_p^ [system_job_kjl_index].latest_clock_time_to_initiate := jmc$latest_clock_time;
    jmv$kjlx_p^ [system_job_kjl_index].job_mode := jmc$batch;
    jmv$kjlx_p^ [system_job_kjl_index].job_monitor_global_task_id := xcb_p^.global_task_id;
    jmv$kjlx_p^ [system_job_kjl_index].output_disposition_key := jmc$normal_output_disposition;
    jmv$kjlx_p^ [system_job_kjl_index].input_file_location := jmc$ifl_no_input_file_exists;
    jmv$kjlx_p^ [system_job_kjl_index].valid_mainframe_set := $jmt$valid_mainframe_set [];
    jmv$kjlx_p^ [system_job_kjl_index].timesharing_job := FALSE;
    jmv$kjlx_p^ [system_job_kjl_index].restart_job := FALSE;
    jmv$kjlx_p^ [system_job_kjl_index].system_label_p := NIL;
    jmv$kjlx_p^ [system_job_kjl_index].terminal_name := osc$null_name;
    pmp$get_compact_date_time (jmv$kjlx_p^ [system_job_kjl_index].job_initiation_time, ignore_status);

    jmv$jcb.job_id := system_job_kjl_index;

{ Allocate active job list (AJL).

    ALLOCATE jmv$ajl_p: [jmv$system_ajl_ordinal .. mtv$mx_ajl_entries + osv$cpus_physically_configured] IN
          osv$mainframe_wired_heap^;
    pmp$zero_out_table (#LOC (jmv$ajl_p^), #SIZE (jmv$ajl_p^));

    FOR i := jmv$system_ajl_ordinal TO mtv$mx_ajl_entries + osv$cpus_physically_configured DO
      jmv$ajl_p^ [i].ijle_p := NIL;
    FOREND;

{ Mark the system job ajl entry as active and connect to the kjl.

    jmv$ajl_p^ [jmv$system_ajl_ordinal].in_use := jmc$swapping_ajl;
    jmv$ajl_p^ [jmv$system_ajl_ordinal].ijl_ordinal := jmv$system_ijl_ordinal;

{
{  Set number of free AJL entries, the system job takes the first AJL ordinal.
{

    jmv$number_free_ajl_entries := mtv$mx_ajl_entries - jmv$system_ajl_ordinal;

{
{  Allocate initiated job list (IJL)
{
{ The size of the initiated job list (IJL) is controlled by the maximum number of tasks that
{ there can be.  Since each job consists of at least one task, the number of IJL entries
{ required is less than or equal to the number of tasks that can exist.
{
{ Please note: there is no precaution taken to prevent the system from running out of IJL
{ entries.  It can't happen.  The above constraint is why.

    ALLOCATE jmv$ijl_p.block_p: [0 .. tmc$maximum_ptl DIV (UPPERVALUE (jmt$ijl_block_index) + 1)] IN
          osv$mainframe_wired_heap^;
    ALLOCATE jmv$ijl_p.block_p^ [0].index_p IN osv$mainframe_wired_heap^;
    pmp$zero_out_table (#LOC (jmv$ijl_p.block_p^ [0].index_p^), #SIZE (jmv$ijl_p.block_p^ [0].index_p^));
    jmv$ijl_p.block_p^ [0].in_use_count := 1;
    jmp$get_ijle_p (jmv$system_ijl_ordinal, ijle_p);

    i := #READ_REGISTER (osc$pr_maintenance_id);
    mtv$cst0 [i].ijl_ordinal := jmv$system_ijl_ordinal;
    mtv$cst0 [i].ajlo := jmv$system_ajl_ordinal;
    mtv$cst0 [i].ijle_p := ijle_p;
    jmv$ajl_p^ [jmv$system_ajl_ordinal].ijle_p := ijle_p;
    ijle_p^.job_name := jmv$kjl_p^ [system_job_kjl_index].user_job_name;
    ijle_p^.system_supplied_name := jmv$kjl_p^ [system_job_kjl_index].system_job_name;
    ijle_p^.entry_status := jmc$ies_job_in_memory_non_swap;
    ijle_p^.ajl_ordinal := jmv$system_ajl_ordinal;
    ijle_p^.kjl_ordinal := system_job_kjl_index;
    ijle_p^.executing_task_count := 1;
    ijle_p^.job_scheduler_data.swapout_reason := jmc$sr_null;
    ijle_p^.job_scheduler_data.job_class := jmc$system_job_class;
    ijle_p^.job_scheduler_data.service_class := jmc$system_service_class;
    ijle_p^.job_monitor_taskid := mtv$cst0 [i].taskid;
    ijle_p^.swap_status := jmc$iss_executing;
    ijle_p^.dispatching_control.dispatching_control_index := jmc$min_dispatching_control;
    ijle_p^.dispatching_control.dispatching_priority := jmc$priority_system_job;
    ijle_p^.scheduling_dispatching_priority := jmc$priority_system_job;
    ijle_p^.dispatching_control.service_remaining := jmc$dc_maximum_service_limit;
    ijle_p^.sfd_p := NIL;
    ijle_p^.job_fixed_contiguous_pages := 0;
    IF syv$all_jobs_selected_for_debug THEN
      ijle_p^.system_breakpoint_selected := TRUE;
    IFEND;
    jmv$jcb.ijle_p := ijle_p;

  PROCEND jmp$initialize_ajl_ijl;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] jmp$save_system_core_template', EJECT ??

  PROCEDURE [XDCL] jmp$save_system_core_template
    (VAR status: ost$status);

    VAR
      i: integer,
      j: integer,
      k: integer,
      l: integer,
      rn: ost$ring,
      len: ost$byte_count,
      segment_number: ost$segment,
      xcb_p: ^ost$execution_control_block;

    status.normal := TRUE;

{ Save current System Core environment.

    jmv$executing_within_system_job := FALSE;
    len := #OFFSET (^osv$job_fixed_heap^);
    len := len + 100;
    ALLOCATE jmv$system_core_template.job_fixed_template_p: [1 .. len] IN osv$mainframe_pageable_heap^;
    i#move (#ADDRESS (1, osc$segnum_job_fixed_heap, 0), #LOC (jmv$system_core_template.job_fixed_template_p^),
          #SIZE (jmv$system_core_template.job_fixed_template_p^));

{ Set system job flag for system job.

    jmv$executing_within_system_job := TRUE;

{ Form XCB offset.

    xcb_p := jmp$job_monitor_xcb ();
    i := #OFFSET (xcb_p);

{ Check for JCB overflow.

    IF #SIZE (jmv$jcb) > i THEN
      status.normal := FALSE;
      osp$system_error ('JOB CONTROL BLOCK OVERFLOW', ^status);
    IFEND;

{ Save JMTR xcb offset.

    jmv$system_core_template.jmtr_xcb_offset := i;

{ Form template offset in heap.

    j := #OFFSET (#LOC (jmv$system_core_template.job_fixed_template_p^));

{ Form pointer to JCB in system core template.

    jmv$system_core_template.jcb_p := #ADDRESS (1, #SEGMENT (^osv$mainframe_pageable_heap^), j);

{ Form pointer to XCB in system core template.

    jmv$system_core_template.xcb_p := #ADDRESS (1, #SEGMENT (^osv$mainframe_pageable_heap^), j + i);

{ Form pointer to SDT in system core template.

    k := xcb_p^.sdt_offset;
    jmv$system_core_template.sdt_p := #ADDRESS (1, #SEGMENT (^osv$mainframe_pageable_heap^), j + k);

{ Form pointer to SDTX in system core template.

    l := xcb_p^.sdtx_offset;
    jmv$system_core_template.sdtx_p := #ADDRESS (1, #SEGMENT (^osv$mainframe_pageable_heap^), j + l);

{ Zero out JCB in system core template.

    pmp$zero_out_table (#LOC (jmv$system_core_template.jcb_p^), #SIZE (jmv$system_core_template.jcb_p^));

{ Initialize the XP portion of the XCB in the system core template.

    jmv$system_core_template.xcb_p^.xp := mtv$xp_initial_value;

{ Initialize the accounting fields in the XCB.

    jmv$system_core_template.xcb_p^.dispatching_priority_bias_id := jmc$dpb_positive;
    jmv$system_core_template.xcb_p^.cp_time.time_spent_in_job_mode := 0;
    jmv$system_core_template.xcb_p^.cp_time.time_spent_in_mtr_mode := 0;
    jmv$system_core_template.xcb_p^.proc_malf_count := 0;
    jmv$system_core_template.xcb_p^.paging_statistics.page_fault_count := 0;
    jmv$system_core_template.xcb_p^.paging_statistics.pages_from_server := 0;
    jmv$system_core_template.xcb_p^.paging_statistics.page_in_count := 0;
    jmv$system_core_template.xcb_p^.paging_statistics.pages_reclaimed_from_queue := 0;
    jmv$system_core_template.xcb_p^.paging_statistics.new_pages_assigned := 0;

{ Clear stack segments of SDT in the system core template.

    FOR rn := 1 TO 3 DO
      jmv$system_core_template.sdt_p^ [jmv$system_core_template.xcb_p^.xp.tos_registers [rn].pva.seg].
            ste.asid := 0;
    FOREND;
    jmv$system_core_template.sdt_p^ [osc$segnum_job_fixed_heap].ste.asid := 0;
    jmv$system_core_template.sdt_p^ [osc$segnum_job_pageable_heap].ste.asid := 0;
    jmv$system_core_template.sdt_p^ [osc$segnum_task_shared_heap].ste.asid := 0;
    jmv$system_core_template.sdt_p^ [osc$segnum_task_private_heap].ste.asid := 0;
    jmv$system_core_template.sdt_p^ [osc$segnum_task_private_ring_11].ste.asid := 0;

{  Scan the SDTX for non-template segments and delete these segments from the SDT.

    FOR segment_number := 0 TO jmv$system_core_template.xcb_p^.xp.segment_table_length DO
      IF jmv$system_core_template.sdtx_p^ [segment_number].inheritance = mmc$si_none THEN
        jmv$system_core_template.sdt_p^ [segment_number].ste.vl := osc$vl_invalid_entry;
      IFEND;
      jmv$system_core_template.sdtx_p^ [segment_number].assign_active := osc$max_segment_length;
    FOREND;
  PROCEND jmp$save_system_core_template;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] jmp$update_job_template_sdt', EJECT ??

  PROCEDURE [XDCL] jmp$update_job_template_sdt
    (    pva: ^cell;
     VAR status: ost$status);

    VAR
      segment_number: 0 .. 4095,
      sdt_entry: mmt$segment_descriptor,
      sdtx_entry: mmt$segment_descriptor_extended;

    status.normal := TRUE;

    IF jmv$executing_within_system_job = FALSE THEN
      status.normal := FALSE;
      RETURN;
    IFEND;

    segment_number := #SEGMENT (pva);

    mmp$get_sdt_for_job_template (pva, sdt_entry, sdtx_entry, status);
    IF status.normal = FALSE THEN
      RETURN;
    IFEND;

    jmv$system_core_template.sdt_p^ [segment_number] := sdt_entry;
    jmv$system_core_template.sdtx_p^ [segment_number] := sdtx_entry;
  PROCEND jmp$update_job_template_sdt;
?? OLDTITLE ??
MODEND jmm$job_deadstart;
