Trailing-Edge
-
PDP-10 Archives
-
BB-X117B-SB_1986
-
10,7/nml/nmuskd.bli
There are 3 other files named nmuskd.bli in the archive. Click here to see a list.
!DSKB:NMUSKD.BLI[10,6026,NML] 3-Apr-86 12:26:04 by DAVENPORT
! Edit=146 NMUNET: Fix definitions for ACTDAE profile format 6.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 12-Mar-86 12:37:56 by DAVENPORT
! Edit=145 DTET10: [QAR#868895] Fix test for CPU running
! in OPEN_DTE_DEVICE.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 7-Mar-86 07:21:35 by DAVENPORT
! Edit=144 NMUCOM:
! DTET10: [QAR#868815] Teach CHK11 to use non-blocking
! input to read CHK11 output from the terminal.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 3-Mar-86 15:59:12 by DAVENPORT
! Edit=143 NMUNET: [QAR#868905] NMU$NETWORK_OPEN claims a node
! is unreachable if the link gets connected
! before it checks for CONNECT_WAIT. Rework
! the code to get this correct.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 30-Dec-85 10:29:25 by DAVENPORT
! Edit=142 NMLDLW: Don't exit DLW_NI_TASK because of any KLNI
! errors.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 23-Dec-85 16:23:19 by DAVENPORT
! Edit=141 NMUT10: Change CRSACS to CRSHAC for FILDDT.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 18-Dec-85 14:51:35 by DAVENPORT
! Edit=140 DTET10: [QAR#868540] When reading CHK11 terminal output
! use TRMOP. function .TOTIC instead of .TOSIP to
! determine if any characters are available.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 12-Dec-85 12:44:51 by DAVENPORT
! Edit=137 NCPRSP: [QAR#868591] When processing an event list
! in a NICE response message be prepared for
! the maximum of 64 bits of data.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 27-Nov-85 10:42:11 by DAVENPORT
! Edit=136 DTET10: When releasing the CHK11 DAEMON buffer clear
! its address in the CD block to prevent later
! memory allocation mishaps.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 22-Nov-85 10:38:42 by DAVENPORT
! Edit=135 NMUNET: Fix NMU$NETWORK_VALIDATE to support
! accounting profile version 6.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 19-Nov-85 14:29:31 by DAVENPORT
! Edit=134 NCPRSP: Fix output routines to always use tabular
! format if defined.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 7-Nov-85 14:58:52, Edit by DAVENPORT
! Edit=133 NMUCOM: Define userid, account, and password fields
! to be 39 characters long.
! NMUNET: Correctly handle long user names and passwords
! in NMU$NETWORK_VALIDATE routine.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 1-Nov-85 11:46:29, Edit by DAVENPORT
! Edit=132 NMLEVL: When output .DMERR failed error messages,
! special case DAEMON not running message.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 1-Nov-85 11:00:13, Edit by DAVENPORT
! Edit=131 NMUT10: [QAR #868327] Rework macro ABORT_LINK to
! always ensure that a link is released.
!
!DSKB:NMUSKD.BLI[10,6026,NML] 30-Oct-85 15:56:32, Edit by DAVENPORT
! Edit=130 NMARCH: Add definitions for NIA20 specific transmit
! and receive error bits.
!
!DSKB:NMUSKD.BLI[10,6062,MCO] 30-Oct-85 11:32:05, Edit by APPELLOF
! Edit=127 NMUT10: Fix various macros to always set up
! the UUO ac before doing NSP. UUOs.
!
!DSKB:NMARCH.REQ[10,6062,NML] 13-Oct-85 08:52:04, Edit by APPELLOF
! Edit=126 NMARCH: [SPR #10-34758] Change "DDCMP-Point" etc.
! to "DDCMP Point" etc.
!
!DSKT:NMUSKD.BLI[10,6026,NML] 11-Sep-85 10:26:44, Edit by DAVENPORT
!
! Edit=125 NMUSKD: Update binary copyright notice.
!
!DSKT:NMUSKD.BLI[10,6026,NML] 5-Sep-85 16:30:22, Edit by DAVENPORT
!
! Edit=124 DTET10: Set IO.SUP for CHK11 terminal.
!
!DSKT:NMUSKD.BLI[10,6026,NML] 26-Aug-85 11:04:13, Edit by DAVENPORT
!
! Edit=123 NMLEVL: On DAEMON UUO error for function .DMERR, include
! the actual UUO error code.
!
!DSKT:NMUSKD.BLI[10,6026,NML] 13-Aug-85 12:31:04, Edit by DAVENPORT
!
! Edit=122 NMLRCZ: [QAR #868202] Fix READ_SPECIFIC_ENTITY to not
! loop forever trying to get larger buffers for
! NTMAN. This can cause NML to fail if the
! resource error is a monitor problem.
!
!DSKT:NMUSKD.BLI[10,6026,NML] 10-Jul-85 11:04:01, Edit by DAVENPORT
!
! Edit=121 NMUNET: [QAR #868047] Fix NMU$NETWORK_OPEN to report
! no communication with remote node rather than
! timeout if remote node isn't up.
!
!DSKT:NMUSKD.BLI[10,6026,NML] 27-Jun-85 15:22:01, Edit by DAVENPORT
!
! Edit=120 KNIT10: Cleanup code to work with ETHNT. PSI improvements.
!
!DSKT:NMUSKD.BLI[10,6026,NML] 23-May-85 14:21:15, Edit by DAVENPORT
!
! Edit=117 NMLLBK:
! NMLDTL:
! NMLDLW:
! NMUDLX:
! NMUKNI:
! KNIT10: Add support for TOPS-10 ethernet service.
!
!DSKT:NMUSKD.BLI[10,6062,NML] 15-May-85 09:12:18, Edit by APPELLOF
!
! Edit=116 DTET10: Add routines to log CHK11 output to ERROR.SYS
! for TOPS-10
! ALL: Update to latest TOPS-20 version.
!
! DSKT:NMUSKD.BLI[10,6026,NMLUPD] 31-Jan-85 15:57:02, Edit by DAVENPORT
!
! Edit=115 NMINI: Add routine NMLCHK to INIT_GLOBALS for TOPS-10.
! NMUSKD: Call routine NMLCHK as part of initialization.
! NMUT10: Add routine NMLCHK which runs SYS:NML702.EXE if
! invoked on monitor version 70260 or earlier.
!
! DSKT:NMUSKD.BLI[10,6026,NMLUPD] 24-Jan-85 10:23:44, Edit by DAVENPORT
!
! Edit=114 All: Upgrade to latest TOPS-20 code.
!
! UPD ID= 232, SNARK:<6.1.NML>NMUSKD.BLI.5, 17-Jan-85 10:53:25 by GLINDELL
! STOP_PROGRAM in NMU$SCHED_COMPLETE instead of trying to continue
!
! UPD ID= 197, SNARK:<6.1.NML>NMUSKD.BLI.4, 10-Dec-84 15:01:03 by HALPIN
! Get MONSYM Library file out of default directory, not BLI:
!
! UPD ID= 102, SLICE:<6.1.NML>NMUSKD.BLI.3, 18-Sep-84 15:41:03 by GUNN
! WORK:<GUNN.NML>NMUSKD.BLI.4 21-Aug-84 14:25:10, 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= 33, SNARK:<6.1.NML>NMUSKD.BLI.2, 24-May-84 16:17:04 by GLINDELL
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 22-Jan-85 13:42:11, Edit by DAVENPORT
!
! Edit=113 NMUDLX: Change routine NMU$DLX_KNOWN_DEVICE to work with
! latest DECnet code.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 11-Jan-85 10:13:32, Edit by DAVENPORT
!
! Edit=112 NCPLIB:
! NMUT10: Remove undeclares of CMAND. UUO symbols as those
! conflicting with the COMND% JSYS have been redefined.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 19-Oct-84 14:47:42, Edit by DAVENPORT
!
! Edit=111 DTET10: Remove calls to NMU$SCHED_PAUSE in TRIGGER_ROM
! and ROM_DUMP routines. NMLDTL and NMLDLW depend
! on being uninterruptable during these operations
! so as to interlock against each other.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 16-Oct-84 09:40:45, Edit by DAVENPORT
!
! Edit=110 DTET10: Add code to OPEN_DTE_DEVICE to detect CPU not
! running and issue an appropriate error message.
! Change START_PROTOCOL to clear the DTE before
! trying to initialize protocol. Also tries four
! times before giving up.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 14-Sep-84 10:26:32, Edit by DAVENPORT
!
! Edit=107 NMUINT: Fix interrupt routines to correctly get the
! address where the interrupt PC is stored.
! NMLMRR: Fix routine LOOP_DATA to correctly allocate
! its loopback buffer.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 28-Aug-84 14:05:21, Edit by DAVENPORT
!
! Edit=106 NCPRSP: Fix NCP$DEQUEUE_RESPONSE routine to properly
! output CHANGE and ZERO responses.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 21-Aug-84 16:57:41, Edit by DAVENPORT
!
! Edit=105 NMLNIC: Add back code to NML$NICE_EXECUTE to set the NICE
! entity id length when expanding node entities.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 1-Aug-84 14:03:32, Edit by DAVENPORT
!
! Edit=104 NMUT10: [SPR 10-34808] Use QUEUE. WTO to send messages
! to OPR instead of using the TRMOP. UUO.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 31-Jul-84 9:34:02, Edit by DAVENPORT
!
! Edit=103 NCPTAB: Change extension of help file from MEM to HLP.
! NCPRSP:
! NMLEVD:
! NMLEVL:
! NMUNET:
! NMARCH: Update from latest TOPS-20 version.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 14-Jun-84 13:16:37, Edit by DAVENPORT
!
! Edit=102 STRLIB: Correct definition of CH$MOVSTRING macro.
! NETLIB: Fix NEXTF macro's checking of the field length.
! NMUINT: Add code to all interrupt routines to expect the
! second subroutine argument to be the address of
! the location where the interrupt PC is stored
! instead of using LEV1PC, LEV2PC, etc.
! NMUT10: Change interrupt level code to call all interrupt
! level routines with the second argument being the
! address where the interrupt PC is stored.
! NMUT20: Change interrupt level code to call all interrupt
! level routines with the second argument being the
! address where the interrupt PC is stored.
! NCPRSP: Change processing to use tabular output format
! for all output instead of only using tabular
! for output of multiple responses.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 8-Jun-84 13:32:10, Edit by DAVENPORT
!
! Edit=101 NMLEVL: Change code to filter remote events so that can
! filter events coming from the MCB. Add code to
! handle 1 byte vs 2 byte entity type from NTMAN
! UUO for DECnet III/IV compatability.
! NMLNIC: Default local area number for node addresses in
! incoming NICE messages.
! NMLVDB: Fix dot bug in code to handle return entity list.
!
! DSKT:NMUSKD.BLI[10,6026,NML703] 22-Feb-84 15:12:11, Edit by DAVENPORT
!
! Edit=100 Upgrade to Phase IV Network Management.
!
! DSKT:NMUSKD.BLI[10,6026,NMLBLI] 14-Jan-84 10:31:08, Edit by DAVENPORT
!
! Edit=57 Changes to GALAXY.R36 to use new versions of GLXMAC.R36
! and ORNMAC.R36. Changes to NCPLIB.REQ and NMUT10.R36 to
! use new version of UUOSYM.R36. Changes to NCPTAB.MAC and
! NCPCEX.B36 to change $DNxxx symbols to $KNxxx symbols to
! avoid conflicts with symbols in new UUOSYM.R36. Changes
! to NMUCOM.REQ and NMUFIL.B36 to allow compilation with
! BLISS version 4(215). Change to NMUT10.R36 to fix the
! CLOSE_LINK routine to wait for the synchronous disconnect
! to complete before releasing the link. Several changes
! to NCPTAB.MAC to fix parsing errors.
!
! DSKT:NMUSKD.BLI[10,6026,NML702] 26-Jan-83 09:44:23, Edit by DAVENPORT
!
! Edit=56 Changes to NMINI to create two NICE-LISTENER tasks.
!
! Edit=55 Change to NCPCEX to put back code to convert account strings,
! user strings, and password strings to upper case for the MCB.
!
! DSKC:NMUSKD.BLI[10,5665,SOURCE,TOPS10] 18-Nov-83 21:41:53, Edit by GROSSMAN
!
! Put copyright text into the .EXE file.
! Edit=47
!
!<MCINTEE.WORK>NMUSKD.BLI.2, 9-Aug-83 13:41:29, Edit by MCINTEE
!
! Ident 22. Change version number to 4.
!
!<MCINTEE.WORK>NMUSKD.BLI.4, 15-Jun-83 14:00:33, Edit by MCINTEE
!
! Ident 21. Merge changes from the -10 as of 15-JUN-83
!
!PH4:<BUILD>NMUSKD.BLI.4 4-Mar-83 17:40:54, Edit by GUNN
!
! Ident 20.
! Merge DECnet-10 changes as of approximately 11-OCT-82.
! Add line mistakenly deleted during merge of DECnet-10 and X25.
!
! <BRANDT.DEVELOPMENT>NMUSKD.BLI.1 22-Jun-82 15:50:31, Edit by BRANDT
!
! Ident 19.
! Clean up some problems introduced in last edit.
! 1) Have SCHED_FLAG unlock the semaphore when the event
! occurs only if no tasks are moved to run queue
! 2) Don't have SCHED_WAIT lock the semaphore when a task
! resumes.
! 3) Make sure TABLE_INDEX has a value when TABLE_DELETE is
! called.
! 4) When a task resumes after sleeping, use the table
! entry for the tasks queued to this event to determine
! if the event has happened or if the sleep time has expired.
!
! <BRANDT.DEVELOPMENT>NMUSKD.BLI.1 25-May-82 12:05:13, Edit by BRANDT
!
! Ident 18.
! Make network function timeouts work.
! 1) In NMU$SCHED_WAIT make calls to SCHED_SLEEP if a wait time
! is specified.
! 2) Remove routine NMU$TIMEOUT_CHECK.
! 3) Always have SCHED_FLAG unlock the semaphore when the event
! occurs
! NET:<PECKHAM.DEVELOPMENT>NMUSKD.BLI.2 22-Apr-82 09:50:31, Edit by PECKHAM
!
! Ident 17.
! Make stack sizes larger for TOPS10/20 in NMU$SCHED_CREATE.
!
! NET:<GROSSMAN.NML-SOURCES>NMUSKD.BLI.3 24-Feb-82 10:24:00, Edit by GROSSMAN
!
! Make NMU$SCHED_DESCHEDULE put NML to sleep forever if it has nothing to do.
! This is for Tops-10 only.
!
! NET:<GROSSMAN>NMUSKD.BLI.2 16-Feb-82 15:16:52, Edit by GROSSMAN
!
! Make NMU$SCHED_FLAG call the table deallocator after it is done reading
! all the tasks from the event block. This should prevent some free space
! lossage problems.
!
! NET:<GROSSMAN.NML-SOURCES>NMUSKD.BLI.4 13-Feb-82 22:54:00, Edit by GROSSMAN
!
! Remove EXTERNAL ROUTINE of DETACH from this file. Put it into the macro
! INIT_GLOBALS in NMINI.REQ. Also change the name of the second formal
! parameter (WAIT) for the routine NMU$TIMEOUT_CHECK to WAIT_FLAG. This is
! to avoid conflict with a Tops-10 monitor call of the same name. (Oddly
! enough, the parameter is never used!?!).
!
! NET:<PECKHAM.DEVELOPMENT>NMUSKD.BLI.2 7-Feb-82 18:21:00, Edit by PECKHAM
!
! Ident 16.
! Fix code in NMU$SCHED_WAIT to avoid generating INFO message.
!
! NET:<PECKHAM.DEVELOPMENT>NMUSKD.BLI.2 5-Feb-82 09:11:11, Edit by GROSSMAN
! for PECKHAM
! Ident 15.
! Initialize RUN_QUEUE (its really just a table now). And, fix ..._EVENT so
! that the resetting of an EVENT_QUEUE (which is really a table) calls
! NMU$TABLE_CLEAR which will collect its own garbage thus alleviating some
! memory problems.
!
! NET:<GROSSMAN>NMUSKD.BLI.11 26-Jan-82 06:42:16, Edit by GROSSMAN
!
! Ident 14.
! Install many changes so that counter timers work. Some of them are:
! 1) Make all events not use a queued data structure. They now use a list
! in order to pointer to all waiting tasks.
! 2) Turn the RUN_QUEUE into a run_list. It is now a list of all runnable
! tasks. This keep it from interfering with the TIME_QUEUE.
! 3) Make NMU$SCHED_SLEEP accept the same task multiple times. (It actually
! just does nothing if the task is already scheduled to be woken up later).
! I hope thats all...
!
! NET:<PECKHAM.DEVELOPMENT>NMUSKD.BLI.2 23-Jan-82 23:48:34, Edit by PECKHAM
!
! Ident 13.
! Fix ref bug in NMU$TIMEOUT_CHECK.
! Comment out call to NMU$TIMEOUT_CHECK in NMU$SCHED_DESCHEDULE.
!
! NET:<DECNET20-V3P1.NMLLIB>NMUSKD.BLI 02-Dec-81 09:49:20, Edit by THIGPEN
!
! Ident 12.
! Merge changes made by Stu Grossman (see below) with changes in ident 11.
!
! NET:<DECNET20-V3P1.NMLLIB>NMUSKD.BLI 02-Dec-81 09:49:20, Edit by THIGPEN
!
! Ident 11.
! Changes to allow timing out calls to NMU$SCHED_WAIT:
! Add routine NMU$TIMEOUT_CHECK
! Change NMU$SCHED_WAIT and NMU$SCHED_DESCHEDULE
! Change calls to NMU$SCHED_WAIT in NMU$SQUEUE_REMOVE, NMU$QQUEUE_INSERT,
! and SCHEDULER_TASK.
!
! NET:<GROSSMAN>NMUSKD.BLI.2 8-Dec-81 17:17:47, Edit by GROSSMAN
!
! Install a call to DETACH if we're running under Tops-10. This should be the
! first thing done in the program, because there are probably several things
! waiting to for us to get off the Force Line.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUSKD.BLI.44 2-Oct-81 15:06:29, Edit by GUNN
!
! Ident 10.
! Change NML version number to 3.0.0 from 2.1.0.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUSKD.BLI.42 12-Aug-81 10:43:40, Edit by JENNESS
!
! Ident 09.
! Add NMU$QQUEUE_EXTRACT routine. Needed to handle REMOTE/LOCAL NML
! request queues.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUSKD.BLI.41 6-Aug-81 13:46:31, Edit by JENNESS
!
! Add routine NMU$SCHED_ERROR. Change NMU$SCHED_COMPLETE to look at
! the error message stored in the task block only. NMU$SCHED_ERROR
! puts the supplied error message in the task block error buffer and
! then calls NMU$SCHED_COMPLETE. (Makes panic interrupts easier).
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUSKD.BLI.40 5-Aug-81 15:26:20, Edit by JENNESS
!
! Fix ch$movasciz call in NMU$SCHED_COMPLETE so that it has the
! correct arguments (addresses instead of immediate pointers).
!
! NET:<DECNET20-V3P1.NMU.LIBRARY>NMUSKD.BLI.2 30-Jun-81 10:36:28, Edit by JENNESS
! Make TIMEOUT_SIGNAL clear TIME_OUT. This solves multiple tasks
! waiting for timeout race problem.
!
!NET:<DECNET20-V3P1.NMU>NMUSKD.BLI.2 16-Jun-81 13:21:51, Edit by JENNESS
!
! Readability improvements. Add TB_ERROR_PC to task block for recording
! PC of exception failures.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.MCB>NMUSKD.BLI.1 10-Jun-81 09:37:45, Edit by SROBINSON
!
! Add Quota Queue Support
!
!<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUSKD.BLI.31 23-Mar-81 11:17:02, Edit by SROBINSON
!
! Fix NMU$SCHED_EVENT to set event block EB_NOINT flags correctly
!
!NET:<DECNET20-V3P1.NMU>NMUSKD.BLI.42 14-Mar-81 15:15:38, Edit by JENNESS
!
! Add trace code for debugging.
!
!<DECNET20-V3P1.BASELEVEL-2.MCB>NMUSKD.BLI.2 13-Mar-81 14:32:46, Edit by SROBINSON
! Fix NMU$SCHED_FLAG to clear out the queue on any EVENT
module NMUSKD ( ! Scheduler
ident = 'X00.22',
main = TOPMOST,
version = '4(146)',
environment (stack = TOPMOST_STACK)
) =
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 scheduling code for multi-tasking.
! The main routine (start) for any program using this scheduler
! is contained here also.
!
! Scheduling is done on two entities:
!
! (1) Queues when a queue becomes non-empty all
! tasks waiting are scheduled.
!
! (2) Events when an event occurs the first task waiting for
! the event is scheduled.
!
!
! Environment: TOPS10 and TOPS20 user mode, MCB RSX task mode
!
! Author: Steven M. Jenness, Creation date: 20 August 1980
!
!--
!
! Include files
!
library 'NMULIB'; ! All needed definitions
%if $TOPS20
%then
library 'MONSYM'; ! Monitor symbols
library 'JLNKG'; ! JSYS linkage definitions
%fi
!
! Global routines
!
forward routine
NMU$SCHED_MANAGER; ! Global entry definitions
!
! Local routines
!
forward routine
TOPMOST : novalue, ! Starting routine
GET_NEXT_TASK, ! Empty RUN_QUEUE
MAKE_TASK_RUNNABLE : novalue, ! Fill up RUN_QUEUE
SCHEDULER_TASK : novalue, ! Scheduler task co-routine
TIMEOUT_SIGNAL : TIMER_INTERRUPT_LINKAGE novalue, ! Signal SKD_EVENT
TT_SCAN; ! Scan TIME_QUEUE
!
! Global literals
!
global literal
%name ('TB.SKD') = %fieldexpand (TB_SCHED_QUEUE, 0) * %UPVAL,
%name ('TB.QUE') = %fieldexpand (TB_TASK_QUEUE, 0) * %UPVAL,
%name ('TB.STR') = %fieldexpand (TB_START, 0) * %UPVAL,
%name ('TB.ABT') = %fieldexpand (TB_ABORT, 0) * %UPVAL,
%name ('TB.RSC') = %fieldexpand (TB_RESOURCE, 0) * %UPVAL,
%name ('TB.ERR') = %fieldexpand (TB_ERROR_PC, 0) * %UPVAL,
%name ('TB.NAM') = %fieldexpand (TB_NAME, 0) * %UPVAL,
%if $TOPS10 or $TOPS20
%then
%name ('TB.BUF') = %fieldexpand (TB_ERROR_BUFFER, 0) * %UPVAL,
%fi
%name ('TB.EVW') = %fieldexpand (TB_EVENT_WAIT, 0) * %UPVAL,
%name ('TB.SEM') = %fieldexpand (TB_SEMAPHORE, 0) * %UPVAL,
%name ('TB.TIM') = %fieldexpand (TB_TIME, 0) * %UPVAL,
%name ('TB.CTX') = %fieldexpand (TB_CONTEXT, 0) * %UPVAL,
%name ('TB.STK') = %fieldexpand (TB_STACK, 0) * %UPVAL;
!
! Own storage
!
!
! Make something have an initial value so $OWN$ PSECT for NMUSKD
! shows up in TKB36 map.
!
literal
STACK_LENGTH = 300,
RUN_QUEUE_SIZE = 50; ! Max number of concurrently running
! tasks
own
COPYRIGHT : vector [20]
initial (%asciz 'COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION, 1984, 1986. ALL RIGHTS RESERVED.'),
TOPMOST_STACK : vector [STACK_LENGTH], ! Use this stack
RUN_QUEUE : vector [RUN_QUEUE_SIZE],! Queue of runnable tasks
NEXT_RUNNABLE_TASK : initial (-1), ! Points into RUN_QUEUE
LAST_RUNNABLE_TASK : initial (-1), ! Last runnable task pointer
TASK_QUEUE : Q_HEADER, ! Queue of all tasks
SKD_EVENT : EVENT_BLOCK, ! Event for scheduler wakeup
SKD_TASK : ref TASK_BLOCK, ! Task block for scheduler
TIME_OUT : TIME_BLOCK;
global
TIME_QUEUE : Q_HEADER, ! Queue of tasks waiting for timeouts
NMLVER : initial (4),
DECECO : initial (0),
USRECO : initial (0);
%master_debug_data_base; ! Debugging data base
!
! Structures
!
! Timer queue scanning data block
!
$field
TQUEUE_SCAN_FIELDS =
set
TT_NOW = [$sub_block (TIME_BLOCK_SIZE)], ! Current time
TT_TIME = [$sub_block (TIME_BLOCK_SIZE)] ! Least of wakeup times found
tes;
literal
TQUEUE_SCAN_SIZE = $field_set_size;
macro
TIMER_SCAN_BLOCK = block [TQUEUE_SCAN_SIZE] field (TQUEUE_SCAN_FIELDS) %;
!
! External references
!
external
CURTSK; ! Current task pointer
external routine
NMU$TABLE_ROUTINES, ! Table manipulation routines
NMU$QUEUE_MANAGER, ! Queue manager routines
NMU$MEMORY_MANAGER, ! Memory management routines
INIT_GLOBALS; ! Other global routines for
! initialization
%routine ('TOPMOST') : novalue =
!++
! Functional description:
!
! This is the "main" routine for the program using this
! scheduler.
!
! It initializes the memory management system, scheduler and
! any other system that requires initialization (defined in
! NMINI.REQ).
!
!
! Note that interlocks need to be developed to allow multi-streaming
! of initialization code.
!
!--
begin
!
! Detach the job from the Force Line if necessary. (Tops-10 only)
!
%if $TOPS10 %then DETACH (); %fi
!
! Run SYS:NML702.EXE if under 7.02 monitor.
!
%if $TOPS10 %then NMLCHK (); %fi
!
! Setup the debugging data base (if needed)
!
%debug_setup;
!
! Reset memory manager
!
NMU$MEMORY_RESET ();
NMU$MEMORY_INITIALIZE (BASIC_MEMORY);
!
! Reset the scheduler.
!
! Reset master task queue and queue of runnable tasks.
!
NMU$QUEUE_RESET (TASK_QUEUE);
!
! Create null task using the current stack.
!
NMU$QUEUE_RESET (TIME_QUEUE);
NMU$SCHED_EVENT (SKD_EVENT, $true);
SKD_TASK = NMU$MEMORY_GET (TASK_BLOCK_ALLOCATION);
CURTSK = .SKD_TASK;
begin
local
TASK_NAME_POINTER, NAME_LITERAL;
TASK_NAME_POINTER = ch$ptr (SKD_TASK [TB_NAME]);
NAME_LITERAL = ch$asciz ('SCHEDULER');
ch$movasciz (TASK_NAME_POINTER, .NAME_LITERAL);
end;
!
! Initialize all other systems.
!
MASTER_INITIALIZATION;
!
! Start scheduling by calling scheduler co-routine
!
SCHEDULER_TASK ();
!
! If return here ... NML has crashed.
!
end; ! End of TOPMOST
%global_routine ('NMU$SCHED_CREATE', CODE, STACK_SIZE, ABORT_RTN, NAME_PTR) =
!++
! Functional description:
!
! This routine allocates a task state block and sets the task
! up for execution. The code specified is started when the
! task comes up in the runnable task queue.
!
! Formal parameters:
!
! .CODE Address of routine to execute as the task
! .STACK_SIZE Number of fullwords to allocate for stack
! .ABORT_RTN Address of a routine to call when the task
! is aborted
! .NAME_PTR Byte pointer to a ASCIZ task name string
!
! Routine value:
!
! The returned value is the address of the task's state
! block. This value is used whenever the task is to
! be affected by such routines as NMU$SCHED_ABORT.
!
! Side effects:
!
! The runnable task queue gets another task.
!
!--
begin
local
TASK : ref TASK_BLOCK,
TASK_NAME;
%debug (SCHEDULER_TRACE, (TRACE_INFO ('Creating %A (%O)', .NAME_PTR, .CODE)));
%if $TOPS10 or $TOPS20
%then
STACK_SIZE = .STACK_SIZE*2;
%fi
!
! Get memory for a task block
!
TASK = NMU$MEMORY_GET (TASK_BLOCK_ALLOCATION + (.STACK_SIZE*%upval));
!
! Initialize start address, error routine, task name and
! stack.
!
TASK [TB_START] = .CODE;
TASK_INITIALIZE (.TASK, .STACK_SIZE);
TASK [TB_ABORT] = .ABORT_RTN;
TASK_NAME = ch$ptr (TASK [TB_NAME]);
ch$movasciz (TASK_NAME, .NAME_PTR);
!
! Insert entry into master task queue and
! runnable task queue.
!
NMU$QUEUE_INSERT (TASK_QUEUE, TASK [TB_TASK_QUEUE]);
MAKE_TASK_RUNNABLE (TASK [TB_SCHED_QUEUE]);
!
! Return address of the task block.
!
.TASK
end; ! End of NMU$SCHED_CREATE
%global_routine ('NMU$SCHED_ABORT', TASK : ref TASK_BLOCK) : novalue =
!++
! Functional description:
!
! This routine aborts a task and calls it's clean up routine.
!
! Formal parameters:
!
! .TASK Address of task block for task to abort.
!
! Routine value: none
! Side effects:
!
! The specified task will be aborted, it's cleanup routine
! will be called (if it exists) and all traces of the task
! will disappear.
!
!--
begin
bind routine
A_ROUTINE = .TASK [TB_ABORT]; ! Abort routine address
%debug (SCHEDULER_TRACE, (TRACE_INFO ('Aborting task %A (%O)',
ch$ptr (TASK [TB_NAME]), .TASK)));
if A_ROUTINE neq 0 then A_ROUTINE (.TASK);
!*****
! If task is completely aborted ... delete the task and resources
!*****
end; ! End of NMU$SCHED_ABORT
%global_routine ('NMU$SCHED_FINI') : novalue =
!++
! Functional description:
!
! This routine is called whenever a task "exits". This means
! that the routine comprising the main routine of the task
! attempts to return.
!
! Formal parameters: none
!
! Routine value: none
! Side effects:
!
!--
begin
TASK_INFO ('Task has exited');
NMU$SCHED_DESCHEDULE ();
end; ! End of NMU$SCHED_FINI
%global_routine ('NMU$SCHED_ERROR', ERROR_PTR) : novalue =
!++
! Functional description:
!
! This routine is called in a task's context to abnormally
! complete it's execution. It puts the supplied error message
! into the task's task block error buffer and then calls
! NMU$SCHED_COMPLETE to abort the task.
!
! Formal parameters:
!
! .ERROR_PTR Pointer to ASCIZ string to be put into the
! task block error buffer.
!
! Routine value: none
! Side effects: none
!
!--
begin
%if not $MCB
%then
local
TASK : ref TASK_BLOCK,
TB_POINTER;
TASK = CURRENT_TASK;
TB_POINTER = ch$ptr (TASK [TB_ERROR_BUFFER]);
if .ERROR_PTR neq 0
then ch$movasciz (TB_POINTER, .ERROR_PTR);
%fi
NMU$SCHED_COMPLETE ();
end; ! End of NMU$SCHED_ERROR
%global_routine ('NMU$SCHED_COMPLETE') : novalue =
!++
! Functional description:
!
! This routine is called in a task's context to abnormally
! complete it's execution. It outputs the message that is
! stored in the task block's error buffer, aborts the task
! and deschedules it forever.
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--
begin
local
TASK : ref TASK_BLOCK;
TASK = CURRENT_TASK;
%if not $MCB
%then
TASK_INFO (ch$ptr (TASK [TB_ERROR_BUFFER]));
%fi
%if $TOPS10 %then STOP_PROGRAM; %fi ! Stop NML right now
%if $TOPS20 %then STOP_PROGRAM; %fi ! Stop NML right now
NMU$SCHED_ABORT (.TASK);
NMU$SCHED_DESCHEDULE ();
end; ! End of NMU$SCHED_COMPLETE
%global_routine ('NMU$SQUEUE_RESET', QUEUE : ref SQ_HEADER) : novalue =
!++
! Functional description:
!
! This routine resets a "scheduling" type queue. Any queue
! that can have scheduling done on it contains extra information
! in the queue header that should be reset any time the queue
! is reset.
!
! Formal parameters:
!
! .QUEUE Address of queue header
!
! Routine value: none
! Side effects:
!
! Any entries on the queue are lost
! Any tasks that are waiting on this queue have
! their entries on the task wait list deleted.
!
!--
begin
!
! Reset data queue.
!
NMU$QUEUE_RESET (QUEUE [Q_QUEUE]);
!
! Reset queue non-empty event.
! Don't allow SQUEUE operations at interrupt level.
!
NMU$SCHED_EVENT (QUEUE [Q_EVENT], $false);
end; ! End of NMU$SQUEUE_RESET
%global_routine ('NMU$SQUEUE_INSERT', QUEUE : ref SQ_HEADER, ENTRY) : novalue =
!++
! Functional description:
!
! This routine inserts an entry into a queue. If a task is
! waiting for this queue to become non-empty, it is scheduled
! for execution.
!
! Formal parameters:
!
! .QUEUE Address of a queue header block
! .ENTRY Address of a entry to be inserted to queue
!
! Routine value: none
! Side effects:
!
! If the queue becomes non-empty the queue of tasks waiting
! for this to happen is checked. If a task is waiting, it
! is put onto the queue of runnable tasks.
!
!--
begin
NMU$QUEUE_INSERT (QUEUE [Q_QUEUE], .ENTRY);
NMU$SCHED_FLAG (QUEUE [Q_EVENT]);
end; ! End of NMU$SQUEUE_INSERT
%global_routine ('NMU$SQUEUE_REMOVE', QUEUE : ref SQ_HEADER) =
!++
! Functional description:
!
! This routine removes an entry from a queue. If the queue
! is empty, the calling task is descheduled and a new task
! is selected for running. If no task is runnable, the null
! task is executed.
!
! Formal parameters:
!
! .QUEUE Address of a queue header block
!
! Routine value:
!
! Address of entry from queue
!
! Side effects: none
!
!--
begin
local
ENTRY;
while (ENTRY = NMU$QUEUE_REMOVE (QUEUE [Q_QUEUE])) eql 0 do
NMU$SCHED_WAIT (QUEUE [Q_EVENT],0);
.ENTRY
end; ! End of NMU$SQUEUE_REMOVE
%global_routine ('NMU$QQUEUE_RESET', QUEUE : ref QQ_HEADER, QUOTA) : novalue =
!++
! Functional description:
!
! This routine resets a "quota scheduling" type queue. Any queue
! that can have scheduling done on it contains extra information
! in the queue header that should be reset any time the queue
! is reset.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .QUOTA Number of Entries in queue before insert waits
!
! Routine value: none
! Side effects:
!
! Any entries on the queue are lost
! Any tasks that are waiting on this queue have
! their entries on the task wait list deleted.
!
!--
begin
!
! Reset the scheduler queue portion of this entry.
!
NMU$SQUEUE_RESET (QUEUE [QQ_SQUEUE]);
!
! Reset insert queue resume event.
! Don't allow SQUEUE operations at interrupt level.
!
NMU$SCHED_EVENT (QUEUE [QQ_IEVENT], $false);
QUEUE [QQ_QUOTA] = .QUOTA;
QUEUE [QQ_CURRENT] = 0;
end; ! End of NMU$QQUEUE_RESET
%global_routine ('NMU$QQUEUE_INSERT', QUEUE : ref QQ_HEADER, ENTRY) : novalue =
!++
! Functional description:
!
! This routine inserts an entry into a queue. If a task is
! waiting for this queue to become non-empty, it is scheduled
! for execution. If this insert would exceed the insert quota
! the current task is suspended.
!
! Formal parameters:
!
! .QUEUE Address of a queue header block
! .ENTRY Address of a entry to be inserted to queue
!
! Routine value: none
! Side effects:
!
! If the queue becomes non-empty the queue of tasks waiting
! for this to happen is checked. If a task is waiting, it
! is put onto the queue of runnable tasks.
!
!--
begin
while .QUEUE [QQ_CURRENT] geq .QUEUE [QQ_QUOTA]
do NMU$SCHED_WAIT (QUEUE [QQ_IEVENT],0);
QUEUE [QQ_CURRENT] = .QUEUE [QQ_CURRENT] + 1;
NMU$SQUEUE_INSERT (QUEUE [QQ_SQUEUE], .ENTRY);
end; ! End of NMU$QQUEUE_INSERT
%global_routine ('NMU$QQUEUE_REMOVE', QUEUE : ref QQ_HEADER) =
!++
! Functional description:
!
! This routine removes an entry from a queue. If the queue
! is empty, the calling task is descheduled and a new task
! is selected for running. If no task is runnable, the null
! task is executed. When a remove has dropped the number of
! queue entries to less than the quota the queue inserter is
! resumed.
!
! Formal parameters:
!
! .QUEUE Address of a queue header block
!
! Routine value:
!
! Address of entry from queue
!
! Side effects: none
!
!--
begin
local
ENTRY;
ENTRY = NMU$SQUEUE_REMOVE (QUEUE [QQ_SQUEUE]);
QUEUE [QQ_CURRENT] = .QUEUE [QQ_CURRENT] - 1;
if .QUEUE [QQ_CURRENT] lss .QUEUE [QQ_QUOTA]
then NMU$SCHED_FLAG ( QUEUE [QQ_IEVENT]);
.ENTRY
end; ! End of NMU$QQUEUE_REMOVE
%global_routine ('NMU$QQUEUE_EXTRACT', QUEUE : ref QQ_HEADER, ENTRY) =
!++
! Functional description:
!
! This routine removes an explicit entry from a queue. The
! quota for the queue is adjusted to reflect the entry's
! extraction.
!
! Formal parameters:
!
! .QUEUE Address of a queue header block
! .ENTRY Address of entry on queue
!
! Routine value:
!
! $true Entry was found on the queue and extracted
! $false Entry was not found on the queue
!
! Side effects: none
!
!--
begin
if NMU$QUEUE_EXTRACT (QUEUE [QQ_SQUEUE], .ENTRY)
then
begin
QUEUE [QQ_CURRENT] = .QUEUE [QQ_CURRENT] - 1;
$true
end
else
$false
end; ! End of NMU$QQUEUE_EXTRACT
%global_routine ('NMU$SCHED_EVENT', EVENT : ref EVENT_BLOCK, INT_OFF) : novalue =
!++
! Functional description:
!
! This routine resets the data base associated with a
! particular event.
!
! Formal parameters:
!
! .EVENT Address of event block (EVENT_BLOCK)
! .INT_OFF Boolean flag indicating if interrupts
! are to be turned off when this event
! is being signalled. (i.e. this flag is
! $true if the event can be signalled from
! interrupt level.)
!
! Routine value: none
! Side effects:
!
! The queue of tasks waiting for the event is cleared.
! The count of event occurances is cleared.
!
!--
begin
%debug (EVENT_TRACE, (TRACE_INFO ('Event reset (%O)', .EVENT)));
!
! Reset queue of tasks waiting for this event.
!
NMU$TABLE_CLEAR (EVENT [EB_TASKS]);
! EVENT [EB_TASKS] = 0;
!
! Lock the event semaphore, indicating is hasn't
! happened yet.
!
!
! LOCK (EVENT [EB_SEMAPHORE]);
EVENT [EB_SEMAPHORE] = $false;
!
! Set the interrupt suppression flag (if event
! can be signalled from interrupt level.
!
EVENT [EB_NOINT] = .INT_OFF;
end; ! End of NMU$SCHED_EVENT
%global_routine ('NMU$SCHED_FLAG', EVENT : ref EVENT_BLOCK) : novalue =
!++
! Functional description:
!
! This routine flags an "event" occurance. Any task that
! is waiting for the event will be put onto the RUNNABLE
! task queue.
!
! Formal parameters:
!
! .EVENT Address of selected event queue header
!
! Routine value: none
! Side effects:
!
! Tasks may be put onto the runnable queue.
! The queue associated with the EVENT will be emptied.
!
!--
begin
local
TASK : ref TASK_BLOCK;
%debug (EVENT_TRACE, (TRACE_INFO ('Event flagged (%O)', .EVENT)));
!
! If can be flagged from interrupt level .. turn
! interrupts off for a moment.
!
if .EVENT [EB_NOINT] then INTERRUPT_OFF;
!
! Signal that the event has happened by either
! scheduling the next task queued to the event
! or unlocking the semaphore if no task is ready
! for the event.
!
TASK = 0;
incr INDEX from 1 to NMU$TABLE_MAX (EVENT [EB_TASKS]) do
if NMU$TABLE_FETCH (EVENT [EB_TASKS], .INDEX, TASK) then
begin
MAKE_TASK_RUNNABLE (TASK [TB_SCHED_QUEUE]);
NMU$TABLE_DELETE (EVENT [EB_TASKS], .INDEX);
end;
!
! Now we clear the table pointed to by the event block, so that people who
! just deallocate the block without calling NMU$SCHED_EVENT, won't make us lose
! the memory taken up by the table. (At this point all of the useful info in
! the table has been extracted.)
!
NMU$TABLE_CLEAR (EVENT [EB_TASKS]);
EVENT [EB_SEMAPHORE] = $true;
!
! Turn interrupts back on if they were
! turned off.
!
if .EVENT [EB_NOINT] then INTERRUPT_ON;
!
! If we can be called at interrupt level, issue a PROCESS_WAKE in case this
! interrupt occurred between the time _DESCHEDULE checked the RUN_QUEUE, and
! the time it does a PROCESS_SLEEP. This will nullify the PROCESS_SLEEP.
!
if .EVENT [EB_NOINT] then PROCESS_WAKE;
end; ! End of NMU$SCHED_FLAG
%global_routine ('NMU$SCHED_WAIT', EVENT: ref EVENT_BLOCK, SECONDS) : =
!++
! Functional description:
!
! This routine blocks a process until it is woken up on
! any event (or queue non-empty) that it is waiting for,
! or until the timeout interval (if specified) passes.
!
! Formal parameters:
!
! .EVENT Address of event block on which to wait
! SECONDS Number of seconds to wait before timing out
!
! Routine value: $true if the awaited event happened or if no timeout requested
! $false if it timed out
! Side effects: none
!
!--
begin
local
TASK : ref TASK_BLOCK,
TABLE_INDEX,
EVENT_OCCURRED;
%debug (EVENT_TRACE, (TRACE_INFO ('Event wait (%O)', .EVENT)));
!
! Turn the interrupts off if this event
! can be signalled from interrupt level.
!
if .EVENT [EB_NOINT] then INTERRUPT_OFF;
!
! Test for the event having occured already.
! Deschedule the task if not. Turn the
! interrupts on in any case.
!
! EVENT_OCCURRED = LOCK (EVENT [EB_SEMAPHORE]);
EVENT_OCCURRED = .EVENT [EB_SEMAPHORE];
EVENT [EB_SEMAPHORE] = $false; ! Reset the flag after reading it
if not .EVENT_OCCURRED ! If event has not yet occurred,
then ! add current task to task list
begin ! for this event.
TABLE_INDEX = NMU$TABLE_INSERT (EVENT [EB_TASKS], CURRENT_TASK);
if .EVENT [EB_NOINT] then INTERRUPT_ON; ! Enable interrupts
if .SECONDS eql 0 ! If no time specified,
then ! just suspend task.
begin
NMU$SCHED_DESCHEDULE (); ! When task resumes...
return $true ! Return
end
else ! If a wait time was specified,
NMU$SCHED_SLEEP (.SECONDS); ! suspend task by sleeping.
!
! Task will resume here if sleep time expires or event occurs.
! If it timed out, task needs to be removed from event task
! list; if event occurred, task needs to be removed from
! TIME_QUEUE. We try to do both -- no ill side effects.
!
if .EVENT [EB_NOINT] then INTERRUPT_OFF; ! Interrupts off again
! EVENT_OCCURRED = LOCK (EVENT [EB_SEMAPHORE]);
EVENT_OCCURRED = .EVENT [EB_SEMAPHORE];
EVENT [EB_SEMAPHORE] = $false; ! Reset the event flag after reading
NMU$TABLE_DELETE (EVENT [EB_TASKS], .TABLE_INDEX);
TASK = CURRENT_TASK;
NMU$QUEUE_EXTRACT(TIME_QUEUE, TASK [TB_SCHED_QUEUE]);
if .EVENT [EB_NOINT] then INTERRUPT_ON;
return .EVENT_OCCURRED
end;
if .EVENT [EB_NOINT] then INTERRUPT_ON;
$true
end; ! End of NMU$SCHED_WAIT
%global_routine ('NMU$SCHED_DESCHEDULE') : novalue =
!++
! Functional description:
!
! This routine deschedules the currently running task. It checks
! to see if any tasks waiting for events have timed out, and causes
! their events to be flagged if so (see NMU$TIMEOUT_CHECK).
! If no other task wants to run, the null task is run.
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--
begin
local
TASK : ref TASK_BLOCK;
TASK = 0;
!
! Wait until a task is found and scheduled
!
while .TASK eql 0
do
begin
!
! Turn interrupts off so that the scheduler is not
! interrupted while working on the run queue.
!
INTERRUPT_OFF;
!
! Get the next entry from the run queue.
!
TASK = GET_NEXT_TASK ();
!
! Turn the interrupts back on now.
!
INTERRUPT_ON;
!
! Switch context to either the new task (if
! one was removed from the queue or the the
! null task.
!
if .TASK neq 0
then
if .TASK neq CURRENT_TASK
then
begin
%debug (SCHEDULER_TRACE,
(TRACE_INFO ('Switch to (%O) %A',
.TASK, ch$ptr (TASK [TB_NAME]))));
CONTEXT_SWITCH (.TASK);
end
else
begin
%debug (SCHEDULER_TRACE,
(TRACE_INFO ('Continuing current task')));
1;
end
else
begin
%debug (SCHEDULER_TRACE,
(TRACE_INFO ('No runnable task .. sleeping')));
%if not $TOPS10 %then PROCESS_SLEEP (60);
%else PROCESS_SLEEP (0); %fi
%debug (SCHEDULER_TRACE,
(TRACE_INFO ('Program woken up')));
end;
end;
!
! When context switched back to this task...
! this routine will return.
!
end; ! End of NMU$SCHED_DESCHEDULE
%global_routine ('NMU$SCHED_PAUSE') : novalue =
!++
!
! Functional description:
!
! This routine will put the currently running task at the end of the
! RUN_QUEUE, and then deschedule. It's purpose is to allow tasks that
! take a long time to be interrupted. This call should be placed at
! strategic, frequently executed points in the task, such as after
! executing a monitor call that blocks for a while.
!
! In essence, this routine will make the current task be the last task
! to be executed in the RUN_QUEUE. Other tasks are installed by
! interrupt level, or by other tasks, and they will all take precedence
! over the current task, if they were on the RUN_QUEUE already.
!
!--
begin
if .NEXT_RUNNABLE_TASK eql .LAST_RUNNABLE_TASK then return;
MAKE_TASK_RUNNABLE (CURRENT_TASK);
NMU$SCHED_DESCHEDULE ();
end; ! End of NMU$SCHED_PAUSE
%global_routine ('NMU$SCHED_SLEEP', TIME) : novalue =
!++
! Functional description:
!
! This routine is called by any task that wishes to go
! to sleep for a short while. The task will block until
! the specified number of seconds elapses.
!
! Formal parameters:
!
! .TIME Number of seconds to wait.
!
! Routine value: none
! Side effects: none
!
!--
begin
local
TASK : ref TASK_BLOCK;
%debug (SCHEDULER_TRACE, (TRACE_INFO ('Task sleeping for %D seconds', .TIME)));
!
! Get address of currently running task's task block.
!
TASK = CURRENT_TASK;
!
! Set the time to wake this task up, clear the wakeup
! event and queue it to the time wakeup queue.
!
TIME_CURRENT (.TIME, TASK [TB_TIME]);
!First extract the item from the queu if it was in there already. This will
!insure that an item never get in there twice.
NMU$QUEUE_EXTRACT(TIME_QUEUE, TASK [TB_SCHED_QUEUE]);
NMU$QUEUE_INSERT (TIME_QUEUE, TASK [TB_SCHED_QUEUE]);
!
! Signal to the TIMER TASK that someone has modified it's
! data base. Then wait for the TIMER TASK to put this task
! back onto the run queue.
!
NMU$SCHED_FLAG (SKD_EVENT);
NMU$SCHED_DESCHEDULE ();
%debug (SCHEDULER_TRACE,
(TRACE_INFO ('Task woken up')));
end; ! End of NMU$SCHED_SLEEP
%routine ('GET_NEXT_TASK') =
!++
!
! Functional description:
!
! This routine will remove the first runnable task from the runnable
! task queue. First, it will check to see if NEXT_RUNNABLE_TASK and
! LAST_RUNNABLE_TASK point to the same vector entry. If so, then the
! queue is empty. Otherwise, we increment NEXT_RUNNABLE_TASK, and
! get that item out of the runnable task vector.
!
! Routine value:
!
! Zero if there are no runnable tasks.
! Otherwise, the address of the task block.
!
!--
begin
local
VALUE;
if .NEXT_RUNNABLE_TASK eql .LAST_RUNNABLE_TASK then return 0;
INTERRUPT_OFF;
NEXT_RUNNABLE_TASK = (.NEXT_RUNNABLE_TASK + 1) mod RUN_QUEUE_SIZE;
VALUE = .RUN_QUEUE [.NEXT_RUNNABLE_TASK];
INTERRUPT_ON;
.VALUE
end; ! End of GET_NEXT_TASK
%routine ('MAKE_TASK_RUNNABLE', TASK) : novalue =
!++
!
! Functional description:
!
! This routine will install the specified task on the RUN_QUEUE.
! The task will be put at the end of the RUN_QUEUE, so that it will
! be run after all currently waiting tasks. This causes round robin
! type scheduling to occur.
!
! It works by incrementing LAST_RUNNABLE_TASK so that it points at
! a new entry in RUN_QUEUE. If (after incrementing) the LAST_RUNNABLE_
! TASK pointer is equal to the NEXT_RUNNABLE_TASK pointer, we stopcode.
!
! Formal parameters:
!
! TASK Address of task to be installed on RUN_QUEUE.
!
!--
begin
INTERRUPT_OFF;
LAST_RUNNABLE_TASK = (.LAST_RUNNABLE_TASK + 1) mod RUN_QUEUE_SIZE;
if .LAST_RUNNABLE_TASK eql .NEXT_RUNNABLE_TASK then
TASK_ERROR ('Run queue overflowed in MAKE_TASK_RUNNABLE');
RUN_QUEUE [.LAST_RUNNABLE_TASK] = .TASK;
INTERRUPT_ON;
end; ! End of MAKE_TASK_RUNNABLE
%routine ('SCHEDULER_TASK') : novalue =
!++
! Functional description:
!
! This task handles timeouts for other tasks. Other
! tasks queue themselves to this task to be woken up
! after the time specified in the TIME_OUT block in
! their respective task blocks.
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--
begin
local
TT_SBLK : TIMER_SCAN_BLOCK;
!
! Flag that no time out interrupt is currently defined.
!
TIME_SET_NULL (TIME_OUT);
!
! Loop doing this task's work forever.
!
while $true do
begin
!
! Get current time.
!
TIME_CURRENT (0, TT_SBLK [TT_NOW]);
TIME_SET_NULL (TT_SBLK [TT_TIME]);
!
! Scan timer queue, scheduling any task that needs
! to be scheduled. Also find the next time to have
! a time out interrupt generated.
!
NMU$QUEUE_SCAN (TIME_QUEUE, TT_SBLK, TT_SCAN);
!
! The time returned in TT_TIME is the time of the closest
! task wakeup. If it is greater than zero, a task is
! waiting for wakeup. If no task is waiting, then clear
! any pending interrupts.
!
! Set a new time out interrupt if needed.
!
if TIME_NULL (TT_SBLK [TT_TIME])
then
begin
TIME_INTERRUPT_CLEAR;
TIME_SET_NULL (TIME_OUT);
end
else
if TIME_TEST (TT_SBLK [TT_TIME], lss, TIME_OUT)
or TIME_NULL (TIME_OUT)
then
begin
TIME_COPY (TIME_OUT, TT_SBLK [TT_TIME]);
TIME_INTERRUPT_CLEAR;
TIME_INTERRUPT_SET (TIME_OUT, TIMEOUT_SIGNAL);
end;
!
! Wait until the next scheduler event occurs. The scheduler
! event includes both time interrupts and another task
! queueing itself to be woken up in the future.
!
NMU$SCHED_WAIT (SKD_EVENT,0);
end;
end; ! End of SCHEDULER_TASK
%routine ('TIMEOUT_SIGNAL') TIMER_INTERRUPT_ROUTINE novalue =
!++
! Functional description:
!
! This routine is called at interrupt level when
! a timer interrupt occurs. It signals the SKD_EVENT
! so that the scheduler task will start again.
!
! Formal parameters: none
!
! Routine value: none
! Side effects: none
!
!--
begin
TIME_SET_NULL (TIME_OUT);
NMU$SCHED_FLAG (SKD_EVENT);
PROCESS_WAKE;
end; ! End of TIMEOUT_SIGNAL
%routine ('TT_SCAN', TASK : ref TASK_BLOCK, DATA : ref TIMER_SCAN_BLOCK) =
!++
! Functional description:
!
! This routine performs the timer queue scaning for the
! scheduler task.
!
! When a task is found that has a wakeup time less than
! the current time, a wakeup event is generated for it.
!
! The closest wakeup time to the current time is kept
! so that a wake up interrupt can be set.
!
! Formal parameters:
!
! .TASK Address of task from time queue
! .DATA Address of timer queue scanning data block
!
! Routine value: none
! Side effects: none
!
!--
begin
!
! Check to see if the task needs to be woken up.
!
if TIME_TEST (TASK [TB_TIME], leq, DATA [TT_NOW])
then
begin
NMU$QUEUE_SCAN_EXTRACT (TASK [TB_SCHED_QUEUE]);
MAKE_TASK_RUNNABLE (TASK [TB_SCHED_QUEUE]);
end
else
!
! Check if wakeup time of task is the closest future
! time.
!
if TIME_TEST (DATA [TT_TIME], gtr, TASK [TB_TIME])
or TIME_NULL (DATA [TT_TIME])
then TIME_COPY (DATA [TT_TIME], TASK [TB_TIME]);
!
! Return value indicating that queue scan should continue to
! the end of the queue.
!
0
end; ! End of TT_SCAN
%global_routine ('NMU$SCHED_CURRENT') =
!++
! Functional description:
!
! This routine returns the current task block address.
!
! Formal parameters: none
!
! Routine value:
!
! A task block address
!
! Side effects: none
!
!--
begin
CURRENT_TASK
end; ! End of NMU$SCHED_CURRENT
end ! End of module SCHED
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:0
! Comment Column:40
! Comment Rounding:+1
! End: