?? RIGHT := 110 ??
*copyc OSD$DEFAULT_PRAGMATS
?? TITLE := 'NOS/VE : Tasking : Execute/Wait Interfaces' ??
?? NEWTITLE := '  Global declarations', EJECT ??
MODULE pmm$tasking_interfaces_ring_n;

{  PURPOSE:
{    This module contains tasking program interfaces which run in the
{    ring of their caller so that the requests are responsive to
{    interactive breaks.
?? EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc pmt$task_id
*copyc ost$status
*copyc oss$job_paged_literal
*copyc ost$caller_identifier
*copyc pmt$loader_seq_descriptor
?? POP ??

*copyc clp$convert_string_to_file
*copyc fsp$open_file
*copyc fsp$close_file
*copyc pmp$establish_condition_handler
*copyc pmp$disestablish_cond_handler
*copyc pmp$establish_segment_access
*copyc pmp$await_task
*copyc pmp$execute_task
*copyc pmp$execute_procedure_as_task
*copyc osp$set_status_abnormal


  VAR
    block_exit: [STATIC, READ, oss$job_paged_literal] pmt$condition := [pmc$condition_combination,
      $pmt$condition_combination [pmc$block_exit_processing]];

?? TITLE := '  [XDCL, #GATE] pmp$execute' ??
?? NEWTITLE := '    ensure_synchronization' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$execute (program_description: pmt$program_description;
        program_parameters: pmt$program_parameters;
        wait: ost$wait;
    VAR task_id: pmt$task_id;
    VAR task_status: pmt$task_status;
    VAR status: ost$status);

*copyc PMH$EXECUTE

?? EJECT ??

    VAR
      execute_task_id: pmt$task_id,
      ignore_status: ost$status;

    VAR
      mpe_description: [STATIC, READ, oss$job_paged_literal] pmt$loader_description := [FALSE, * , * ];

    PROCEDURE ensure_synchronization (condition: pmt$condition;
          condition_descriptor: ^pmt$condition_information;
          save_area: ^ost$stack_frame_save_area;
      VAR ensure_status: ost$status);

      IF status.normal THEN
        pmp$await_task_termination (execute_task_id, ignore_status);
        task_id := execute_task_id;
      IFEND;
      ensure_status.normal := TRUE;
    PROCEND ensure_synchronization;

?? OLDTITLE ??

    VAR
      caller: ost$caller_identifier,
      nonlocal_exit: pmt$established_handler;

    #caller_id (caller);
    task_status.complete := FALSE;
    status.normal := TRUE;
    task_id := LOWERVALUE (pmt$task_id);
    execute_task_id := LOWERVALUE (pmt$task_id);
    CASE wait OF
    = osc$wait =
      pmp$establish_condition_handler (block_exit, ^ensure_synchronization, ^nonlocal_exit, ignore_status);
      pmp$execute_task (caller.ring, program_description, mpe_description, program_parameters, osc$null_name,
            wait, FALSE, execute_task_id, task_status, status);
      IF status.normal THEN
        task_id := execute_task_id;
        pmp$await_task_termination (execute_task_id, status);
      IFEND;
      pmp$disestablish_cond_handler (block_exit, ignore_status);
    = osc$nowait =
      pmp$execute_task (caller.ring, program_description, mpe_description, program_parameters, osc$null_name,
            wait, FALSE, task_id, task_status, status);
    ELSE
      osp$set_status_abnormal ('PM', pme$invalid_wait_parameter, '', status);
    CASEND;

  PROCEND pmp$execute;

?? TITLE := '  [XDCL, #GATE] pmp$execute_procedure' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$execute_procedure (starting_procedure: pmt$user_program;
        parameters: pmt$program_parameters;
        critical_frame: ^ost$stack_frame_save_area;
    VAR task_id: pmt$task_id;
    VAR task_status: pmt$task_status;
    VAR status: ost$status);

*copyc PMH$EXECUTE_PROCEDURE


    VAR
      ignore_status: ost$status,
      caller: ost$caller_identifier;

    #caller_id (caller);
    task_status.complete := FALSE;
    status.normal := TRUE;
    task_id := LOWERVALUE (pmt$task_id);
    pmp$execute_procedure_as_task (caller.ring, starting_procedure, parameters, critical_frame,
            task_id, task_status, status);

  PROCEND pmp$execute_procedure;
?? TITLE := '  [XDCL, #GATE] pmp$execute_with_apd' ??
?? NEWTITLE := '    ensure_synchronization' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$execute_with_apd (program_description: pmt$program_description;
        mpe_description: pmt$loader_description;
        program_parameters: pmt$program_parameters;
        wait: ost$wait;
    VAR task_id: pmt$task_id;
    VAR task_status: pmt$task_status;
    VAR status: ost$status);
*copyc PMH$EXECUTE

    VAR
      execute_task_id: pmt$task_id,
      ignore_status: ost$status;

    PROCEDURE ensure_synchronization (condition: pmt$condition;
          condition_descriptor: ^pmt$condition_information;
          save_area: ^ost$stack_frame_save_area;
      VAR ensure_status: ost$status);

      IF status.normal THEN
        pmp$await_task_termination (execute_task_id, ignore_status);
        task_id := execute_task_id;
      IFEND;
      ensure_status.normal := TRUE;
    PROCEND ensure_synchronization;

?? OLDTITLE ??

    VAR
      caller: ost$caller_identifier,
      nonlocal_exit: pmt$established_handler;

    #caller_id (caller);
    task_status.complete := FALSE;
    status.normal := TRUE;
    task_id := LOWERVALUE (pmt$task_id);
    execute_task_id := LOWERVALUE (pmt$task_id);
    CASE wait OF
    = osc$wait =
      pmp$establish_condition_handler (block_exit, ^ensure_synchronization, ^nonlocal_exit, ignore_status);
      pmp$execute_task (caller.ring, program_description, mpe_description, program_parameters, osc$null_name,
            wait, FALSE, execute_task_id, task_status, status);
      IF status.normal THEN
        task_id := execute_task_id;
        pmp$await_task_termination (execute_task_id, status);
      IFEND;
      pmp$disestablish_cond_handler (block_exit, ignore_status);
    = osc$nowait =
      pmp$execute_task (caller.ring, program_description, mpe_description, program_parameters, osc$null_name,
            wait, FALSE, task_id, task_status, status);
    ELSE
      osp$set_status_abnormal ('PM', pme$invalid_wait_parameter, '', status);
    CASEND;
  PROCEND pmp$execute_with_apd;
?? TITLE := '  [XDCL, #GATE] pmp$await_task_termination', EJECT ??
?? NEWTITLE := '    ensure_wait_complete' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$await_task_termination (task_id: pmt$task_id;
    VAR status: ost$status);

*copyc PMH$AWAIT_TASK_TERMINATION

    VAR
      await_complete: boolean;



    PROCEDURE ensure_synchronization (condition: pmt$condition;
          condition_descriptor: ^pmt$condition_information;
          save_area: ^ost$stack_frame_save_area;
      VAR ensure_status: ost$status);

      IF NOT await_complete THEN
        pmp$await_task_termination (task_id, status);
      IFEND;
      ensure_status.normal := TRUE;
    PROCEND ensure_synchronization;

?? OLDTITLE ??

    VAR
      nonlocal_exit: pmt$established_handler,
      await_status: ost$status,
      ignore_status: ost$status;

    await_complete := FALSE;
    status.normal := TRUE;
    pmp$establish_condition_handler (block_exit, ^ensure_synchronization, ^nonlocal_exit, ignore_status);
    REPEAT
      pmp$await_task (task_id, await_complete, await_status);
    UNTIL await_complete OR NOT await_status.normal;
    pmp$disestablish_cond_handler (block_exit, ignore_status);
    status := await_status;

  PROCEND pmp$await_task_termination;
?? TITLE := '  [XDCL, #GATE] pmp$execute_with_less_privilege' ??
?? NEWTITLE := '    ensure_synchronization' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$execute_with_less_privilege (target_ring: ost$valid_ring;
        program_description: pmt$program_description;
        program_parameters: pmt$program_parameters;
        wait: ost$wait;
        cl_task:boolean;
    VAR task_id: pmt$task_id;
    VAR task_status: pmt$task_status;
    VAR status: ost$status);

*copyc PMH$EXECUTE_WITH_LESS_PRIVILEGE

    VAR
      execute_task_id: pmt$task_id,
      ignore_status: ost$status;

    PROCEDURE ensure_synchronization (condition: pmt$condition;
          condition_descriptor: ^pmt$condition_information;
          save_area: ^ost$stack_frame_save_area;
      VAR ensure_status: ost$status);

      IF status.normal THEN
        pmp$await_task_termination (execute_task_id, ignore_status);
        task_id := execute_task_id;
      IFEND;
      ensure_status.normal := TRUE;
    PROCEND ensure_synchronization;
?? OLDTITLE ??

    CONST
      no_command_file = osc$null_name;

    VAR
      caller: ost$caller_identifier,
      nonlocal_exit: pmt$established_handler;

    VAR
      mpe_description: [STATIC, READ, oss$job_paged_literal] pmt$loader_description := [FALSE, * , * ];

    #caller_id (caller);
    IF (target_ring >= caller.ring) THEN
      task_status.complete := FALSE;
      status.normal := TRUE;
      task_id := LOWERVALUE (pmt$task_id);
      execute_task_id := LOWERVALUE (pmt$task_id);
      CASE wait OF
      = osc$wait =
        pmp$establish_condition_handler (block_exit, ^ensure_synchronization, ^nonlocal_exit, ignore_status);
        pmp$execute_task (target_ring, program_description, mpe_description, program_parameters,
              no_command_file, wait, cl_task, execute_task_id, task_status, status);
        IF status.normal THEN
          task_id := execute_task_id;
          pmp$await_task_termination (execute_task_id, status);
        IFEND;
        pmp$disestablish_cond_handler (block_exit, ignore_status);
      = osc$nowait =
        pmp$execute_task (target_ring, program_description, mpe_description, program_parameters,
              no_command_file, wait, cl_task, task_id, task_status, status);
      ELSE
        osp$set_status_abnormal ('PM', pme$invalid_wait_parameter, '', status);
      CASEND;
    ELSE
      osp$set_status_abnormal ('PM', pme$target_ring_error, '', status);
    IFEND;

  PROCEND pmp$execute_with_less_privilege;
?? TITLE := '  [XDCL, #GATE] pmp$execute_with_command_file' ??
?? NEWTITLE := '    ensure_synchronization' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] pmp$execute_with_command_file (target_ring: ost$valid_ring;
        program_description: pmt$program_description;
        program_parameters: pmt$program_parameters;
        command_file: amt$local_file_name;
        wait: ost$wait;
        cl_task:boolean;
    VAR task_id: pmt$task_id;
    VAR task_status: pmt$task_status;
    VAR status: ost$status);

*copyc pmh$execute_with_command_file

    VAR
      execute_task_id: pmt$task_id,
      ignore_status: ost$status;

    PROCEDURE ensure_synchronization (condition: pmt$condition;
          condition_descriptor: ^pmt$condition_information;
          save_area: ^ost$stack_frame_save_area;
      VAR ensure_status: ost$status);

      IF status.normal THEN
        pmp$await_task_termination (execute_task_id, ignore_status);
        task_id := execute_task_id;
      IFEND;
      ensure_status.normal := TRUE;
    PROCEND ensure_synchronization;
?? OLDTITLE ??

    VAR
      caller: ost$caller_identifier,
      nonlocal_exit: pmt$established_handler;

    VAR
      mpe_description: [STATIC, READ, oss$job_paged_literal] pmt$loader_description := [FALSE, * , * ];

    #caller_id (caller);
    IF (target_ring >= caller.ring) THEN
      task_status.complete := FALSE;
      status.normal := TRUE;
      task_id := LOWERVALUE (pmt$task_id);
      execute_task_id := LOWERVALUE (pmt$task_id);
      CASE wait OF
      = osc$wait =
        pmp$establish_condition_handler (block_exit, ^ensure_synchronization, ^nonlocal_exit, ignore_status);
        pmp$execute_task (target_ring, program_description, mpe_description, program_parameters, command_file,
              wait, cl_task, execute_task_id, task_status, status);
        IF status.normal THEN
          task_id := execute_task_id;
          pmp$await_task_termination (execute_task_id, status);
        IFEND;
        pmp$disestablish_cond_handler (block_exit, ignore_status);
      = osc$nowait =
        pmp$execute_task (target_ring, program_description, mpe_description, program_parameters, command_file,
              wait, cl_task, task_id, task_status, status);
      ELSE
        osp$set_status_abnormal ('PM', pme$invalid_wait_parameter, '', status);
      CASEND;
    ELSE
      osp$set_status_abnormal ('PM', pme$target_ring_error, '', status);
    IFEND;
  PROCEND pmp$execute_with_command_file;
?? TITLE := '  [XDCL, #GATE] pmp$open_common_block_file', EJECT ??
  PROCEDURE [XDCL, #GATE] pmp$open_common_block_file (file: fst$file_reference;
        common_block: pmt$program_name;
    VAR segment_pointer: amt$segment_pointer;
    VAR status: ost$status);

*copyc pmh$open_common_block_file

    VAR
      file1: clt$file,
      file_identifier: amt$file_identifier,
      usage_attributes: array [1 .. 3] of fst$attachment_option,
      ignore_status: ost$status,
      caller_id: ost$caller_identifier;

    status.normal := TRUE;
    #caller_id (caller_id);

    clp$convert_string_to_file (file, file1, ignore_status);
    usage_attributes [1].selector := fsc$validation_ring;
    usage_attributes [1].validation_ring := caller_id.ring;
    usage_attributes [2].selector := fsc$access_and_share_modes;
    usage_attributes [2].access_modes.selector := fsc$permitted_access_modes;
    usage_attributes [2].share_modes.selector := fsc$required_share_modes;
    usage_attributes [3].selector := fsc$create_file;
    usage_attributes [3].create_file := TRUE;

    fsp$open_file (file1.local_file_name, amc$segment, ^usage_attributes, NIL, NIL, NIL, NIL,
               file_identifier, status);
    IF NOT status.normal THEN
      RETURN
    IFEND;

    pmp$establish_segment_access (file_identifier, common_block, segment_pointer, status);

    IF NOT status.normal THEN
      fsp$close_file (file_identifier, ignore_status);
    IFEND;

  PROCEND pmp$open_common_block_file;
MODEND pmm$tasking_interfaces_ring_n;
