MODULE osm$keypoint_support_r1;
?? PUSH (LISTEXT := ON) ??
*copyc amt$file_identifier
*copyc osc$multiprocessor_constants
*copyc osd$default_pragmats
*copyc ose$keypoint_conditions
*copyc ost$execution_control_block

*copyc jmv$ijl_p
*copyc jmv$jcb
*copyc jmv$null_ijl_ordinal
*copyc mtv$scb
*copyc osv$keypoint_control
*copyc osv$mainframe_wired_cb_heap
*copyc osv$page_size
*copyc syv$perf_keypoints_enabled
*copyc syv$pmf_cb_rm_word_address
*copyc tmv$ptl_p

*copyc i#call_monitor
*copyc i$real_memory_address
*copyc jmp$get_ijle_p
*copyc dmp$allocate_file_space_r1
*copyc mmp$get_sdtx_entry_p
*copyc osp$fetch_locked_variable
*copyc osp$set_locked_variable
*copyc osp$set_status_abnormal
*copyc osp$fatal_system_error
*copyc pmp$delay
*copyc pmp$find_executing_task_xcb
?? POP ??

  VAR
    ppu_keypoint_control: ^ost$ppu_keypoint_control;

?? TITLE := 'osp$reserve_keypoint_r1', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$reserve_keypoint_r1
    (   env: ost$keypoint_environment;
        mm,
        jm: ost$keypoint_class_mask;
        mpo: ost$keypoint_multipro_option;
        kc: integer;
        kbs: integer;
        fap: integer;
        performance_keypoints: syt$perf_keypoints_enabled;
    VAR status: ost$status);

    VAR
      actual: integer,
      i: integer,
      locked: boolean,
      rma: integer;

    osp$set_locked_variable (osv$keypoint_control.lock, 0, 1, actual, locked);
    IF jmv$jcb.system_name = osv$keypoint_control.jsn THEN
      osp$set_status_abnormal ('OS', ose$task_in_job_owns_env, '', status);
      RETURN;
    IFEND;
    IF NOT locked THEN
      osp$set_status_abnormal ('OS', ose$kpt_environment_not_avail, '',
            status);
      RETURN;
    IFEND;
    osp$processor_selections_r1;
    osv$keypoint_control.environment := env;
    osv$keypoint_control.envjm := jm;
    osv$keypoint_control.envmm := mm;
    osv$keypoint_control.jm := $ost$keypoint_mask [];
    osv$keypoint_control.mm := $ost$keypoint_mask [];
    osv$keypoint_control.mpo := mpo;
    osv$keypoint_control.maximum_keypoints := kc;
    osv$keypoint_control.max_pages := kbs;
    osv$keypoint_control.ijlo := jmv$jcb.ijl_ordinal;
    osv$keypoint_control.periodic_requested := FALSE;
    osv$keypoint_control.jsn := jmv$jcb.system_name;
    osv$keypoint_control.first_active_processor := 31;
    osv$keypoint_control.last_active_processor := fap;
    osv$keypoint_control.termination_status := osc$kp_term_not_stopped;

    ALLOCATE ppu_keypoint_control IN osv$mainframe_wired_cb_heap^;
    ppu_keypoint_control^.number_of_processors := 0;
    ppu_keypoint_control^.pages_per_processor := kbs;
    ppu_keypoint_control^.page_size := osv$page_size;
    i#real_memory_address (ppu_keypoint_control, rma);
    syv$pmf_cb_rm_word_address := rma DIV 8;
    syv$perf_keypoints_enabled := performance_keypoints;
    status.normal := TRUE;
  PROCEND osp$reserve_keypoint_r1;
?? TITLE := 'osp$init_keypoints_for_proc', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$init_keypoints_for_proc
    (   collection_pva: ^cell;
        offset: integer;
        mtr_req: ost$rb_keypoint_request;
        pid: integer;
    VAR status: ost$status);

    VAR
      i: integer,
      j: integer,
      lpid: integer,
      ls: ost$status,
      pva: ^cell,
      rma: integer,
      sdtxe_p: ^mmt$segment_descriptor_extended,
      xcb_p: ^ost$execution_control_block;


    osp$fetch_locked_variable (osv$keypoint_control.lock, i);
    IF (i = 0) OR (osv$keypoint_control.jsn <> jmv$jcb.system_name) THEN
      osp$set_status_abnormal ('OS', ose$kpt_illegal_request, '', status);
      RETURN;
    IFEND;
    lpid := #read_register (osc$pr_processor_id);
    IF lpid <> pid THEN
      osp$fatal_system_error (' Init keypoints on wrong processor', NIL);
    IFEND;
    pmp$find_executing_task_xcb (xcb_p);
    sdtxe_p := mmp$get_sdtx_entry_p (xcb_p, #SEGMENT(collection_pva));
    osv$keypoint_control.cpus [lpid].sfid := sdtxe_p^.sfid;
    IF osv$keypoint_control.cpus [lpid].sfid.residence <>
          gfc$tr_system THEN
      osp$set_status_abnormal ('OS', ose$kpt_invalid_collection_file, '',
            status);
      RETURN;
    IFEND;
    IF (osv$keypoint_control.environment = osc$job_keypoints) OR
          (osv$keypoint_control.environment = osc$system_keypoints) THEN
      dmp$allocate_file_space_r1 (osv$keypoint_control.cpus [lpid].sfid, 0,
         osv$keypoint_control.maximum_keypoints * 8, 0, osc$wait, sfc$no_limit, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;
    IF lpid < osv$keypoint_control.first_active_processor THEN
      osv$keypoint_control.first_active_processor := lpid;
    IFEND;
    osv$keypoint_control.cpus [lpid].avail_count := 0;
    osv$keypoint_control.cpus [lpid].io_count := 0;
    osv$keypoint_control.cpus [lpid].in_use_count := 0;
    osv$keypoint_control.cpus [lpid].collector_pva := #address (1,
          osc$kpt_pva_segment, offset);
    osv$keypoint_control.cpus [lpid].pid := pid;
    osv$keypoint_control.cpus [lpid].offset := 0;
    REPEAT
      i#call_monitor (#LOC (mtr_req), #SIZE (mtr_req));
      IF NOT mtr_req.status.normal THEN
        pmp$delay (1000, status);
      IFEND;
    UNTIL mtr_req.status.normal;

    IF osv$keypoint_control.last_active_processor < lpid THEN
      osv$keypoint_control.last_active_processor := lpid;
    IFEND;

    pva := osv$keypoint_control.cpus [lpid].collector_pva;
    i := ppu_keypoint_control^.number_of_processors;
    FOR j := 1 TO ppu_keypoint_control^.pages_per_processor DO
      i#real_memory_address (pva, rma);
      ppu_keypoint_control^.cpus [i] [j] := rma DIV 8;
      pva := #address (#ring (pva), #segment (pva), #offset (pva) +
            osv$page_size);
    FOREND;
    ppu_keypoint_control^.number_of_processors :=
          ppu_keypoint_control^.number_of_processors + 1;
    status.normal := TRUE;
  PROCEND osp$init_keypoints_for_proc;
?? TITLE := 'osp$release_keypoint_r1', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$release_keypoint_r1
    (VAR status: ost$status);

    VAR
      actual: integer,
      i: integer,
      ls: ost$status,
      result: boolean;

    status.normal := TRUE;
    osp$fetch_locked_variable (osv$keypoint_control.lock, i);
    IF (i = 0) OR (osv$keypoint_control.jsn <> jmv$jcb.system_name) THEN
      osp$set_status_abnormal ('OS', ose$kpt_illegal_request, '', status);
      RETURN;
    IFEND;

    syv$pmf_cb_rm_word_address := 0;
    pmp$delay (10000, ls);
    FREE ppu_keypoint_control IN osv$mainframe_wired_cb_heap^;

    osv$keypoint_control.jsn := '     ';
    osv$keypoint_control.first_active_processor := - 2;
    osv$keypoint_control.last_active_processor := - 1;
    osv$keypoint_control.ijlo := jmv$null_ijl_ordinal;
    osv$keypoint_control.processor_select_flag := FALSE;
    syv$perf_keypoints_enabled.memory_keypoints := FALSE;
    syv$perf_keypoints_enabled.heap_keypoints := FALSE;
    syv$perf_keypoints_enabled.swapping_keypoints := FALSE;
    syv$perf_keypoints_enabled.aging_keypoints := FALSE;
    syv$perf_keypoints_enabled.swapping_stack_trace := FALSE;
    syv$perf_keypoints_enabled.aging_stack_trace := FALSE;
    syv$perf_keypoints_enabled.disk_cache := FALSE;
    syv$perf_keypoints_enabled.command_keypoints := FALSE;

    osp$set_locked_variable (osv$keypoint_control.lock, 1, 0, actual, result);

  PROCEND osp$release_keypoint_r1;
?? EJECT ??

  PROCEDURE [XDCL, #GATE] osp$fetch_keypoint_lock
    (VAR i: integer);

    osp$fetch_locked_variable (osv$keypoint_control.lock, i);

  PROCEND osp$fetch_keypoint_lock;

  PROCEDURE [XDCL, #GATE] osp$collection_file_info_r1
    (   pva_array: array [1 .. osc$max_number_of_processors] of ^cell;
        file_id_array: array [1 .. osc$max_number_of_processors] of amt$file_identifier;
        num_of_files: 0 .. 0ff(16));

    VAR
      i: integer;

    osv$keypoint_control.number_of_keypoint_files := num_of_files;
    FOR i := 1 TO num_of_files DO
      osv$keypoint_control.keypoint_pva_array [i] := pva_array [i];
      osv$keypoint_control.keypoint_file_array [i] := file_id_array [i];
    FOREND;
  PROCEND osp$collection_file_info_r1;
?? EJECT ??

  PROCEDURE [XDCL, #GATE] osp$processor_selections_r1;

    VAR
      ijle_p: ^jmt$initiated_job_list_entry,
      processor_selections: ost$processor_id_set,
      xcb_p: ^ost$execution_control_block;

    pmp$find_executing_task_xcb (xcb_p);
    jmp$get_ijle_p (tmv$ptl_p^ [xcb_p^.global_task_id.index].ijl_ordinal, ijle_p);
    IF ijle_p^.job_scheduler_data.job_class = jmc$maintenance_job_class THEN
      processor_selections := mtv$scb.cpus.logically_on;
    ELSE
      processor_selections := mtv$scb.cpus.available_for_use;
    IFEND;
    osv$keypoint_control.processor_selections := xcb_p^.processor_selections;
    IF NOT (xcb_p^.processor_selections = processor_selections) THEN
      osv$keypoint_control.processor_select_flag := TRUE;
    IFEND;

  PROCEND osp$processor_selections_r1;
?? TITLE := 'OSP$RESET_PROCESSOR_R1', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$reset_processor_r1;

    VAR
      xcb: ^ost$execution_control_block;

    pmp$find_executing_task_xcb (xcb);
    xcb^.processor_selections := osv$keypoint_control.processor_selections;

  PROCEND osp$reset_processor_r1;
MODEND osm$keypoint_support_r1
