*copyc osd$default_pragmats
MODULE iim$st_flush;
?? NEWTITLE := 'MODULE iim$st_flush' ??

?? PUSH (LISTEXT := ON) ??
*copyc ifc$interrupt_timesharing_io
*copyc ife$error_codes
*copyc iik$keypoints
*copyc iit$connection_description
*copyc iit$interactive_signal_type
*copyc iiv$connection_desc_ptr
*copyc iiv$interactive_terminated
*copyc iiv$int_task_open_file_count
*copyc nat$data_fragments
*copyc ost$status
*copyc pmp$log
?? POP ??

*copyc iip$clear_lock
*copyc iip$report_status_error
*copyc iip$search_connection_desc
*copyc iip$set_lock
*copyc iip$st_put
*copyc iip$st_send_output_message
*copyc jmp$handle_ts_io_req_failure
*copyc jmp$ts_io_request_valid
*copyc osp$clear_job_signature_lock
*copyc osp$establish_condition_handler
*copyc osp$decrement_locked_variable
*copyc osp$disestablish_cond_handler
*copyc osp$increment_locked_variable
*copyc osp$set_status_abnormal
*copyc osp$system_error
*copyc osp$test_sig_lock
*copyc pmp$continue_to_cause
*copyc pmp$log

*copyc iiv$io_requests_in_job
*copyc iiv$io_requests_in_task

?? NEWTITLE := 'PROCEDURE iip$st_flush', EJECT ??

  PROCEDURE [XDCL, #GATE] iip$st_flush (file_id: amt$file_identifier;
        open_file_desc_pointer: ^iit$st_open_file_description;
    VAR status: ost$status);

    VAR
      byte_address: amt$file_byte_address,
      connection_desc_ptr: ^iit$connection_description,
      decrement_error: boolean,
      exit_in_progress: boolean,
      io_requests_in_job: integer,
      local_status: ost$status,
      ls: ost$signature_lock_status;

?? NEWTITLE := 'PROCEDURE handle_break', EJECT ??

    PROCEDURE handle_break (cond: pmt$condition;
          cd: ^pmt$condition_information;
          sa: ^ost$stack_frame_save_area;
      VAR ch_status: ost$status);

      VAR
      iiv$condition_handler_trace: [XREF]  boolean,
      local_status: ost$status;


      IF cond.selector = pmc$block_exit_processing THEN
        IF iiv$condition_handler_trace THEN
          pmp$log ('ST_FLUSH block exit condition',local_status);
        IFEND;
        iiv$io_requests_in_task:= iiv$io_requests_in_task - 1;
        osp$decrement_locked_variable (iiv$io_requests_in_job, iiv$io_requests_in_job, io_requests_in_job,
              decrement_error);

      ELSEIF (cond.selector = pmc$user_defined_condition) AND
          (cond.user_condition_name = ifc$interrupt_timesharing_io) THEN

        IF iiv$condition_handler_trace THEN
          pmp$log ('ST_FLUSH interrupt condition',local_status);
        IFEND;
        IF exit_in_progress THEN
          pmp$log ('Multiple ifc$interrupt_timesharing_io conditions received.', local_status);
        IFEND;

        pmp$continue_to_cause (pmc$execute_standard_procedure, ch_status);
        exit_in_progress := TRUE;
        EXIT iip$st_flush;
      ELSE
        IF iiv$condition_handler_trace THEN
          pmp$log ('ST_FLUSH neither block exit nor interrupt',local_status);
        IFEND;
        pmp$continue_to_cause (pmc$execute_standard_procedure, ch_status);
        IF exit_in_progress THEN
          EXIT iip$st_flush;
        IFEND;
      IFEND;

    PROCEND handle_break;
?? OLDTITLE ??
?? EJECT ??

    osp$test_sig_lock (iiv$downline_queue_lock, ls);
    IF ls = osc$sls_locked_by_current_task THEN

{     some sort of unintended recursion has occured. ignore flush.

      status.normal := TRUE;
      RETURN;
    IFEND;

    exit_in_progress := FALSE;
    #spoil (exit_in_progress);
    osp$establish_condition_handler (^handle_break, TRUE);

    IF iiv$put_info.last_term_option <> amc$terminate THEN

    { Add the contents of the buffer used for put-partial data to the downline queue.

      iip$st_put (file_id, open_file_desc_pointer, amc$put_partial_req,
            NIL, 0, NIL, amc$terminate, status);
      IF NOT status.normal THEN
        pmp$log (' IIP$ST_PUT returned bad status in IIP$ST_FLUSH', status);
      IFEND;
    IFEND;

  /st_flush/
    BEGIN
      osp$increment_locked_variable (iiv$io_requests_in_job, iiv$io_requests_in_job, io_requests_in_job);
      iiv$io_requests_in_task := iiv$io_requests_in_task + 1;
      WHILE NOT jmp$ts_io_request_valid () DO
        iiv$io_requests_in_task := iiv$io_requests_in_task - 1;
        osp$decrement_locked_variable (iiv$io_requests_in_job, iiv$io_requests_in_job, io_requests_in_job,
              decrement_error);
        osp$disestablish_cond_handler;

        jmp$handle_ts_io_req_failure (status);
        IF status.normal THEN
          osp$establish_condition_handler (^handle_break, TRUE);
          osp$increment_locked_variable (iiv$io_requests_in_job, iiv$io_requests_in_job, io_requests_in_job);
          iiv$io_requests_in_task := iiv$io_requests_in_task + 1;
        ELSE
          RETURN;
        IFEND;
      WHILEND;

      iip$search_connection_desc (open_file_desc_pointer^.session_layer_file_name, connection_desc_ptr);
      IF connection_desc_ptr = NIL THEN
        IF exit_in_progress THEN
          osp$system_error ('FLUSH non-local exit did not complete.', NIL);
        IFEND;

        iiv$io_requests_in_task := iiv$io_requests_in_task - 1;
        osp$decrement_locked_variable (iiv$io_requests_in_job, iiv$io_requests_in_job,
              io_requests_in_job, decrement_error);
        osp$disestablish_cond_handler;
        RETURN;
      IFEND;

    /empty_the_downline_queue/
      WHILE TRUE DO
        iip$set_lock (iiv$downline_queue_lock, osc$wait, local_status);
        IF connection_desc_ptr^.downline_queue_count = 0 THEN
          iip$clear_lock (iiv$downline_queue_lock, local_status);
          EXIT /empty_the_downline_queue/;
        ELSE
          iip$clear_lock (iiv$downline_queue_lock, status);
          iip$st_send_output_message (connection_desc_ptr, open_file_desc_pointer^.vtp_file_id, status);
          IF NOT status.normal THEN
            IF exit_in_progress THEN
              osp$system_error ('FLUSH non-local exit did not complete.', NIL);
            IFEND;

            iiv$io_requests_in_task := iiv$io_requests_in_task - 1;
            osp$decrement_locked_variable (iiv$io_requests_in_job, iiv$io_requests_in_job,
                  io_requests_in_job, decrement_error);
            osp$disestablish_cond_handler;
            RETURN;
          IFEND;
        IFEND;
      WHILEND /empty_the_downline_queue/;

    END /st_flush/;

    #spoil (exit_in_progress);
    IF exit_in_progress THEN
      osp$system_error ('FLUSH non-local exit did not complete.', NIL);
    IFEND;

    iiv$io_requests_in_task := iiv$io_requests_in_task - 1;
    osp$decrement_locked_variable (iiv$io_requests_in_job, iiv$io_requests_in_job, io_requests_in_job,
          decrement_error);
    osp$disestablish_cond_handler;

    status.normal := TRUE;

  PROCEND iip$st_flush;

MODEND iim$st_flush;
