Trailing-Edge
-
PDP-10 Archives
-
BB-P363B-SM_1985
-
mcb/nml/nmlque.bli
There are 2 other files named nmlque.bli in the archive. Click here to see a list.
!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.09'
) =
begin
!
! COPYRIGHT (c) 1980, 1981, 1982
! DIGITAL EQUIPMENT CORPORATION
! Maynard, Massachusetts
!
! This software is furnished under a license and may be used
! and copied only in accordance with the terms of such license
! and 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. No title to
! and ownership of the software is hereby transferred.
!
! The information in this software is subject to change
! without notice and should not be construed as a commitment
! by DIGITAL EQUIPMENT CORPORATION.
!
! DIGITAL assumes no responsibility for the use or reliability
! of its software on equipment which is not supplied by
! DIGITAL.
!
!++
! 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.
!
! 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;
!
! 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:
!
! $true if request was found and canceled
! $false if request was not found on WAITING queue
!
! 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);
$true
end
else
$false
end
else
$false
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