Trailing-Edge
-
PDP-10 Archives
-
BB-JR93N-BB_1990
-
10,7/decmai/mx/mxnque.b36
There are 13 other files named mxnque.b36 in the archive. Click here to see a list.
%title 'NMUQUE -- General Queue Management'
module NMUQUE (
ident = 'X00.04'
) =
begin
! COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1985, 1989.
! ALL RIGHTS RESERVED.
!
! 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 THAT IS NOT SUPPLIED BY DIGITAL.
!++
! Facility: LSG DECnet Network Management
!
! Abstract:
!
! This set of routines provides a primitives for
! manipulating queues. The only requirement for
! using this set of routines is that the queue overhead
! information must be defined at the very beginning
! of any entry made to a queue.
!
! Environment: TOPS10 and TOPS20 user mode, MCB RSX task level
!
! Author: Steven M. Jenness, Creation date: 19 August 1980
!
!--
!
! INCLUDE FILES
!
library 'MXNLIB'; ! All needed definitions
!
! TABLE OF CONTENTS
!
forward routine
NMU$QUEUE_MANAGER; ! Global entry definitions
%global_routine ('NMU$QUEUE_RESET', QUEUE: ref Q_HEADER) : novalue =
!++
! Functional description:
!
! This routine resets a queue header to the null
! state.
!
! Formal parameters:
!
! .QUEUE Address of queue header
!
! Routine value: none
! Side effects:
!
! All pointers in the queue header point to
! the header itself (empty queue).
!
!--
begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
UNLOCK (QUEUE[Q_SEMAPHORE]);
end; ! End of NMU$QUEUE_RESET
%global_routine ('NMU$QUEUE_INSERT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =
!++
! Functional description:
!
! This routine inserts an entry to the end of
! a queue.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .ENTRY Address of entry data. The queueing information
! is stored starting at this address. A block
! of length Q_ENTRY_SIZE must be reserved.
!
! Routine value:
!
! $true if queue becomes non-empty with this insert
! $false if queue was previously non-empty
!
! Side effects:
!
! The forward pointer of the last item on the queue and
! the reverse pointer of the queue header are changed to
! point to the new entry.
!
!--
begin
local
LAST_ENTRY : ref Q_ENTRY,
RET_VAL;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Check for queue empty and set empty transition
! flag.
!
RET_VAL = (.QUEUE eql .QUEUE[Q_REVERSE]); ! Check for non-empty
!
! Insert entry onto end of queue and
! update pointers.
!
LAST_ENTRY = .QUEUE[Q_REVERSE];
ENTRY[Q_REVERSE] = .LAST_ENTRY;
ENTRY[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .ENTRY;
LAST_ENTRY[Q_FORWARD] = .ENTRY;
!
! Unlock the queue.
!
UNLOCK (QUEUE[Q_SEMAPHORE]);
!
! Return empty to non-empty transition flag.
!
return .RET_VAL;
end; ! End of NMU$QUEUE_INSERT
%global_routine ('NMU$QUEUE_REMOVE', QUEUE: ref Q_HEADER) =
!++
! Functional description:
!
! This routine removes the first entry on a queue.
! If the queue is empty a zero (0) value is returned.
!
! Formal parameters:
!
! .QUEUE Address of queue header
!
! Routine value:
!
! Non-empty queue Address of entry (after queue information)
! Empty queue Zero (0)
!
! Side effects:
!
! The forward pointer of the queue header and the
! reverse pointer of the second entry (if any) are
! changed to point to each other.
!--
begin
local
ENTRY : ref Q_ENTRY,
NEXT_ENTRY : ref Q_ENTRY;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Get address of first entry on the queue.
!
ENTRY = .QUEUE[Q_FORWARD];
!
! Check for empty queue, return zero if empty.
! If entry found...
! unlink from queue
! fixup queue around hole made by removal
! clear queue linkage in removed entry.
!
if .ENTRY eql .QUEUE
then ENTRY = 0
else begin
NEXT_ENTRY = .ENTRY[Q_FORWARD];
QUEUE[Q_FORWARD] = .NEXT_ENTRY;
NEXT_ENTRY[Q_REVERSE] = .QUEUE;
ENTRY[Q_FORWARD] = 0;
ENTRY[Q_REVERSE] = 0;
end;
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock the queue
return .ENTRY; ! Return address of entry found, if any
end; ! End of NMU$QUEUE_REMOVE
%global_routine ('NMU$QUEUE_EXTRACT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =
!++
! Functional description:
!
! This routine handles extraction of an entry from a place
! in a queue other than the beginning. This requires "knowing"
! the address of the queue entry before calling this routine.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .ENTRY Address of entry (after queue information)
!
! Routine value:
!
! $true Entry was found on the queue and extracted
! $false Entry was not found on the queue
!
! Side effects:
!
! The links of the queue entries before and after the
! entry to be extracted are updated to point to each
! other.
!
!--
begin
local
NEXT_ENTRY : ref Q_ENTRY,
PREVIOUS_ENTRY : ref Q_ENTRY,
SEARCH : ref Q_ENTRY,
RET_VAL;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Loop until the entry is found.
!
SEARCH = .QUEUE[Q_FORWARD];
while (.SEARCH neq .ENTRY) and (.SEARCH neq .QUEUE)
do SEARCH = .SEARCH[Q_FORWARD];
if .SEARCH eql .ENTRY ! Found entry ?
then begin ! Yes, extract it and return true
NEXT_ENTRY = .ENTRY[Q_FORWARD];
PREVIOUS_ENTRY = .ENTRY[Q_REVERSE];
NEXT_ENTRY[Q_REVERSE] = .PREVIOUS_ENTRY;
PREVIOUS_ENTRY[Q_FORWARD] = .NEXT_ENTRY;
RET_VAL = $TRUE;
end
else RET_VAL = $FALSE; ! No, return false
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock queue
return .RET_VAL; ! Return result of extraction
end; ! End of NMU$QUEUE_EXTRACT
%global_routine ('NMU$QUEUE_LENGTH', QUEUE: ref Q_HEADER) =
!++
! Functional description:
!
! This routine returns the length (number of entries) of a queue.
!
! Formal parameters:
!
! .QUEUE Address of queue header
!
! Routine value:
!
! The length (number of entries) of the queue.
!
! Side effects: none
!
!--
begin
local
ENTRY,
RESULT,
NEXT : ref Q_ENTRY;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Return length of 0
!
RESULT = 0;
if .(.QUEUE) neq 0
then begin
NEXT = .QUEUE[Q_FORWARD]; ! Set first entry to the queue
while (ENTRY = .NEXT) neq .QUEUE
do begin ! Scan queue until end of queue
RESULT = .RESULT + 1;
NEXT = .NEXT[Q_FORWARD];
end;
end;
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock the queue
return .RESULT; ! Return the result of scanning
end; ! End of NMU$QUEUE_LENGTH
%global_routine ('NMU$QUEUE_SCAN', QUEUE: ref Q_HEADER, DATA, S_RTN) =
!++
! Functional description:
!
! This routine facilitates scanning a queue. The S_RTN
! parameter specifies a routine that is to be called with
! the DATA parameter and each ENTRY. When the return
! from the S_RTN is non-zero or the queue runs out, the
! scanning stops.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .DATA Data to be passed to each S_RTN call
! .S_RTN Scanning routine to be called for each entry
!
! Routine value:
!
! The value of S_RTN if it ever returns a non-zero value.
! Zero if the queue runs out before non-zero from S_RTN.
!
! Side effects: none
!
!--
begin
bind routine
SCAN_ROUTINE = .S_RTN;
local
ENTRY,
RESULT,
NEXT : ref Q_ENTRY;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Clear the result value and point to the
! first entry on the queue.
!
RESULT = 0;
NEXT = .QUEUE[Q_FORWARD];
!
! Scan queue until end of queue or the scan
! routine returns a non zero value.
!
while (ENTRY = .NEXT) neq .QUEUE
do begin
NEXT = .NEXT[Q_FORWARD];
UNLOCK (QUEUE[Q_SEMAPHORE]);
if (RESULT = SCAN_ROUTINE (.ENTRY, .DATA)) neq 0
then exitloop;
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
end;
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock the queue
return .RESULT; ! Return the result of scanning
end; ! End of NMU$QUEUE_SCAN
%global_routine ('NMU$QUEUE_SCAN_EXTRACT', ENTRY: ref Q_ENTRY) : novalue =
!++
! Functional description:
!
! This routine is used to extract a queue entry from
! a queue while scanning the queue. It is assumed
! that the only queue being worked on is the one being
! scanned. It also is assumed that the entry being
! extracted is the one currently being looked at by
! the scanning routine.
!
! ANY OTHER USE OF THIS ROUTINE CAN GIVE UNPREDICTABLE
! RESULTS!
!
! Formal parameters:
!
! .ENTRY Address of queue entry to remove.
!
! Routine value: none
! Side effects: none
!
!--
begin
local
NEXT_ENTRY : ref Q_ENTRY,
PREVIOUS_ENTRY : ref Q_ENTRY;
NEXT_ENTRY = .ENTRY[Q_FORWARD];
PREVIOUS_ENTRY = .ENTRY[Q_REVERSE];
NEXT_ENTRY[Q_REVERSE] = .PREVIOUS_ENTRY;
PREVIOUS_ENTRY[Q_FORWARD] = .NEXT_ENTRY;
end; ! End of NMU$QUEUE_SCAN_EXTRACT
%global_routine ('NMU$QUEUE_NEXT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =
!++
!
! Functional description:
!
! This routine will return the next entry in a queue.
!
! At the first call, ENTRY should be zero. The routine will then return
! the first element. On successive calls, ENTRY should be the entry
! returned on the previous call. NMU$QUEUE_NEXT will return the next
! entry or 0 at the end of the queue.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .ENTRY Address of entry
!
! Routine value:
!
! 0 End of queue
! ENTRY Address of next entry in queue
!
!--
begin
local RESULT;
if ..QUEUE eql 0
then return 0 ! No queue at all
else begin
! Lock the queue from concurrently running processes
while not LOCK(QUEUE[Q_SEMAPHORE]) do 1;
if .ENTRY eql 0
then RESULT = .QUEUE[Q_FORWARD] ! First entry
else RESULT = .ENTRY[Q_FORWARD]; ! Get next entry
if .RESULT eql .QUEUE
then RESULT = 0; ! At end of queue
! Unlock the queue
UNLOCK(QUEUE[Q_SEMAPHORE]);
end;
return .RESULT;
end; ! End of NMU$QUEUE_NEXT
end ! End of module NMUQUE
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:2
! Comment Column:40
! Comment Rounding:+1
! End: