Trailing-Edge
-
PDP-10 Archives
-
BB-X117B-SB_1986
-
10,7/nml/nmlctt.bli
There are 2 other files named nmlctt.bli in the archive. Click here to see a list.
! UPD ID= 202, SNARK:<6.1.NML>NMLCTT.BLI.4, 10-Dec-84 15:20:43 by HALPIN
! Get MONSYM Library file out of default directory, not BLI:
!
! UPD ID= 84, SLICE:<6.1.NML>NMLCTT.BLI.3, 18-Sep-84 14:58:09 by GUNN
! WORK:<GUNN.NML>NMLCTT.BLI.2 21-Aug-84 12:03:43, Edit by GUNN
!
! Change to accomodate new LIBRARY conventions. MONSYM.L36 and JLNKG.L36
! are now explicity declared here rather than in NMULIB.
!
! UPD ID= 35, SNARK:<6.1.NML>NMLCTT.BLI.2, 24-May-84 16:27:15 by GLINDELL
!NET:<BRANDT.DEVELOPMENT>NMLCTT.BLI.1 9-Dec-82 18:00:03, Edit by BRANDT
!
! Ident 04.
! Change COUNTER_BUFFER_SIZE to 200 and allocation call as suggested
! by VOBA and GROSSMAN.
!
! NET:<PECKHAM.DEVELOPMENT>NMLCTT.BLI.4 6-Mar-82 21:19:03, Edit by PECKHAM
!
! Ident 03.
! Change input parameters for $NML$SHOZC.
!
! NET:<PECKHAM.DEVELOPMENT>NMLCTT.BLI.2 5-Feb-82 16:38:08, Edit by PECKHAM
!
! Ident 02.
! Fix range checking for 16 bit machines in NML$COUNTER_TIMER_SET.
!
! NET:<GROSSMAN>NMLCTT.BLI.2 27-Jan-82 08:44:55, Edit by GROSSMAN
!
! Ident 1.
! Don't allow counter timers to be set with 0, negative, or values greater
! than 65536. The routine NML$COUNTER_TIMER_SET will return a $false value
! if there is an attempt to do so.
!
! NET:<GROSSMAN>NMLCTT.BLI.34 26-Jan-82 06:48:16, Edit by GROSSMAN
!
! Fix bug in NML$CTR_CHECK_TIME. This caused the counter block given in
! the call to NMU$QUEUE_SCAN to never be changed (and this caused the task to
! always schedule the first counter block that ever got set). Also fix bugs
! related to being woken up on multiple events. We can now successfully wake
! up on counter timer queue changes, and on timeouts!
!
! NET:<GROSSMAN>NMLCTT.BLI.10 23-Jan-82 02:25:06, Edit by GROSSMAN
!
! Fix bug(s) with routines called by NMU$QUEUE_SCAN. They were all declared
! novalue, but it turns out to be much more valuable to return values than
! not to, because a non-zero value (which the novalue attribute does not
! ensure) terminates queue scanning immediately. This screws me up.
!
! NET:<GROSSMAN>NMLCTT.BLI.8 22-Jan-82 14:46:13, Edit by GROSSMAN
!
! Fix routine NML$CTR_CHECK_TIME so that it returns the counter block with
! the least date/time.
!
! NET:<GROSSMAN>NMLCTT.BLI.6 22-Jan-82 02:17:43, Edit by GROSSMAN
!
! Fix NML$CTR_REMOVE_ENTITY so that it knows how to remove the first item
! on the counter blocks entity list.
!
! NET:<GROSSMAN>NMLCTT.BLI.17 21-Jan-82 10:35:42, Edit by GROSSMAN
!
! Add the SHOW and ZERO function and event logging interface...
!
module NMLCTT ( ! Counter Timer Task
ident = 'X00.04'
) =
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 implements the Counter Timer functionality. This task wakes
! up every time a Counter Timer goes off in order to generate an
! Automatic Counter event. The internal functioning of this module will
! be to repeatedly do a Read-and-Zero function for each entity which has
! a counter timer set. And then to sleep until the next counter timer
! goes off. The actual counter timer event would seem to be an atomic
! operation to the user.
!
! Environment: TOPS10 and TOPS20 user mode, MCB RSX task mode
!
! Author: Stu Grossman, Creation date: 6 January 1982
!
!--
!
! Include files
!
library 'NMLLIB'; ! NML definitions
%if $TOPS20
%then
library 'MONSYM'; ! Monitor symbols
library 'JLNKG'; ! JSYS linkage definitions
%fi
!
! External routines
!
external routine
NMU$TABLE_ROUTINES, ! Table manipulation stuff
NMU$QUEUE_MANAGER, ! Queue management routines
NMU$SCHED_MANAGER, ! Scheduler routines
NMU$MEMORY_MANAGER, ! Memory management routines
NML$DECLARE_EVENT; ! Interface to event generator
!
! Debugging definitions
!
external
%debug_data_base; ! Debugging definitions
!
! Forward references
!
forward routine
NML$CTR_CHECK_TIME,
NML$CTR_COUNTER_TIMER_PREDICATE,
NML$CTR_ENTITY_LIST_SCANNER,
NML$CTR_REMOVE_ENTITY : novalue,
NML$CTR_COUNTER_QUEUE_SCANNER;
!
! Counter timer block definitions
!
$field
CTR_FIELDS =
set
CTR_QUEUE = [$sub_block (Q_ENTRY_SIZE)], ! Queue of these blocks
CTR_TIME = [$sub_block (TIME_BLOCK_SIZE)], ! Abs time of next period
CTR_PERIOD = [$integer], ! Period in seconds
CTR_ENTITY_LIST = [$address] ! Pointers to entities on this timer
tes;
literal
CTR_SIZE = $field_set_size,
CTR_ALLOCATION = $field_set_units;
macro
CTR_BLOCK = block [CTR_SIZE] field (CTR_FIELDS) %;
!
! Entity block, pointed to by CTR_BLOCKs
!
$field
ENTITY_FIELDS =
set
ENTITY_NEXT = [$address], ! Points to next block
ENTITY_TYPE = [$tiny_integer], ! Entity type
ENTITY_ID_PTR = [$pointer] ! Pointer to string id
tes;
literal
ENTITY_SIZE = $field_set_size,
ENTITY_ALLOCATION = $field_set_units;
macro
ENTITY_BLOCK = block [ENTITY_SIZE] field (ENTITY_FIELDS) %;
!
! Storage
!
own
COUNTER_TIMER_QUEUE : SQ_HEADER,
OLD_ENTITY_ID : ref ENTITY_BLOCK,
OLD_COUNTER_TIMER_BLOCK : ref CTR_BLOCK,
COUNTER_TIMER_QUEUE_WAS_CHANGED;
%global_routine ('NML$COUNTER_TIMER_TASK') : novalue =
!++
! Functional description:
!
! This routine will initialize the counter timer data base and
! then loop forever waiting for counter timers to be set or for
! counter timers to go off.
!
! Formal parameters:
!
! None.
!
! Routine value:
!
! None.
!
! Side effects:
!
! None.
!
!--
begin
local
CURRENT_TIME : TIME_BLOCK,
TEMP,
CURRENT_COUNTER : ref CTR_BLOCK,
COUNTER_BUFFER_PTR, ! Points to receiving buffer
COUNTER_BUFFER_SIZE, ! Contains size of buffer
EVENT : ref RAW_EVENT_BLOCK; ! Event block
!
! Reset the counter timer scheduler queue
!
NMU$SQUEUE_RESET (COUNTER_TIMER_QUEUE);
COUNTER_TIMER_QUEUE_WAS_CHANGED = $false;
!
! Set up a buffer for reading the counters into and a raw event block for
! queueing up the event.
!
COUNTER_BUFFER_SIZE = 200;
COUNTER_BUFFER_PTR =
ch$ptr (NMU$MEMORY_GET (ch$allocation (.COUNTER_BUFFER_SIZE)),,8);
EVENT = NMU$MEMORY_GET (RAW_EVENT_BLOCK_ALLOCATION);
!
! Loop forever doing this tasks' work
!
while $true do
begin
!
! Block, waiting for the counter timer queue to become non-empty.
! After receiving an item reinstall it on the queue, because we really don't
! want to remove anything from the queue.
!
CURRENT_COUNTER = NMU$SQUEUE_REMOVE (COUNTER_TIMER_QUEUE);
NMU$QUEUE_INSERT (COUNTER_TIMER_QUEUE [Q_QUEUE],
CURRENT_COUNTER [CTR_QUEUE]);
COUNTER_TIMER_QUEUE_WAS_CHANGED = $false;
!
! Scan through the queue looking for the counter timer block that has the
! nearest time to now (or one that should have occurred already).
!
TIME_CURRENT (0, CURRENT_TIME);
NMU$QUEUE_SCAN (COUNTER_TIMER_QUEUE,
CURRENT_COUNTER,
NML$CTR_CHECK_TIME);
!
! See if the time has already passed, if it has, don't go to sleep, else
! sleep until we wake up at the right time (or if the COUNTER_TIMER_QUEUE
! has changed (so that we can reschedule)).
!
TEMP = TIME_DIFFERENCE_SECONDS (CURRENT_COUNTER [CTR_TIME],
CURRENT_TIME);
%debug (CTT_TRACE,
(TRACE_INFO ('%D second counter selected in %D seconds',
.CURRENT_COUNTER [CTR_PERIOD],
.TEMP)));
!
! Now we have to put ourself on our own event queue so that when
! NML$COUNTER_TIMER_SET changes the counter timer queue, we get woken up.
! First, clear the event block, then put the current task (me) into the
! event queue for myself. This is just like doing an NMU$SCHED_WAIT with
! no wait.
!
if .TEMP gtr 0 then
begin
bind
EB = COUNTER_TIMER_QUEUE [Q_EVENT] : EVENT_BLOCK;
NMU$TABLE_INSERT (EB [EB_TASKS], CURRENT_TASK);
NMU$SCHED_SLEEP (.TEMP);
NMU$TABLE_DELETE (EB [EB_TASKS], 1);
end;
!
! Now, its time to see if we woke up because we timed out, or because we
! have to reschedule. This is done by examining the event queue. If the queue
! is still full, then we got here because of we woke up from our sleep, else
! the queue has been changed, and we have to reschedule.
!
if not .COUNTER_TIMER_QUEUE_WAS_CHANGED then
begin
local
ENTITY : ref ENTITY_BLOCK;
ENTITY = .CURRENT_COUNTER [CTR_ENTITY_LIST];
while .ENTITY neq 0 do
begin
%debug (CTT_TRACE,
(TRACE_INFO ('Counter timer for entity %#A going off',
ch$rchar(.ENTITY[ENTITY_ID_PTR]),
ch$plus(.ENTITY[ENTITY_ID_PTR],1))));
EVENT [REB_EVENT_CODE] = 0 ^ 6 + 8; ! Automatic Counters
EVENT [REB_ENTITY_TYPE] = .ENTITY [ENTITY_TYPE];
EVENT [REB_ENTITY_POINTER] = .ENTITY [ENTITY_ID_PTR];
EVENT [REB_DATA_POINTER] = .COUNTER_BUFFER_PTR;
EVENT [REB_DATA_LENGTH] = .COUNTER_BUFFER_SIZE;
EVENT [REB_SOURCE_POINTER] = 0;
EVENT [REB_TIME_BLOCK] = 0;
$NML$SHOZC(.ENTITY [ENTITY_TYPE],
.ENTITY [ENTITY_ID_PTR],
, %(no qualifier)%
EVENT [REB_DATA_LENGTH],
.COUNTER_BUFFER_PTR);
NML$DECLARE_EVENT (.EVENT);
ENTITY = .ENTITY [ENTITY_NEXT];
end;
TIME_PLUS (CURRENT_COUNTER [CTR_TIME],
.CURRENT_COUNTER [CTR_PERIOD]);
end;
end; ! End of task loop
end; ! End of NML$COUNTER_TIMER_TASK
%global_routine ('NML$COUNTER_TIMER_SET', PARM_NO, TYPE, EID_ADR, PARM_VAL_PTR) =
!++
! Functional description:
!
! This routine is called by the Volatile Data Base manager each time a
! parameter is set. If the parameter is a counter timer, then it will
! either create a new counter timer block or just string the entity onto
! an already existing counter timer block of the same period. It will
! also notify the counter timer task if a new counter timer block has
! been created.
!
! Formal parameters:
!
! PARM_NO The Network Management parameter number
! TYPE The entity type
! EID_ADR Address of entity id string
! PARM_VAL_PTR Character pointer to byte swapped parameter value
!
! Routine value:
!
! $true The value of the counter is between 1 and 65536
! $false Counter timer value is out of range
!
!--
begin
local
ENTITY_ID : ref ENTITY_BLOCK,
PERIOD;
!
! First check to see if a counter timer is being set. If not, just return.
!
if not NML$CTR_COUNTER_TIMER_PREDICATE (.PARM_NO, .TYPE) then return $true;
!
! Ok, we got a counter timer, now lets see if it has been set already.
! First set up an entity id block
!
PERIOD = GETW (PARM_VAL_PTR);
if .PERIOD eqlu 0 or (%bpval gtr 16 and .PERIOD gtr 65535) then return $false;
ENTITY_ID = NMU$MEMORY_GET (ENTITY_ALLOCATION);
ENTITY_ID [ENTITY_TYPE] = .TYPE;
ENTITY_ID [ENTITY_ID_PTR] = ch$ptr(.EID_ADR,,8);
ENTITY_ID [ENTITY_NEXT] = 0;
!
! Now scan through the data base looking for another block similar to the one
! we now have.
!
OLD_ENTITY_ID = OLD_COUNTER_TIMER_BLOCK = 0;
NMU$QUEUE_SCAN (COUNTER_TIMER_QUEUE,
.ENTITY_ID,
NML$CTR_ENTITY_LIST_SCANNER);
!
! If a counter timer has already been set for this entity, clear it, otherwise
! just proceed.
!
if .OLD_ENTITY_ID neq 0
then NML$CTR_REMOVE_ENTITY (.OLD_COUNTER_TIMER_BLOCK, .OLD_ENTITY_ID);
!
! Now see if there is an existing counter block with the same period as that of
! the counter we want to set.
!
OLD_COUNTER_TIMER_BLOCK = 0;
NMU$QUEUE_SCAN (COUNTER_TIMER_QUEUE,
.PERIOD,
NML$CTR_COUNTER_QUEUE_SCANNER);
!
! If there is no counter block with that period, create one, insert it into
! the queue of counter blocks (and wake up the counter timer task), and set
! its time and period.
!
if .OLD_COUNTER_TIMER_BLOCK eql 0 then
begin
OLD_COUNTER_TIMER_BLOCK = NMU$MEMORY_GET (CTR_ALLOCATION);
NMU$SQUEUE_INSERT (COUNTER_TIMER_QUEUE, .OLD_COUNTER_TIMER_BLOCK);
COUNTER_TIMER_QUEUE_WAS_CHANGED = $true;
OLD_COUNTER_TIMER_BLOCK [CTR_PERIOD] = .PERIOD;
TIME_CURRENT (0, OLD_COUNTER_TIMER_BLOCK [CTR_TIME]);
OLD_COUNTER_TIMER_BLOCK [CTR_ENTITY_LIST] = .ENTITY_ID;
return $true
end;
OLD_ENTITY_ID = .OLD_COUNTER_TIMER_BLOCK [CTR_ENTITY_LIST];
while .OLD_ENTITY_ID [ENTITY_NEXT] neq 0 do
OLD_ENTITY_ID = .OLD_ENTITY_ID [ENTITY_NEXT];
OLD_ENTITY_ID [ENTITY_NEXT] = .ENTITY_ID;
$true
end; ! End of NML$COUNTER_TIMER_SET
%global_routine ('NML$COUNTER_TIMER_CLEAR', PARM_NO, TYPE, EID_ADR) : novalue =
!++
! Functional description:
!
! This routine is called by the Volatile Data Base manager each time a
! parameter is cleared. If the parameter is a counter timer, then it
! will remove that counter timer from the data base.
!
! Formal parameters:
!
! PARM_NO The Network Management parameter number
! TYPE The entity type
! EID_ADR Address of entity id string
!
!--
begin
local
ENTITY_ID : ref ENTITY_BLOCK;
!
! First check to see if a counter timer is being set. If not, just return.
!
if not NML$CTR_COUNTER_TIMER_PREDICATE (.PARM_NO, .TYPE) then return ;
!
! Ok, we got a counter timer, now lets see if it has been set already.
! First set up an entity id block
!
ENTITY_ID = NMU$MEMORY_GET (ENTITY_ALLOCATION);
ENTITY_ID [ENTITY_TYPE] = .TYPE;
ENTITY_ID [ENTITY_ID_PTR] = ch$ptr(.EID_ADR,,8);
ENTITY_ID [ENTITY_NEXT] = 0;
!
! Now scan through the data base looking for another block similar to the one
! we now have.
!
OLD_ENTITY_ID = OLD_COUNTER_TIMER_BLOCK = 0;
NMU$QUEUE_SCAN (COUNTER_TIMER_QUEUE,
.ENTITY_ID,
NML$CTR_ENTITY_LIST_SCANNER);
!
! If a counter timer has already been set for this entity, clear it, otherwise
! just return.
!
if .OLD_ENTITY_ID neq 0 then
begin
NML$CTR_REMOVE_ENTITY (.OLD_COUNTER_TIMER_BLOCK, .OLD_ENTITY_ID);
return
end;
NMU$MEMORY_RELEASE (.ENTITY_ID, ENTITY_ALLOCATION);
end; ! End of NML$COUNTER_TIMER_CLEAR
%routine ('NML$CTR_CHECK_TIME', COUNTER_BLOCK : ref CTR_BLOCK, CURRENT_COUNTER) =
!++
! Functional description:
!
! This routine is called from NML$QUEUE_SCAN with the address of a
! CTR_BLOCK and a time block. It will update CURRENT_COUNTER to reflect
! the counter block found thus far that has the smallest time.
!
! Inputs:
!
! COUNTER_BLOCK The address of a counter block
! CURRENT_COUNTER The address of the address of a counter block
! used as an initial comparison for this routine.
!
! Outputs:
!
! .CURRENT_COUNTER The address of the latest (thus far) CTR_BLOCK
!
!--
begin
bind
TEMP = .CURRENT_COUNTER : ref CTR_BLOCK;
if TIME_TEST (COUNTER_BLOCK [CTR_TIME], lss, TEMP [CTR_TIME])
then TEMP = .COUNTER_BLOCK;
0 ! Ensure that NMU$QUEUE_SCAN does not terminate prematurely
end; ! End of NML$CTR_CHECK_TIME
%routine ('NML$CTR_ENTITY_LIST_SCANNER', COUNTER_BLOCK : ref CTR_BLOCK, ENTITY_ID : ref ENTITY_BLOCK) =
!++
! Functional description:
!
! This routine will facilitate the search for an entity in the counter
! timer data base. It is called for each counter timer block, and will
! scan through that blocks entity list looking for the desired entity.
! When it finds a match, it will set up OLD_ENTITY_ID and
! OLD_COUNTER_TIMER_BLOCK.
!
! Formal parameters:
!
! COUNTER_BLOCK The address of the current counter block
! ENTITY_ID The address of the entity being sought after.
!
! Implicit outputs:
!
! OLD_ENTITY_ID The address of the found entity or 0
! OLD_COUNTER_TIMER_BLOCK " " " " " counter " "
!
! Routine value:
!
! none
!--
begin
local
TEMP : ref ENTITY_BLOCK;
TEMP = .COUNTER_BLOCK [CTR_ENTITY_LIST];
while .TEMP neq 0 do
begin
if .TEMP [ENTITY_ID_PTR] eql .ENTITY_ID [ENTITY_ID_PTR] then
begin
OLD_ENTITY_ID = .TEMP;
OLD_COUNTER_TIMER_BLOCK = .COUNTER_BLOCK;
return 1 ! Tell NMU$QUEUE_SCAN to stop scanning
end;
TEMP = .TEMP [ENTITY_NEXT];
end;
0 ! Tell NMU$QUEUE_SCAN to keep on scanning
end; ! End of NML$CTR_ENTITY_LIST_SCANNER
%routine ('NML$CTR_COUNTER_QUEUE_SCANNER', COUNTER_BLOCK : ref CTR_BLOCK, PERIOD) =
!++
! Functional description:
!
! This routine will facilitate the search for a counter block with a
! certain period. If such a block is not found a zero will be returned.
!
! Formal parameters:
!
! COUNTER_BLOCK The address of the current counter block
! PERIOD The period be being searched for.
!
! Implicit outputs:
!
! OLD_COUNTER_TIMER_BLOCK The address of a counter block that has the
! proper period.
!
! Routine value:
!
! none
!--
begin
if .COUNTER_BLOCK [CTR_PERIOD] neq .PERIOD then return 0
else OLD_COUNTER_TIMER_BLOCK = .COUNTER_BLOCK
end; ! End of NML$CTR_COUNTER_QUEUE_SCANNER
%routine ('NML$CTR_COUNTER_TIMER_PREDICATE', PARM_NO, TYPE) =
!++
! Functional description:
!
! This routine will determine whether or not the entity type and
! parameter number constitute a counter timer parameter for that entity
! type. This routine is needed because the fucking NML specification is
! so inane.
!
! Formal parameters:
!
! PARM_NO Parameter number
! TYPE Network management type number
!
! Routine value:
!
! $false The parameter is not a counter timer
! $true The parameter is a counter timer
!--
begin
if ( .TYPE eql NODE_E and .PARM_NO eql 160
or .TYPE eql LINE_ and .PARM_NO eql 110
or .TYPE eql CIRCUIT_ and .PARM_NO eql 110
or .TYPE eql MODULE_ and .PARM_NO eql 100)
then $true else $false
end; ! End of NML$CTR_COUNTER_TIMER_PREDICATE
%routine ('NML$CTR_REMOVE_ENTITY') : novalue =
!++
! Functional description:
!
! This routine will remove an entity from the counter timer data base.
! It will unlink and deallocate its entity block. It will also unlink
! and deallocate empty counter timer blocks (and wake up the counter
! timer task if so).
!
! Implicit inputs:
!
! OLD_ENTITY_ID The address of the entity to be killed
! OLD_COUNTER_TIMER_BLOCK The address of the counter block that contains
! the aforementioned entity.
!
! Side effects:
!
! The counter timer task may be invoked if a counter timer block gets
! destroyed. If all the counter timer blocks get destroyed, the
! counter timer task will sleep forever.
!
! Routine value:
!
! none
!
!--
begin
local
TEMP : ref ENTITY_BLOCK;
!
! First see if the entity is hooked up directly to the counter block (ie: is
! it the first item?). If so, update the pointer in the counter block, else
! update the pointer in the appropriate entity block in the counters entity
! block list.
!
if .OLD_COUNTER_TIMER_BLOCK [CTR_ENTITY_LIST] eql .OLD_ENTITY_ID
then
OLD_COUNTER_TIMER_BLOCK [CTR_ENTITY_LIST] = .OLD_ENTITY_ID [ENTITY_NEXT]
else
begin
TEMP = .OLD_COUNTER_TIMER_BLOCK [CTR_ENTITY_LIST];
while (.TEMP [ENTITY_NEXT] neq .OLD_ENTITY_ID) do
TEMP = .TEMP [ENTITY_NEXT];
TEMP [ENTITY_NEXT] = .OLD_ENTITY_ID [ENTITY_NEXT];
end;
NMU$MEMORY_RELEASE (.OLD_ENTITY_ID, ENTITY_ALLOCATION);
if .OLD_COUNTER_TIMER_BLOCK [CTR_ENTITY_LIST] eql 0 then
begin
NMU$QUEUE_EXTRACT (COUNTER_TIMER_QUEUE [Q_QUEUE],
OLD_COUNTER_TIMER_BLOCK [CTR_QUEUE]);
COUNTER_TIMER_QUEUE_WAS_CHANGED = $true;
NMU$MEMORY_RELEASE (.OLD_COUNTER_TIMER_BLOCK, CTR_ALLOCATION);
NMU$SCHED_FLAG (COUNTER_TIMER_QUEUE [Q_EVENT]);
end;
end; ! NML$CTR_REMOVE_ENTITY
end ! End of NMLCTT
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:0
! Comment Column:40
! Comment Rounding:+1
! End: