?? NEWTITLE := 'NOS/VE Network Access: Channel Connection Procedures Ring 1' ??
MODULE nlm$channel_connection_ring1;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains miscellaneous procedures needed by the Channel Connection Entity.
{   These procedures execute in ring 1 and are callable from ring 3.

?? NEWTITLE := 'Global Declarations Referenced by This Module' ??
?? PUSH (LISTEXT := ON) ??
*copyc nac$null_connection_id
*copyc nat$received_message_list
*copyc nlt$bm_message_descriptor
*copyc nlt$cl_connection
*copyc nlt$connection_queue
*copyc nlt$receiving_connections
*copyc osd$virtual_address
*copyc ost$signature_lock_status
*copyc ost$status
?? POP ??
*copyc pmp$ready_task
?? TITLE := 'Global Variables Referenced by This Module', EJECT ??
*copyc nav$si_received_message_list
*copyc nav$network_wired_heap
*copyc nav$system_input_taskid
*copyc nlv$receiving_connections
?? TITLE := '[XDCL, #GATE] nlp$cc_get_received_messages', EJECT ??
*copy nlh$cc_get_received_messages

  PROCEDURE [XDCL, #GATE] nlp$cc_get_received_messages
    (    cl_connection: {input, output} ^nlt$cl_connection;
     VAR received_messages: ^nlt$bm_message_descriptor);

    VAR
      actual_input_queue: nat$received_message_list,
      cl_connection_r1: ^nlt$cl_connection,
      initial_input_queue: nat$received_message_list,
      new_input_queue: nat$received_message_list,
      result: osc$cs_successful .. osc$cs_variable_locked;

    received_messages := NIL;
    new_input_queue.next_received_message := NIL;
    new_input_queue.fill := 0;
    initial_input_queue := new_input_queue;
    cl_connection_r1 := #ADDRESS (1, #SEGMENT (cl_connection), #OFFSET (cl_connection));

    REPEAT
      #COMPARE_SWAP (cl_connection_r1^.input_queue, initial_input_queue, new_input_queue, actual_input_queue,
            result);
      IF result = osc$cs_failed THEN
        initial_input_queue.next_received_message := actual_input_queue.next_received_message;
        received_messages := actual_input_queue.next_received_message;
      IFEND;
    UNTIL result = osc$cs_successful;

  PROCEND nlp$cc_get_received_messages;
?? TITLE := '[XDCL, #GATE] nlp$cc_requeue_msgs_on_conn', EJECT ??
*copy nlh$cc_requeue_msgs_on_conn

  PROCEDURE [XDCL, #GATE] nlp$cc_requeue_msgs_on_conn
    (    cl_connection: ^nlt$cl_connection;
         received_messages: ^nlt$bm_message_descriptor);

    VAR
      actual_input_queue: nat$received_message_list,
      cl_connection_r1: ^nlt$cl_connection,
      initial_input_queue: nat$received_message_list,
      new_input_queue: nat$received_message_list,
      queued_message: ^nlt$bm_message_descriptor,
      result: osc$cs_successful .. osc$cs_variable_locked;

    initial_input_queue.next_received_message := NIL;
    initial_input_queue.fill := 0;
    new_input_queue.next_received_message := received_messages;
    new_input_queue.fill := 0;
    cl_connection_r1 := #ADDRESS (1, #SEGMENT (cl_connection), #OFFSET (cl_connection));

  /queue_message/
    REPEAT
      #COMPARE_SWAP (cl_connection_r1^.input_queue, initial_input_queue, new_input_queue, actual_input_queue,
            result);
      IF result = osc$cs_failed THEN
        initial_input_queue := actual_input_queue;
        IF actual_input_queue.next_received_message <> NIL THEN

{ The input queue is not empty.

          queued_message := actual_input_queue.next_received_message;

{ Find the last message in the queue.

          WHILE queued_message^.received_message.next_received_message <> NIL DO
            queued_message := queued_message^.received_message.next_received_message;
          WHILEND;

{ Link the received messages at the end of the queue.

          queued_message^.received_message.next_received_message := received_messages;
          EXIT /queue_message/; {----->
        IFEND;
      IFEND;
    UNTIL result = osc$cs_successful;

  PROCEND nlp$cc_requeue_msgs_on_conn;
?? TITLE := '[XDCL, #GATE] nlp$connection_queued', EJECT ??
*copy nlh$connection_queued

  FUNCTION [XDCL, #GATE] nlp$connection_queued
    (    receiving_connection: ^nlt$cl_connection): boolean;

    VAR
      actual_connection_queue: nlt$connection_queue,
      cl_connection_r1: ^nlt$cl_connection,
      initial_connection_queue: nlt$connection_queue,
      new_connection_queue: nlt$connection_queue,
      cs_status: osc$cs_successful .. osc$cs_variable_locked;

    cl_connection_r1 := #ADDRESS (1, #SEGMENT (receiving_connection), #OFFSET (receiving_connection));
    initial_connection_queue.in_queue := FALSE;
    initial_connection_queue.fill := 0;
    initial_connection_queue.next_connection := NIL;
    new_connection_queue := initial_connection_queue;
    REPEAT
      #COMPARE_SWAP (cl_connection_r1^.connection_queue, initial_connection_queue, new_connection_queue,
            actual_connection_queue, cs_status);
    UNTIL cs_status <> osc$cs_variable_locked;

    nlp$connection_queued := actual_connection_queue.in_queue;

  FUNCEND nlp$connection_queued;
?? TITLE := '[XDCL, #GATE] nlp$delink_receiving_connection', EJECT ??
*copy nlh$delink_receiving_connection

  PROCEDURE [XDCL, #GATE] nlp$delink_receiving_connection
    (    receiving_connection: ^nlt$cl_connection;
     VAR next_receiving_connection: nlt$cl_connection_id);

    VAR
      actual_connection_queue: nlt$connection_queue,
      cl_connection_r1: ^nlt$cl_connection,
      initial_connection_queue: nlt$connection_queue,
      new_connection_queue: nlt$connection_queue,
      cs_status: osc$cs_successful .. osc$cs_variable_locked;

    cl_connection_r1 := #ADDRESS (1, #SEGMENT (receiving_connection), #OFFSET (receiving_connection));
    initial_connection_queue.in_queue := TRUE;
    initial_connection_queue.fill := 0;
    initial_connection_queue.next_connection := NIL;
    new_connection_queue := initial_connection_queue;
    REPEAT
      #COMPARE_SWAP (cl_connection_r1^.connection_queue, initial_connection_queue, new_connection_queue,
            actual_connection_queue, cs_status);
      IF cs_status = osc$cs_failed THEN
        initial_connection_queue.next_connection := actual_connection_queue.next_connection;
      IFEND;
    UNTIL cs_status = osc$cs_successful;
    IF actual_connection_queue.next_connection <> NIL THEN
      next_receiving_connection := actual_connection_queue.next_connection^.identifier;
    ELSE
      next_receiving_connection := nac$null_connection_id;
    IFEND;

  PROCEND nlp$delink_receiving_connection;
?? TITLE := '[XDCL, #GATE] nlp$dequeue_receiving_conection', EJECT ??
*copy nlh$dequeue_receiving_conection

  PROCEDURE [XDCL, #GATE] nlp$dequeue_receiving_conection
    (    receiving_connection: ^nlt$cl_connection;
     VAR next_receiving_connection: nlt$cl_connection_id);

    VAR
      actual_connection_queue: nlt$connection_queue,
      cl_connection_r1: ^nlt$cl_connection,
      initial_connection_queue: nlt$connection_queue,
      new_connection_queue: nlt$connection_queue,
      cs_status: osc$cs_successful .. osc$cs_variable_locked;

    cl_connection_r1 := #ADDRESS (1, #SEGMENT (receiving_connection), #OFFSET (receiving_connection));
    initial_connection_queue.in_queue := TRUE;
    initial_connection_queue.fill := 0;
    initial_connection_queue.next_connection := NIL;
    new_connection_queue.in_queue := FALSE;
    new_connection_queue.fill := 0;
    new_connection_queue.next_connection := NIL;
    REPEAT
      #COMPARE_SWAP (cl_connection_r1^.connection_queue, initial_connection_queue, new_connection_queue,
            actual_connection_queue, cs_status);
      IF cs_status = osc$cs_failed THEN
        initial_connection_queue.next_connection := actual_connection_queue.next_connection;
      IFEND;
    UNTIL cs_status = osc$cs_successful;
    IF actual_connection_queue.next_connection <> NIL THEN
      next_receiving_connection := actual_connection_queue.next_connection^.identifier;
    ELSE
      next_receiving_connection := nac$null_connection_id;
    IFEND;

  PROCEND nlp$dequeue_receiving_conection;
?? TITLE := '[XDCL, #GATE] nlp$get_receiving_connections', EJECT ??
*copy nlh$get_receiving_connections

  PROCEDURE [XDCL, #GATE] nlp$get_receiving_connections
    (VAR receiving_connections: ^nlt$cl_connection);

    VAR
      actual: nlt$receiving_connections,
      initial: nlt$receiving_connections,
      new: nlt$receiving_connections,
      result: osc$cs_successful .. osc$cs_variable_locked;

    new.fill := 0;
    new.next_connection := NIL;
    initial := new;
    REPEAT
      #COMPARE_SWAP (nlv$receiving_connections, initial, new, actual, result);
      IF result = osc$cs_failed THEN
        initial.next_connection := actual.next_connection;
      IFEND;
    UNTIL result = osc$cs_successful;

    receiving_connections := actual.next_connection;

  PROCEND nlp$get_receiving_connections;
?? TITLE := '[XDCL, #GATE] nlp$requeue_msgs_for_input_task', EJECT ??
*copy nlh$requeue_msgs_for_input_task

  PROCEDURE [XDCL, #GATE] nlp$requeue_msgs_for_input_task
    (    received_messages: ^nlt$bm_message_descriptor);

    VAR
      actual: nat$received_message_list,
      initial: nat$received_message_list,
      last_received_message: ^nlt$bm_message_descriptor,
      new: nat$received_message_list,
      result: osc$cs_successful .. osc$cs_variable_locked,
      status: ost$status;

{ Find the last message in the list.

    last_received_message := received_messages;
    WHILE last_received_message^.received_message.next_received_message <> NIL DO
      last_received_message := last_received_message^.received_message.next_received_message;
    WHILEND;

    new.next_received_message := received_messages;
    new.fill := 0;
    initial.fill := 0;
    initial.next_received_message := NIL;

    REPEAT
      #COMPARE_SWAP (nav$si_received_message_list, initial, new, actual, result);
      IF result = osc$cs_failed THEN
        initial := actual;
        last_received_message^.received_message.next_received_message := initial.next_received_message;
      IFEND;
    UNTIL result = osc$cs_successful;
    IF initial.next_received_message = NIL THEN
      pmp$ready_task (nav$system_input_taskid, {ignore} status);
    IFEND;
  PROCEND nlp$requeue_msgs_for_input_task;
MODEND nlm$channel_connection_ring1;
