?? RIGHT := 110 ??
MODULE mmm$read_write_io_ring_1;

{ This module contains the ring 1 procedures for processing
{ user read/write requests.

?? PUSH (LISTEXT := ON) ??
*copyc mmt$io_control_block
*copyc mmt$iocb_index
*copyc ost$status
*copyc ost$execution_control_block
*copyc osv$job_fixed_heap
?? POP ??

{External procedures used by this module.

*copyc osp$system_error
*copyc pmp$find_executing_task_xcb

?? TITLE := 'mmp$allocate_iocb_r1' ??
?? EJECT ??

{ The purpose of this procedure is to allocate and I/O control block for
{ a task doing asynchronous I/O.

  PROCEDURE [XDCL, #GATE] mmp$allocate_iocb_r1;

    VAR
      iocb_index: mmt$iocb_index,
      iocb_p: ^mmt$io_control_block,
      xcb_p: ^ost$execution_control_block;

    pmp$find_executing_task_xcb (xcb_p);

{ Allocate space for the iocb using a local variable, then move the
{ pointer to the xcb (the iocb_p field in the xcb is declared as ^cell).

    IF xcb_p^.iocb_p = NIL THEN
      ALLOCATE iocb_p in osv$job_fixed_heap^;
      IF iocb_p <> NIL THEN
        xcb_p^.iocb_p := iocb_p;

{ Initialize table.

        iocb_p^.latest_completion_time := 0;
        iocb_p^.maximum_iocb_index_in_use := 0;
        iocb_p^.wait_for_any_completion := FALSE;
        FOR iocb_index := LOWERBOUND (iocb_p^.iocb_table) TO UPPERBOUND (iocb_p^.iocb_table) DO
          iocb_p^.iocb_table [iocb_index].iostatus_p := NIL;
          iocb_p^.iocb_table [iocb_index].active_io_count := 0;
          iocb_p^.iocb_table [iocb_index].condition := 0;
          iocb_p^.iocb_table [iocb_index].used_for_asynchronous_io := FALSE;
          iocb_p^.iocb_table [iocb_index].io_already_active := FALSE;
        FOREND;
      ELSE
        osp$system_error ('job fixed is full', NIL);
      IFEND;
    IFEND;
  PROCEND mmp$allocate_iocb_r1;

?? TITLE := 'mmp$update_iocb_completions' ??
?? EJECT ??

  PROCEDURE [XDCL, #GATE] mmp$update_iocb_completions (completion_table:
    mmt$iocb_table_array);

    VAR
      iocb_index: mmt$iocb_index,
      iocb_ptr: ^mmt$io_control_block,
      new_maximum_iocb_index: mmt$iocb_index,
      xcb_p: ^ost$execution_control_block;

    pmp$find_executing_task_xcb (xcb_p);
    iocb_ptr := xcb_p^.iocb_p;
    new_maximum_iocb_index := 0;

    FOR iocb_index := LOWERBOUND (completion_table) TO iocb_ptr^.maximum_iocb_index_in_use DO
      IF (completion_table [iocb_index].active_io_count = 0) AND
            (completion_table[iocb_index].used_for_asynchronous_io) THEN
        iocb_ptr^.iocb_table [iocb_index].iostatus_p := NIL;
        iocb_ptr^.iocb_table [iocb_index].used_for_asynchronous_io := FALSE;
        iocb_ptr^.iocb_table [iocb_index].condition := 0;
        iocb_ptr^.iocb_table [iocb_index].io_already_active := FALSE;
      ELSEIF completion_table[iocb_index].used_for_asynchronous_io THEN
        new_maximum_iocb_index := iocb_index;
      IFEND;
    FOREND;
    iocb_ptr^.maximum_iocb_index_in_use := new_maximum_iocb_index;

  PROCEND mmp$update_iocb_completions;
MODEND mmm$read_write_io_ring1;
