Google
 

Trailing-Edge - PDP-10 Archives - BB-X117B-SB_1986 - 10,7/nml/nmlque.bli
There are 2 other files named nmlque.bli in the archive. Click here to see a list.
! PH4:<MCINTEE>NMLQUE.BLI.3,  2-Jun-83 10:47:55, Edit by MCINTEE
!
! Ident 10.
!  In routine LOCAL_REMOTE_CHECK, force RT$REMOTE when
!  debug flag PRIVATE_HOST_LINK is set.
!
!NET:<BRANDT.DEVELOPMENT>NMLQUE.BLI.1 19-Jan-82 12:35:21, Edit by BRANDT
!
! Ident 09.
!   In routine LOCAL_REMOTE_CHECK change local variable
!   LOCAL_NODE_NUMBER to LOCAL_NODE_NUMB to prevent a conflict with
!   a macro named NML_LOCAL_NUMBER that is now a part of NMLLIB.
!   Of course we all know the correct solution would be to make the
!   macro name adhere to macro naming conventions, but this is easier
!   and we will never see this problem again, and ...
!
!NET:<BRANDT.DEVELOPMENT>NMLQUE.BLI.1 19-Jan-82 10:35:21, Edit by BRANDT
!
! Ident 08.
!   Add routine NML$REQUEST_TERMINATE to terminate an aborted request
!   having multiple response messages.
!
!NET:<BRANDT.DEVELOPMENT>NMLQUE.BLI.1 19-Nov-81 13:25:18, Edit by BRANDT
!
! Ident 07.
!   Fix NML$REQUEST_FINISH so it does not reference the request
!   block after calling the completion routine since the completion
!   routine releases the request block.
!
!NET:<DECNET20-V3P1.NML>NMLQUE.BLI.2 12-Aug-81 09:51:53, Edit by JENNESS
!
!    Ident 06.
!    Fix CANCEL routine (ABORT still doesn't work).  
!    Update coding conventions.
!    Increase request queue quotas for -36 bit versions.
!
!<DECNET20-V3P1.BASELEVEL-2.MCB>NMLQUE.BLI.2 10-Jun-81 11:03:40, Edit by SROBINSON
!
!    Make Local and Remote Queues Quota Scheduled
!
!<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLQUE.BLI.13  4-Jun-81 08:25:49, Edit by SROBINSON
!
!    Conditionalize routines not used in $MCB
!
!BL2SRC:<DECNET20-V3P1.BASELEVEL-2.MCB>NMLQUE.BLI.11 10-Feb-81 11:45:55, Edit by SROBINSON
!
!    Make Q_ENTRY_SIZE be Q_ENTRY_ALLOCATION
!
!NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLQUE.BLI.10  9-Feb-81 09:01:55, Edit by GUNN
!
!    Make test on NICE return code treated as signed byte.
!
!NET:<DECNET20-V3P1.NMU>NMLQUE.BLI.6  3-Feb-81 10:02:33, Edit by JENNESS
!
!    Set state of request to RB$ACTIVE when giving to processor (REQUEST_NEXT).
!    Make byte pointer to response message (instead of using address as ptr)
!	and properly load the response code.
%title 'NMLQUE -- NICE Request Queue Management Routines'
module NMLQUE (				! NICE Request queueing module
		ident = 'X01.10'
		) =
begin
!
!                       COPYRIGHT (C) 1981 BY
!    DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS  01754
!
! THIS SOFTWARE IS FURNISHED  UNDER A LICENSE FOR USE ONLY ON A SINGLE
! COMPUTER  SYSTEM AND  MAY BE  COPIED ONLY WITH  THE INCLUSION OF THE
! ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE, OR ANY OTHER COPIES  THEREOF
! MAY NOT BE PROVIDED OR  OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON
! EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE
! TERMS.  TITLE TO AND  OWNERSHIP OF THE  SOFTWARE  SHALL AT ALL TIMES
! REMAIN IN DEC.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
! AND SHOULD  NOT BE CONSTRUED  AS A COMMITMENT  BY DIGITAL  EQUIPMENT
! CORPORATION.
!
! DEC ASSUMES  NO  RESPONSIBILITY  FOR  THE USE OR  RELIABILITY OF ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
!

!++
! Facility: LSG DECnet Network Management
!
! Abstract: This module provides the routines that control the
!           master request queue in the user level NML system.
!
! Environment: TOPS10/TOPS20 user mode, MCB RSX task level
!
! Author: Steven M. Jenness, Creation date: 23-Sep-80
!
!--

!
! Include files
!

library 'NMLLIB';				! All needed definitions

!
! Global routines
!

forward routine
    NML$REQUEST_MANAGER;			! Define global entry points

!
! Literal values
!

literal
    MAX_REQUESTS_QUEUED =
        %if $MCB
        %then 3
        %else 100
        %fi ;

!
! Local routines
!

forward routine
%if not $MCB %then
    REQUEST_SEARCH,				! Abort/cancel scanning routine
    SHOW_SCAN,					! Queue scan routine for SHOW
%fi
    LOCAL_REMOTE_CHECK : novalue;		! Determination of local/remote

!
! Own storage
!

own
    REQUEST_QUEUE : Q_HEADER,			! Queue of all requests
    LOCAL_QUEUE : QQ_HEADER,			! Local waiting requests
    REMOTE_QUEUE : QQ_HEADER,			! Remote waiting requests
    REQUEST_NUMBER;				! Last request number allocated

!
! External references
!

external routine
    NMU$QUEUE_MANAGER,			! Generalized queue management routines
    NMU$SCHED_MANAGER,			! Scheduler
    NMU$MEMORY_MANAGER,			! Memory management routines
    NMU$NETWORK_UTILITIES;		! Network interface

!
! Definitions needed for debugging
!

external
    %debug_data_base;

    %module_name ('NMLQUE');
%global_routine ('NML$REQUEST_INITIALIZE') : novalue =

!++
! Functional description:
!
!       This routine initializes the request manager.  All queues
!       of requests are cleared.
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--

    begin
    NMU$QUEUE_RESET (REQUEST_QUEUE);
    NMU$QQUEUE_RESET (LOCAL_QUEUE, MAX_REQUESTS_QUEUED);
    NMU$QQUEUE_RESET (REMOTE_QUEUE, MAX_REQUESTS_QUEUED);
    end;					! End of NML$REQUEST_INITIALIZE
%global_routine ('NML$REQUEST_ENTER', ENTRY : ref REQUEST_BLOCK) =

!++
! Functional description:
!
!       This routine enters a request onto the master request queue.
!
! Formal parameters:
!
!       .ENTRY   Address of the request block to be entered
!
! Routine value:
!
!       The request number of entered request
!
! Side effects:
!
!       When the entry is made onto the request queue a processing
!       task may be scheduled.
!
!--

    begin

!
! Assign the next request number, clear the processing task id
! and set the request state to WAITING.
!
    ENTRY [RB_NUMBER] = (REQUEST_NUMBER = .REQUEST_NUMBER + 1);
    ENTRY [RB_TASK] = 0;
    ENTRY [RB_STATE] = RB$WAITING;
!
! Figure out whether the request is local or remote.
!
    LOCAL_REMOTE_CHECK (.ENTRY);
!
! Insert entry into master queue of entries and onto the
! appropriate queue of waiting requests.
!
    NMU$QUEUE_INSERT (REQUEST_QUEUE, ENTRY [RB_REQUEST_QUEUE]);

    if .ENTRY [RB_TYPE] eql RT$LOCAL
    then
	NMU$QQUEUE_INSERT (LOCAL_QUEUE, ENTRY [RB_PROCESS_QUEUE])
    else
	NMU$QQUEUE_INSERT (REMOTE_QUEUE, ENTRY [RB_PROCESS_QUEUE]);

!
! Return the request number.
!
    .ENTRY [RB_NUMBER]
    end;					! End of NML$REQUEST_ENTER
%routine ('LOCAL_REMOTE_CHECK', REQUEST : ref REQUEST_BLOCK) : novalue =

!++
! Functional description:
!
!	This routine determines  whether a  request is  for the  local
!	node or is to be  sent out node for  a remote NML to  process.
!	This determination  is made  by comparing  the local  node  id
!	against the EXECUTOR node id for the request.
!	If the debug flag PRIVATE_HOST_LINK is set, force all requests 
!	to be remote.
!
! Formal parameters:
!
!	.REQUEST    Address of request block
!
! Routine value: none
! Side effects:
!
!	REQUEST [RB_TYPE] is set to either RT$LOCAL or RT$REMOTE.
!
!--

    begin

    local
	REQUEST_NODE_NUMBER,
	LOCAL_NODE_NUMB,
	REQUEST_ID_POINTER,
	LOCAL_ID_POINTER;

!
!   If PRIVATE_HOST_LINK is set, force remote.
!

    if PRIVATE_HOST_LINK 
    then begin
	 REQUEST [RB_TYPE] = RT$REMOTE;
	 return;
	 end;

!
! Default the request type to local.
!
    REQUEST [RB_TYPE] = RT$LOCAL;
!
! Check for an EXECUTOR node id specified, if not
! then just return (local request).
!
    if .REQUEST [RB_EXECUTOR] eql 0 then return;
!
! Make pointers to the local node id and request id.
!
    LOCAL_ID_POINTER = NMU$NETWORK_LOCAL ();
    REQUEST_ID_POINTER = ch$ptr (.REQUEST [RB_EXECUTOR],,8);
    LOCAL_NODE_NUMB = GETW (LOCAL_ID_POINTER);
!
! Check request's node number.  If non zero then compare
! against the local node number.  If it is zero then compare
! the node names.
!
    if (REQUEST_NODE_NUMBER = GETW (REQUEST_ID_POINTER)) neq 0
    then
	if .REQUEST_NODE_NUMBER eql .LOCAL_NODE_NUMB
	then return
	else REQUEST [RB_TYPE] = RT$REMOTE
    else
	if ch$eql (GETB (REQUEST_ID_POINTER), .REQUEST_ID_POINTER,
		   GETB (LOCAL_ID_POINTER), .LOCAL_ID_POINTER)
	then return
	else REQUEST [RB_TYPE] = RT$REMOTE;

    end;					! End of LOCAL_REMOTE_CHECK
%global_routine ('NML$REQUEST_NEXT', REQUEST_TYPE) =

!++
! Functional description:
!
!       This routine is called by the request processing tasks.  It
!       retrieves the next request to be processed of the type specified
!       (local/remote) and returns the address of the request block to
!       the caller for processing.
!
! Formal parameters:
!
!       .REQUEST_TYPE  RT$LOCAL   Local request
!                      RT$REMOTE  Remote request
!
! Routine value:
!
!      Request block address for processing
!
! Side effects:
!
!      The calling task is blocked until a request of the type
!      desired is queued for processing.
!
!--

    begin

    local
         REQUEST : ref REQUEST_BLOCK;

!
! Get request entry from appropriate queue.
!

    if .REQUEST_TYPE eql RT$LOCAL
    then
	REQUEST = NMU$QQUEUE_REMOVE (LOCAL_QUEUE)
    else
	REQUEST = NMU$QQUEUE_REMOVE (REMOTE_QUEUE);

!
! Adjust entry address to account for master queue
! linkage info preceding processing queue info.
!
    REQUEST = .REQUEST - Q_ENTRY_ALLOCATION;
!
! Set the task id of the processing task for the request.
!
    REQUEST [RB_TASK] = NMU$SCHED_CURRENT ();
!
! Set the request state to active
!
    REQUEST [RB_STATE] = RB$ACTIVE;
!
! Return the request address
!
    .REQUEST
    end;					! End of NML$REQUEST_NEXT
%global_routine ('NML$REQUEST_FINISH', REQUEST : ref REQUEST_BLOCK) =

!++
! Functional description:
!
!       This routine is called by a task that has finished  processing
!       a request (with either a partial or full response).  The  NICE
!       return message pointer has been filled in.  If the state of the
!	request is "active" ([RB_STATE] eql RB$ACTIVE) and the return code
!       is 2 (multiple response) then the request state is set to 
!	"more responses coming" ([RB_STATE] = RB$MORE) and the request
!	block is left on the request queue. If the state is "active" and
!	the return code is 1 , the request is "done" and is removed from
!	the request queue. If the state is "more responses coming" 
!	([RB_STATE] eql RB$MORE) and the return code is not -128 then the
!	request is left on the queue.
!
! Formal parameters:
!
!       .REQUEST    Address of request block
!
! Routine value:
!
!	$true	  if state is RB$DONE at exit
!	$false	  Otherwise
!
! Side effects:
!
!       A call to the completion routine specific in the request
!       block is made.
!
!--

    begin

    $field SIGNED_BYTE =
        set
        VALUE = [0,0,8,1]               ! Signed eight bit byte
        tes;

    local
	RETURN_VALUE,
	RESP_MSG,
	RESP_CODE: block[1] field(SIGNED_BYTE) ; ! 8 bit signed return code 

!
! Get response to request (1st byte in message)
!
    RESP_MSG = ch$ptr (.REQUEST [RB_RESPONSE],, 8);
    RESP_CODE = ch$rchar_a (RESP_MSG);

!
! If state is "active" then this is the first response we've
! seen. Set state to "more" if NICE return code is 2,
! otherwise state to "done" and remove the request from
! the queue.
!
! If the state is "more" and the return code is -128 then set
! state to "done" and remove request from the queue.
!

    if .REQUEST [RB_STATE] eql RB$ACTIVE
    then
        begin
	if (.RESP_CODE[VALUE] eql 2)
	then
	    REQUEST [RB_STATE] = RB$MORE
	else
	    begin
	    REQUEST [RB_STATE] = RB$DONE;
	    NMU$QUEUE_EXTRACT (REQUEST_QUEUE, REQUEST [RB_REQUEST_QUEUE]);
	    end;
        end
    else if .REQUEST [RB_STATE] eql RB$MORE
	 then if (.RESP_CODE[VALUE] eql -128)
	      then
		  begin
		  REQUEST [RB_STATE] = RB$DONE;
		  NMU$QUEUE_EXTRACT (REQUEST_QUEUE,
			             REQUEST [RB_REQUEST_QUEUE]);
		  end;

    RETURN_VALUE = (if .REQUEST [RB_STATE] eql RB$DONE
		    then $true
		    else $false) ;

!
! Call completion routine with request response.
! If request is done, completion routine releases request block.
!
    begin

    bind routine
	COMPLETION_ROUTINE = .REQUEST [RB_COMPLETION];

    if COMPLETION_ROUTINE neq 0 then COMPLETION_ROUTINE (.REQUEST);

    end;
!
! Return indication to processing routine whether the
! request is done yet.
!

    .RETURN_VALUE

    end;					! End of NML$REQUEST_FINISH
!
!Routines that are not used in $MCB follow this conditional:
!
%if not $MCB
%then

%global_routine ('NML$REQUEST_ABORT', R_NUMBER) =

!++
! Functional description:
!
!       This routine aborts the request with the specified
!       request number.  The request is removed (if it exists)
!       from either the ACTIVE or WAITING request queue.
!
! Formal parameters:
!
!       .R_NUMBER    Request number to abort
!
! Routine value:
!
!       $true    request was found and aborted
!       $false   request was not found
!
! Side effects:
!
!       The completion routine for the request is called with
!       a failure NICE return message.
!
!--

    begin

    local
         REQUEST : ref REQUEST_BLOCK;

    if (REQUEST = NMU$QUEUE_SCAN (REQUEST_QUEUE, .R_NUMBER, REQUEST_SEARCH)) neq 0
    then
	begin

	bind routine
	    COMPLETION_ROUTINE = .REQUEST [RB_COMPLETION];

	if .REQUEST [RB_STATE] eql RB$ACTIVE
        then NMU$SCHED_ABORT (.REQUEST [RB_TASK]);

        NMU$QUEUE_EXTRACT (REQUEST_QUEUE, REQUEST [RB_REQUEST_QUEUE]);

        if .REQUEST [RB_STATE] eql RB$WAITING
        then
            if .REQUEST [RB_TYPE] eql RT$LOCAL
            then
                NMU$QQUEUE_EXTRACT (LOCAL_QUEUE, REQUEST [RB_PROCESS_QUEUE])
            else
                NMU$QQUEUE_EXTRACT (REMOTE_QUEUE, REQUEST [RB_PROCESS_QUEUE]);

	REQUEST [RB_STATE] = RB$CANCELLED;

	if COMPLETION_ROUTINE neq 0
        then COMPLETION_ROUTINE (.REQUEST);

	$true
	end
    else
	$false

    end;					! End of NML$REQUEST_ABORT
%global_routine ('NML$REQUEST_TERMINATE', REQUEST : ref REQUEST_BLOCK) =

!++
! Functional description:
!
!       This routine is called to terminate a request that gets aborted
!       during the processing of a sequence of multiple responses.
!       A terminating response message (response code = -128) is created
!	and the REQUEST_FINISH routine is called.  Therefore, any output
!       that is queued for printing (including the error message causing
!       the abort) will be sent	to the operator and any memory resources
!       allocated for this request will get released.
!
! Formal parameters:
!
!       .REQUEST    Address of request block
!
! Routine value:
!
!	$true	  if state is RB$DONE at exit
!	$false	  Otherwise
!
! Side effects:
!
!       See NML$REQUEST_FINISH
!
!--

    begin

    $field SIGNED_BYTE =
        set
        VALUE = [0,0,8,1]               ! Signed eight bit byte
        tes;

    local
	RESP_MSG,
	RESP_CODE: block[1] field(SIGNED_BYTE) ; ! 8 bit signed return code 

!
! Set response to request (1st byte in message) to -128
!
    RESP_MSG = ch$ptr (.REQUEST [RB_RESPONSE],, 8);
    RESP_CODE[VALUE] = -128 ;
    ch$wchar (.RESP_CODE,.RESP_MSG);

    REQUEST [RB_RESPONSE_LENGTH] = 1 ;	! Length of response message

    NML$REQUEST_FINISH (.REQUEST)	! Finish off in graceful manner

    end;				! End of NML$REQUEST_TERMINATE
%global_routine ('NML$REQUEST_CANCEL', R_NUMBER) =

!++
! Functional description:
!
!       This routine cancels a request that is waiting to
!       start processing.  Only requests that are still on
!       the WAITING queue are affected.
!
! Formal parameters:
!
!       .R_NUMBER    Request number to cancel
!
! Routine value:
!
!	0	if request was found and cancelled
!	1	if request was not found
!	2	if request was active.  It therefore could not be cancelled
!
! Side effects:
!
!       The completion routine for the request is called with
!       a failure NICE return message.
!
!--

    begin

    local
         REQUEST : ref REQUEST_BLOCK;

    if (REQUEST = NMU$QUEUE_SCAN (REQUEST_QUEUE, .R_NUMBER, REQUEST_SEARCH)) neq 0
    then
	begin

	bind routine
	    COMPLETION_ROUTINE = .REQUEST [RB_COMPLETION];

	if .REQUEST [RB_STATE] eql RB$WAITING
	then
	    begin
            NMU$QUEUE_EXTRACT (REQUEST_QUEUE, REQUEST [RB_REQUEST_QUEUE]);

            if .REQUEST [RB_TYPE] eql RT$LOCAL
            then
                NMU$QQUEUE_EXTRACT (LOCAL_QUEUE, REQUEST [RB_PROCESS_QUEUE])
            else
                NMU$QQUEUE_EXTRACT (REMOTE_QUEUE, REQUEST [RB_PROCESS_QUEUE]);

	    REQUEST [RB_STATE] = RB$CANCELLED;

	    if COMPLETION_ROUTINE neq 0
            then COMPLETION_ROUTINE (.REQUEST);

	    0	! Request was found and cancelled
	    end
	else
	    2	! Request was active, and not cancelled

	end
    else
	1	! Request was not found

    end;					! End of NML$REQUEST_CANCEL
%routine ('REQUEST_SEARCH', REQUEST : ref REQUEST_BLOCK, NUMBER) =

!++
! Functional description:
!
!       This routine is used by both REQUEST_ABORT and REQUEST_CANCEL
!       to do the queue scanning for the desired request.
!
! Formal parameters:
!
!       .REQUEST     Address of request currently being checked
!       .NUMBER	     Request number being searched for
!
! Routine value:
!
!       Zero (0) if request numbers didn't match
!       Address of request block if the request numbers matched
!
! Side effects: none
!
!--

    begin

    if .REQUEST [RB_NUMBER] eql .NUMBER then .REQUEST else 0

    end;					! End of REQUEST_SEARCH
%global_routine ('NML$REQUEST_SHOW', NEXT_R, R_BLOCK_ADR) =

!++
! Functional description:
!
!       This routine is called repeatedly to step through all
!       the queues of requests (WAITING and ACTIVE).  Each
!       time this routine returns it passes back the address of
!       a block that contains the following information:
!
!          Request number
!          Request state
!          NICE message
!          EXECUTOR node name
!
!       Also the NEXT_R parameter is updated so that the next
!       call will step onto the next entry in the queues.
!
! Formal parameters:
!
!	.NEXT_R		Return next request that is greater or equal
!			in magnitude to this number
!
!	.R_BLOCK_ADR	Address of cell to receive request block
!			address
! Routine value:
!
!       $false    no request was found
!       $true     request block has been returned
!
! Side effects:
!
!       Note that the caller MUST release all the memory associated
!       with each request block after use.
!
!--

    begin

    bind
	R_BLOCK = .R_BLOCK_ADR : ref REQUEST_BLOCK;

    if (R_BLOCK = NMU$QUEUE_SCAN (REQUEST_QUEUE, ..NEXT_R, SHOW_SCAN)) neq 0
    then
	begin
	.NEXT_R = .R_BLOCK [RB_NUMBER];
	$true
	end
    else
	$false

    end;					! End of NML$REQUEST_SHOW
%routine ('SHOW_SCAN', ENTRY : ref REQUEST_BLOCK, DATA) =

!++
! Functional description:
!
!	If the ENTRY matches the request number specified, a
!	copy of the entry is made and the address of the entry
!	returned.
!
! Formal parameters:
!
!	.ENTRY    Address of current request queue entry
!	.DATA    Scanning data (request number to find)
!
! Routine value:
!
!	Zero (0) if no match
!	Address of copy block if match
!
! Side effects: none
!
!--

    begin

!
! Get then next highest numbered request
!

    if .ENTRY [RB_NUMBER] gtr .DATA
    then
	begin
	local
	    COPY : ref REQUEST_BLOCK;

	!
	! Make a copy of the request block
	!

	COPY = NMU$MEMORY_GET (REQUEST_BLOCK_ALLOCATION);
	COPY [RB_NUMBER] = .ENTRY [RB_NUMBER];
	COPY [RB_TYPE] = .ENTRY [RB_TYPE];
	COPY [RB_NICE] = .ENTRY [RB_NICE];
	COPY [RB_NICE_LENGTH] = .ENTRY [RB_NICE_LENGTH];
	COPY [RB_EXECUTOR] = .ENTRY [RB_EXECUTOR];
	COPY [RB_SOURCE] = .ENTRY [RB_SOURCE];
	COPY [RB_STATE] = .ENTRY [RB_STATE];
!
!****
!****  Allocate space and copy the NICE and EXECUTOR strings ???
!****  No, I don't think we can do that. The strings reside in the
!****  the additional data block.
!****
!

        !
        ! If there is a data block allocated copy it.
        !

	if .ENTRY [RB_DATA_ALLOCATION] neq 0
	then
	    begin
            COPY [RB_DATA] = NMU$MEMORY_GET (.ENTRY[RB_DATA_ALLOCATION]);
            COPY [RB_DATA_ALLOCATION] = .ENTRY [RB_DATA_ALLOCATION] ;
            ch$move (.ENTRY [RB_DATA_ALLOCATION],
	             ch$ptr(.ENTRY [RB_DATA],,(%bpval/%upval)),
                     .ENTRY [RB_DATA_ALLOCATION]) ;
	    end;

	.COPY
	end
    else
	0

    end;					! End of SHOW_SCAN
%fi !End of %if not $MCB

end						! End of module NMLQUE
eludom