Google
 

Trailing-Edge - PDP-10 Archives - BB-JF18A-BM - sources/diu/diuspl.b36
There are 4 other files named diuspl.b36 in the archive. Click here to see a list.
%TITLE 'DIU Spooler Start/Stop Routines'

MODULE DIUSPL (IDENT = '257',
               ENTRY(sp$start,                 ! Start spooler
                     sp$stop,                  ! Stop spooler
                     sp$shut                   ! Shut down spooler entirely
                     )
               )=
BEGIN

!	COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1986.
!	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:  DIU-20. (Data Interchange Utility for TOPS-20)
!
! ABSTRACT:    This module contains the top level spooler routines.  These
!              routines declare the current job as the DIU master, initialize 
!              the job scheduler, and set up the interrupt system so that 
!              appropriate routines are called to handle IPCF messages,network 
!              topology changes, and timer interrupts.
!
! ENVIRONMENT: TOPS-20 V6.1 (privileged)    XPORT.
!              BLISS-36 V4                  RMS V3 
! HISTORY:
!
!  257  Change library BLI:MONSYM to just MONSYM.
!       Gregory A. Scott 7-Jul-86
!
!  216  Call routine S$NOMOUNT when becoming the spooler so we can run  without
!       incrementing the mount count for every regulated structure.
!       Gregory A. Scott 3-Jun-86
!
!  171  Call routine C$CONTROL_C for control C interrupts.
!       Gregory A. Scott 19-May-86
!
!  164  Go NOINT while starting the spooler.
!       Gregory A. Scott 16-May-86
!
!  154  Use routine j$kill instead of s$kiljob.
!       Gregory A. Scott 12-May-86
!
!  152  Use new routine to write to  the  system  LOG  file  for  the  "maximum
!       requests set to n" message from SP$START.
!       Gregory A. Scott 11-May-86
!
!  144  DIU$MESSAGE calls from here should always write to the system LOG file.
!       Gregory A. Scott 7-May-86
!
!  140  Spooler restart aborted error wasn't furnishing the version number for
!       FAO output.
!       Gregory A. Scott 4-May-86
!
!  135  A restart  should show  us the  maximum simultaneous  requests.   Don't
!       decrement NJOB here, it is done when we get the IPCF that the job died.
!       Gregory A. Scott 1-May-86
!
!  134  A START command should counteract any shutdown in progress.   We  don't
!       have to write to the LOG file ourselves now since DIU$MESSAGE does it.
!       Gregory A. Scott 30-Apr-86
!
!  133  Set IPCF send/recieve quotas to +INF for rcvpid.
!       Gregory A. Scott 29-Apr-86
!
!  132  Enable illegal instruction and illegal memory read/write panic channels
!       so that we can recover from  problems.  Add routine SP$PANIC to  handle
!       these conditions.  Add control-C trap.  Move spooler restart logic that
!       checks for restart loops here from DIUERR since panic interrupts  don't
!       signal errors.
!       Gregory A. Scott 28-Apr-86
!
!  130  Call MAKEPROMPT to reset the prompt string in SP$SHUT and SP$START.
!       Gregory A. Scott 28-Apr-86
!
!  126  Change calls to S$ACTIVATE.  Regular STOP  command  was broken by  last
!       edit.  STOP/NOW shouldn't call  SP$SHUT, but wait for  it to be  called
!       after all of the jobs logout.
!       Gregory A. Scott 26-Apr-86
!
!  125  Output a little different  message if we  have been restarted.   Output
!       proper event codes to LOG file on start/stop/shut messages.  Only  call
!       SP$SHUT at the end of SP$STOP if we have to mumble around killing jobs.
!       Gregory A. Scott 24-Apr-86
!
!  122  Output the  DIU version  to the  system LOG  file at  startup, put  the
!       spooler startup message  in the  LOG file before  any possible  message
!       from opening the queue file.
!       Gregory A. Scott  22-Apr-86
!
!    57	Enable the interrupt system at the end of routine SP$STOP.
!	Sandy Clemens	4-Dec-85
!
!    56	Make STOP/NOWAIT complete shutting down the queue.
!	Sandy Clemens	3-Dec-85
!
!    52 Make sure PSI channels which are enabled by STARTing queue are
!       disabled when by STOP command.
!	Sandy Clemens	12-Nov-85
!
! V01-004  DPR0001		Doug Rayner		25-Jul-85
!	    Change use of PSI a little for TOPS-10
!
! V01-003  RDF0001           Rick Fricchione               26-Oct-1984
!          Modify for DIU.  Clean up can comment.  Make blocks
!          readable, and put in any DIU specifics.
!
! V01-002  AWN0002           Andy Nourse                    --- no date ---
!          Put in entry points.
!--
!**************************************************************************
!**                    F O R W A R D   R O U T I N E S 
!***************************************************************************
FORWARD ROUTINE
%IF %SWITCHES(TOPS20)
%THEN
    sp$panic : NOVALUE,                 ! panic interrupt handler
%FI
    sp$start : NOVALUE,                 ! Start spooler
    sp$stop  : NOVALUE,                 ! Stop spooler
    sp$shut  : NOVALUE;                 ! Shut down spooler entirely
!**************************************************************************
!**                    L I B R A R Y   F I L E S 
!***************************************************************************

LIBRARY 'BLI:XPORT';                    ! XPORT is our trusted friend
%IF %SWITCHES(TOPS10) %THEN
LIBRARY 'BLI:UUOSYM';                   ! TOPS-10 UUO symbols
%ELSE
LIBRARY 'MONSYM';                       ! TOPS-20 JSYS symbols
REQUIRE 'JSYSDEF';                      ! TOPS-20 JSYS linkages
%FI
LIBRARY 'DIU';                          ! Our library
LIBRARY 'FAO';                          ! Formatted Ascii Output library
!**************************************************************************
!**             G L O B A L S   A N D   E X T E R N A L S 
!***************************************************************************
GLOBAL
    mst_flag : INITIAL (0) VOLATILE,
    rcvpid,                             ! PID for master to receive queries on

%IF %SWITCHES(DEBUG)
%THEN
    my_name : $STR_DESCRIPTOR (STRING = '[SYSTEM]DIUDEB'),
%ELSE
    my_name : $STR_DESCRIPTOR (STRING = '[SYSTEM]DIU'),
%FI
%IF %SWITCHES(TOPS20) %THEN
    topology_failure : INITIAL (0),     ! Net topology interrupt failure
%FI
    shutdown;                           ! Shutdown pending flag

EXTERNAL
%IF %SWITCHES(TOPS20) %THEN
    i_channel,                          ! IPCF interrupt channel
    t_channel,                          ! Timer interrupt channel
    n_channel,                          ! Network topology interrupt channel
    c_channel,                          ! Control-c channel
%FI
    time_restart,                       ! nonzero if we have been restarted
    njob,                               ! Number of jobs in progress
    mjob,                               ! Max no. of jobs
    tty : $XPO_IOB (),                  ! IOB for user's terminal
    jobstatus : BLOCKVECTOR [DIU$K_MAX_MJOB, DIUJ$K_LEN]
                FIELD (DIUJ$$JOBSTAT_FIELDS);

EXTERNAL ROUTINE
%IF %SWITCHES(TOPS20) %THEN             ! TOPS-20 external routines
    C$CONTROL_C : NOVALUE,              ! Exit unless we are (yet) the spooler
    S$ACTIVATE : NOVALUE,               ! Activate an interrupt channel
    S$DEACTIVATE : NOVALUE,             ! Deactivate an interrupt channel
    S$ATI : NOVALUE,                    ! Attach Terminal Interrupt character
    S$DTI : NOVALUE,                    ! Detach Terminal Interrupt character
    S$RESTART : NOVALUE,                ! Restart this program
    S$RIR,                              ! Read interrupt addresses
    S$TOPINT,                           ! Net topology change interrupt setup
    S$NOMOUNT : NOVALUE,                ! Allos us ot ignore increment mount ct
    IP$QUOTA : NOVALUE,                 ! Set send/rec quotas
    IP$INT_SET : NOVALUE,               ! IPCF interrupt setup
%ELSE                                   ! TOPS-10 external routines
    ip$eat : NOVALUE,                   ! Clean out the IPCF recv queue
    psi$add_condition,                  ! Add a condition to the PSI system
    psi$remove_condition,               ! Remove condition from the PSI system
%FI                                     ! End TOPS-10/TOPS-20 conditional
    MAKEPROMPT : NOVALUE,               ! Make a new prompt string for operator
    DIU$MESSAGE,                        ! DIU message printer
    j$kill,                             ! Logout a job
    L$EVENT : NOVALUE,                  ! Log an event to system log file
    IPC_MASTER,                         ! Declare ourselves master
    IPC_HNDLR,                          ! IPCF interrupt handler
    Q$INIT,                             ! Open or create queue file
    S$TIME,                             ! Return time of day
    S$HALT : NOVALUE,                   ! Halt this fork
    S$NOINT : NOVALUE,                  ! Disable interrupts
    S$OKINT : NOVALUE,                  ! Enable interrupts
    SCHED : NOVALUE,                    ! Scheduler
    IP$DELETE_PID : NOVALUE;            ! Delete a PID
!****************************************************************************
!**                           S P $ S T A R T
!****************************************************************************
GLOBAL ROUTINE sp$start : NOVALUE =
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!       This routine starts the spooler.  We get the DIU spooler pid, set  some
!       flags, and call the scheduler to get something to do.  If we are inside
!       a shutdown, then we just clear the shutdown flag and return.
!
! IMPLICIT INPUTS:
!       mst_flag: 1 if we are (yet) the spooler
!       shutdown: 1 if we are shutting down
!       time_restart: 0 if we haven't been started yet
!
! IMPLICIT OUTPUTS:
!       rcvpid: set to the named spooelr job pid
!
! SIDE EFFECTS:
!       sched is called to (maybe) run some jobs
!--

BIND jobver = %O'137';                  ! Where the version is kept

LOCAL
     vlist : VECTOR[2] PRESET ([0] = 1),        ! List for passing to FAO
     time_current,                              ! current time
     retcode;

! See if we have been here before.  If I am the spooler and I am being shut
! down, then the shutdown will be aborted and I will restart.  If I'm already
! started just give a message and exit.

IF .mst_flag
THEN IF .shutdown
     THEN BEGIN                         ! Here if START after STOP
          DIU$MESSAGE(DIU$_SHUTDOWN_ABORTED,0,0,TRUE);
          shutdown = 0;                 ! We are not (yet) shutting down
          RETURN;                       ! Don't try anything else but return
          END
     ELSE BEGIN                         ! Here if we are the spooler already
          DIU$MESSAGE(DIU$_ALREADY_STARTED,0,0,TRUE);
          RETURN;                       ! Return now before damage is done
          END;

%IF %SWITCHES(TOPS10)
%THEN                                   ! on the -10,
ip$eat(0);                              ! Clean out the recv queue
%FI

! I am not (yet) the spooler until I get my PID

IF NOT (retcode = ipc_master (my_name, rcvpid))
THEN SIGNAL (.retcode);

! I am (yet) the spooler.  Turn off the interrupt system for now, init flags

S$NOINT();                              ! Turn off the interrupt system
mst_flag = 1;                           ! Set flag saying we are master
shutdown = 0;                           ! We aren't (yet) shutting down
njob = 0;                               ! No jobs active (yet)
MAKEPROMPT();                           ! I am going to need (yet) a new prompt

! Determine what has been going on.  We have either not (yet) been started,
! we haven't been started in over a minute (we restart), or we have been
! started less than a minute ago (we abort).

time_current = S$TIME();                ! Get the current time
vlist[1] = .jobver;                     ! Copy version number to FAO vector

IF .time_restart NEQ 0                  ! Get proper message please
THEN retcode = DIU$_SPOOLER_RESTARTED   ! We've been warm started
ELSE retcode = DIU$_SPOOLER_STARTED;    ! Brrrr.  Cold start.

IF .time_current LSS .time_restart+((60^18)/(60*60*24)) ! Up .lt. 1 minute?
THEN BEGIN
     time_restart = 1;                  ! Next time let me go please
     DIU$MESSAGE(DIU$_SPOOLER_ABORTED,0,vlist,TRUE); ! Yes, abort it
     S$HALT();                          ! Halt the fork allow continue
     END;
time_restart = .time_current;           ! Set the time that we were restarted

! Squirt a startup message in the system log file and to the operator

DIU$MESSAGE(.retcode,0,vlist,TRUE);     ! Type the message out

! Output the mjob setting to the log file.

vlist[1] = .mjob;                       ! Load the mjob setting
L$EVENT(DIU$_MAXIMUM_REQ_SET,0,vlist);  ! Write max stuff to system log file

! Pry open the system queue file (hello RMS, are you there today?)

IF NOT (retcode = q$init ())            ! Open or create the queue file 
THEN SIGNAL (DIU$_BUG,.retcode);        ! Something wrong with the queue

%IF %SWITCHES(TOPS10) %THEN
! Assign interrupt channels for IPCF messages, timer events, and
! network topology changes.  Only IPCF messages need special handling,
! other events just call the scheduler.
psi$add_condition($PCIPC, 0, 0, ipc_hndlr);
psi$add_condition($PCTMR, 0, 0, sched);
psi$add_condition($PCNET, 0, 0, sched);
%ELSE

! Activate interrupt channels for IPCF messages, timer events, network topology
! changes, control-c trap, and panic channels.

s$activate(.i_channel,ipc_hndlr);       ! IPCF interrupts
s$activate(.t_channel,sched);           ! TIMER interrupts
s$activate(.n_channel,sched);           ! Network status change interrupts
s$activate(.c_channel,c$control_c);     ! Control C interrupts
s$activate($ICILI,SP$PANIC);            ! Illegal instruction
s$activate($ICIRD,SP$PANIC);            ! Illegal memory read
s$activate($ICIWR,SP$PANIC);            ! Illegal memory write

! Enable interrupts for IPCF messages arriving on our PID, network topology
! changes, and control-c trap.

IP$INT_SET(.rcvpid, .i_channel);        ! Set IPCF interrupts for master pid
IP$QUOTA(.rcvpid, %O'777', %O'777');    ! Set send/rec quota to +inf
IF NOT S$TOPINT(.n_channel) THEN topology_failure = 1;  ! Set topology ints
S$ATI($TICCC,.c_channel);               ! Set control-C trap

! Allow us to touch any structure on the system since we are yet a spooler

S$NOMOUNT();                            ! Do a MSTR MSIIC function

%FI                                     ! End of TOPS-20 only code

! Make all job status blocks available

INCR index FROM 0 TO DIU$K_MAX_MJOB - 1
     DO jobstatus[.index, DIUJ$V_INUSE] = 0;

! Call the scheduler to start any jobs in the queue.

SCHED();

! Turn the interrupt system on and return

S$OKINT();

END;                                ! End of sp$start
!*********************************************************************
!**                       S P $ S T O P 
!*********************************************************************
GLOBAL ROUTINE sp$stop (now_flag) : NOVALUE =
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!   Stop the spooler and queue manager.
!
! FORMAL PARAMETERS:
!   now_flag            - Boolean value:
!                         TRUE  - Immediately abort all current transfers
!                         FALSE - Allow all current transfers to complete
!
! IMPLICIT INPUTS:
!   NONE
!
! IMPLICIT OUTPUTS:
!   NONE
!
! ROUTINE VALUE and
! COMPLETION CODES:
!   NONE
!
! SIDE EFFECTS:
!   NONE
!
!--

LOCAL scode;                            ! spooler stop event code

IF NOT .mst_flag                        ! Are we (yet) the spooler?
THEN SIGNAL(DIU$_NOT_STARTED);          ! Oops, we are not (yet) the spooler

shutdown = 1;                           ! Flag pending shutdown
time_restart = 1;                       ! Let restarts work later

! Print a message depending on spooler shutdown status

IF .now_flag
THEN scode = DIU$_SPOOLER_STOP_NOW      ! STOP/NOW command
ELSE scode = DIU$_SPOOLER_STOP;         ! STOP command

DIU$MESSAGE(.scode,0,0,TRUE);           ! Write it to terminal and log file

! If there aren't any jobs running shutdown the spooler and return now.

IF .njob EQL 0
THEN BEGIN
     SP$SHUT();
     RETURN;
     END;

! If it was a regular stop command and there were jobs running wait for them
! to finish up; don't shutdown the spooler yet.

IF NOT .now_flag THEN RETURN;

! STOP/NOWAIT specified and there are jobs active.  Abort all inuse jobs.

S$NOINT();                              ! Turn off interrupts

INCR index FROM 0 TO DIU$K_MAX_MJOB - 1
DO IF .jobstatus[.index, DIUJ$V_INUSE]
   THEN j$kill(.jobstatus[.index, DIUJ$H_REQUEST_ID],
               .scode);

S$OKINT();                              ! Enable the interrupt system

END;                                    ! End of sp$stop
!************************************************************************
!**                            S P $ S H U T 
!************************************************************************
GLOBAL ROUTINE sp$shut : NOVALUE =
BEGIN
!++
! FUNCTIONAL DESCRIPTION:
!
!       Completely shut down spooler.   After a STOP  command, this routine  is
!       called if there are  no active slave jobs.   If there are active  slave
!       jobs, this routine is called when  the last one finishes.  The  spooler
!       pid is deleted and all interrupts are disabled.
!
! IMPLICIT INPUTS:
!       rcvpid: spooler pid
!       shutdown: flag that we are shutting down
!       mst_flag: flag that we are (yet) the spooler
!
! IMPLICIT OUTPUTS:
!       rcvpid: zeroed
!       shutdown: cleared
!       mst_flag: cleared, because we are not (yet) the spooler again
!
! SIDE EFFECTS:
!       The spooler pid is deleted.
!       All enabled interrupts are disabled.
!       A new prompt is made for the spooler job.
!--

! Tell the operator and the LOG file about this event.

DIU$MESSAGE(DIU$_SPOOLER_DOWN,0,0,TRUE);   ! Tell the operator ane the log file

! Deativate the interrupt system.

%IF %SWITCHES(TOPS10) 
%THEN
      IP$DELETE_PID(.rcvpid,0);
      psi$remove_condition($PCIPC, ipc_hndlr);
%ELSE
      IP$DELETE_PID(.rcvpid);           ! That's all for the pid
      s$deactivate(.n_channel);         ! Network topology interrupts
      s$deactivate(.t_channel);         ! Timer interrupts
      s$deactivate(.i_channel);         ! IPCF interrupts
      s$deactivate(.c_channel);         ! Control C interrupts
      S$DTI($TICCC);                    ! No longer trapping control C
%FI

! Shut off the flags indicating that I am the spooler and shutdown in progress

rcvpid = 0;                             ! No longer a spooler pid
mst_flag = 0;                           ! We are not (yet) the spooler again
shutdown = 0;                           ! We aren't shutting down any more

! Make a new prompt string for the user.

MAKEPROMPT();

END;                                    ! End of sp$shut
%IF %SWITCHES(TOPS20) %THEN
ROUTINE SP$PANIC (channel) : novalue =
!++
! FUNCTIONAL DESCRIPTION:
!
!       This routine is called on a panic interrupt to print a fatal error and
!       restart the spooler.
!
! FORMAL PARAMETERS:
!
!       channel: channel that we were interrupted on
!
! SIDE EFFECTS:
!
!       Program is restarted
!
!--
BEGIN
 
LOCAL elist : VECTOR[2] PRESET ([0] = 1),        ! List for passing to FAO
      edesc : $STR_DESCRIPTOR(CLASS=DYNAMIC),    ! spooler message
      epc,                                       ! PC of error
      etype;                                     ! Error type

! Compute the error code from the channel number we were called with. 

etype = (SELECTONE .channel OF
         SET
         [$ICILI]: DIU$_PANIC_ILL_INST;
         [$ICIRD]: DIU$_PANIC_ILL_READ;
         [$ICIWR]: DIU$_PANIC_ILL_WRIT;
         TES);

! Get the PC that the error occured at

epc = S$RIR();                          ! Get levtab,,chntab
elist[1] = (..((.epc<LH>)+2))-1;        ! Get the interrupt chan 3 pc

! Tell the operator and the log file about the bad news

DIU$MESSAGE(.etype,0,elist,TRUE);       ! Tell me about it please

! Restart the program

s$restart();                            ! Never returns

END;                                    ! End of s$panic
%FI                                     ! End of TOPS20 conditional
END                                     ! End of module DIUSPL
ELUDOM