*DECK XCHKPCR 
USETEXT NIPDEF
USETEXT ACNB
USETEXT ACNT
USETEXT AT
USETEXT DRHDR 
USETEXT ACB 
USETEXT PRUBUFF 
USETEXT FREETAB 
USETEXT KDIS
USETEXT PT
USETEXT MSGIDX
USETEXT RELFILE 
USETEXT STATTAB 
USETEXT SYSTIME 
USETEXT LLCB
USETEXT NBT 
USETEXT TNT 
USETEXT PARAMS
USETEXT PIT 
USETEXT OVERLAY 
 PRGM XCHKPCR;               # CHECK FOR TIME-OUT ON A CONNECTION      #
  
 STARTIMS;
 #
*1DC  XCHKPCR 
* 
*     1. PROC NAME           AUTHOR              DATE 
*        XCHKPCR             PETER TAM           18/03/25 
* 
*     2. FUNCTIONAL DESCRIPTION.
*        LOOK FOR ACNT TABLE TO SHRINK, 
*        CHECK EVERY NETWORK CONNECTION FOR LACK OF ACTIVITY. 
* 
*     3. METHOD USED. 
*          IF PP-CALL-RING EXISTS AND COMPLETION BIT IS SET IN THE
*          CIO OR DSP REQUEST PARAMETER BLOCK, DELINK BLOCK FROM THE PCR
*          AND RELEASE IT.
*          FOR EVERY ACNT TABLE, CHECK IF THERE IS POSSIBILITY
*          OF SHRINKING. CALL SDELQTB TO SHRINK THE TABLE.
*          FOR EACH ACNB
*          CHECK TIMER FOR INACTIVITY 
*          SEND *INACT* MSG TO APPLICATION
*          CALL PIP 
* 
*     4. ENTRY PARAMETERS.  NONE
* 
*     5. EXIT  PARAMETERS.  NONE
* 
*     6. COMDECKS CALLED AND SYMPL TEXTS USED.
*        ACB                 APPLICATION CONTROL BLOCK TEMPLATE 
*        ACNB                APPLICATION CONNECTION CONTROL BLK TEMPLATE
*        ACNT                APPLICATION CONNECTION TABLE TEMPLATE
*        AT                  APPLICATION TABLE TEMPLATE 
*        DRHDR               DATA RING HEADER WORD TEMPLATE 
*        FREETAB             FREE CHAIN TABLE 
*        LLCB                LOGICAL LINK CONTROL BLOCK TEMPLATE
*        MSGIDX              DAYFILE MESSAGE TABLE
*        NIPDEF              CONSTANT DEFINITIONS 
*        OVERLAY             OVERLAY TABLE
*        PARAMS              PARAMETERS FOR PASSING TO SECONDARY OVERLAY
*        PIT                 PIP INTERFACE TABLE
*        PRUBUFF             PRU BUFFER TEMPLATE
*        PT                  POINTER TABLE
*        RELFILE             FET FOR RETURNING FILES TEMPLATE 
*        STATTAB             STATISTICS TABLE 
*        SYSTIME             SYSTEM TIME TABLE
*        TNT                 TERMINAL NODE TABLE TEMPLATE 
* 
*     7. ROUTINES CALLED. 
*          ABORT             ABORT NIP
*          BLINK             LINK DATA BLOCK INTO DATA RING 
*          MGETS             ALLOCATE BUFFER SPACE
*          OSCHAPP           SCHEDULE AN APPLICATION
*        OTIME               GET SYSTEM RTIME 
*          XTRACE            TRACES CALLS 
* 
*     8. DAYFILE MESSAGES.  NONE
* 
*        WHEN EXECUTION HAS COMPLETED, A JUMP TO LABEL
*        RJMAIN IS MADE TO RETURN TO CALLING PROGRAM. 
* 
*        W A R N I N G - THE SUM OF PROGRAM LENGTH OF XCHKPCR,
*                        MREDUCE SHOULD NOT EXCEED THE PRIMARY
*CALL OPSIZE
* 
*        THIS OVERLAY IS CALLED BY XEXEC. 
* 
 #
 STOPIMS; 
# 
 PARAMETERS.  NONE
  
                    EXTERNAL VARIABLES
# 
 XREF BEGIN 
   PROC ABORT;               # ABORT NIP                               #
   PROC BLINK;               # LINK DATA BLOCK INTO DATA RING          #
   PROC HCSTTP ;                   # HOST SIDE CONNECTION STATE TABLE  #
   PROC LOCLLCB;             # LOCATE LLCB                             #
   PROC OTIME;               # GET SYSTEM RTIME                        #
   PROC OVLCALL;             # LOAD AND EXECUTE OVERLAY                #
   PROC MGETS;               # ALLOCATE BUFFER SPACE                   #
   PROC MREDUCE ; 
   PROC OSCHAPP;             # SCHEDULE THE APPLICATION                #
   PROC MRELS;               # RELEASE BUFFER SPACE                    #
   PROC OMSG;                # DAYFILE MESSAGE                         #
   PROC XTRACE;              # TRACE CALLS                             #
   LABEL RJMAIN;             # RETURN ADDRESS                          #
   END
# 
                    INTERNAL VARIABLES
# 
 ARRAY QFERRMSG    S(4);
   BEGIN
   ITEM QFERRTEXT  C(0,0,30) = [" XXX ERROR NNB, LFN = XXXXXXX."];
   ITEM QFPPNAME   U(0,6,18);          # DSP OR CIO                    #
   ITEM QFERRNN    U(1,6,12);          # OCTAL ERROR CODE              #
   ITEM QFERRLFN   C(2,12,NC);         # QUEUE FILE LFN                #
   ITEM QFENDTEXT  U(3,0,60) = [0]; 
   END
 ITEM NXTACNB, LASTAN, TMP; 
 ITEM NEXTBLK;               # NEXT PP-CALL-RING BLOCK                 #
 ITEM LASTBLK;               # LAST PP-CALL-RING BLOCK                 #
 ITEM INDEX;                 # FOR LOOP INDEX                          #
 ITEM TMP1;                  # TEMPORARY VARIABLE                      #
 ITEM TN;                    # TERMINAL NODE                           #
 ITEM HN;                    # HOST NODE                               #
 ITEM CURR;                  # CURRENT BUFFER TO RELEASE               #
  ITEM NEXT;                 # SCRATCH VARIABLE                        #
  
 BASED ARRAY PRUNIPWD  S(1);           # TEMPLATE FOR NIP WORD IN PIT  #
   BEGIN
   ITEM PRUNIPMFB   U(0,00,06);        # MINIMUM NO OF PRU BUFS        #
   ITEM PRUNIPMAB   U(0,06,06);        # MAXIMUM NO OF PRU BUFS        #
   ITEM PRUNIPNCA   U(0,12,12);        # CURRENT NO OF BUFFERS ASSIGNED#
   ITEM PRUNIPNC    U(0,24,12);        # CURRENT NO OF PRU CONNECTIONS #
   ITEM PRUNIPFPB   U(0,42,18);        # ADR OF FIRST BUF IN FREE CHAIN#
   END
  
 BASED ARRAY PRUPIPWD  S(1);           # TEMPLATE FOR PIP WORD IN PIT  #
   BEGIN
   ITEM PRUPIPNFB   U(0,00,12);        # NO OF BUFS IN FREE CHAIN      #
   ITEM PRUPIPNRA   U(0,12,12);        # NO OF BUS NEEDED BY PIP       #
   ITEM PRUPIPRPB   U(0,42,18);        # ADDR OF BUF TO RELEASE        #
   END
  
 CONTROL IFEQ STAT,1; 
   ARRAY STIME P(1);         # RTIME BUFFER FOR STARTING TIME          #
     BEGIN
     ITEM SMILS U(0,24,36);  # STARTING TIME IN MILLESECONDS           #
     END
   ARRAY ETIME P(1);         # RTIME BUFFER FOR ENDING TIME            #
     BEGIN
     ITEM EMILS U(0,24,36);  # ENDING TIME IN MILLESECONDS             #
     END
  
   ITEM STTEMP;              # TEMPORARY STATISTICS VARIABLE           #
 CONTROL FI;
  
  
#**********************************************************************#
      BEGIN 
      CONTROL IFEQ DEBUG,1 ;
        XTRACE("XCHPC") ; 
      CONTROL FI; 
  
  
      IF HRL EQ HRLV0 
      THEN                   # NAM IN MAX FL REACHED CONDITION         #
        GOTO RJMAIN;
  
      CONTROL IFEQ STAT,1;
        OTIME(STIME);        # GET SYSTEM TIME AT BEGINNING OF PROC    #
      CONTROL FI; 
  
# 
      CHECK NAM K DISPLAY ACTIVITY
# 
      FOR NBTIDX = 0 STEP NBTFETNO WHILE NBTIDX LQ NBTMAXID 
      DO
        BEGIN 
        IF NBTREL[NBTIDX + 5]  # BUFFER RELEASE FLAG SET               #
        THEN
          BEGIN 
            IF NBTFIRST[NBTIDX + 5] NQ 0
            THEN
              BEGIN 
              MRELS(NBTFIRST[NBTIDX + 5]- BLKHSIZE);# RELEASE BUFFER   #
              END 
            NBTWD1[NBTIDX + 5] = 0; # CLEAR ALL FOUR WORDS IN TRACE FET#
            NBTWD2[NBTIDX + 5] = 0; 
            NBTWD3[NBTIDX + 5] = 0; 
            NBTWD4[NBTIDX + 5] = 0; 
          END 
        END 
  
      TMP1 = RTSECS[0]; 
      IF KDVW[0]
      THEN                   # K DISPLAY BEING VIEWED                  #
        BEGIN 
        IF KDTIMER[0] LQ TMP1 
        THEN                 # K DISPLAY VIEW TIMER TIMEOUT            #
          BEGIN 
          IF KDLCOMP[0] OR KDRCOMP[0] 
          THEN               # K DISPLAY IS ON                         #
            BEGIN 
            KDTIMER[0] = TMP1 + TKDVW; # RESTART TIMER                 #
            KDLCOMP[0] = FALSE; 
            KDRCOMP[0] = FALSE; 
            END 
          ELSE               # K DISPLAY IS NOT ON                     #
            BEGIN 
            KDVW[0] = FALSE;
            OVLNAME = KPCLNUPP; # CLEAN UP K DISPLAY DATA              #
            OVLCALL;
            END 
          END 
        END 
  
      IF KDST[0]
      THEN                   # STATUS DISPLAY IS ON                    #
        BEGIN 
        IF NOT KFAST[0] 
          AND KSLOWTM[0] LQ TMP1
        THEN                 # SLOW MODE AND TIMER EXPIRED             #
          BEGIN 
          KDIS$STAT = STM"STM$UPDATE"; # UPDATE STATUS DISPLAY         #
          KSLOWTM[0] = TMP1 + TSLOW; # RESTART TIMER                   #
          END 
  
        CONTROL IFEQ STAT,1;
        IF KSTATIM[0] LQ TMP1 
        THEN                 # UPDATE STATISTICS IN K DISPLAY          #
          BEGIN 
          OVLNAME = KSTTUPDP; 
          OVLCALL;
          KSTATIM[0] = TMP1 + TSTAT; # RESTART TIMER                   #
          END 
        CONTROL FI; 
  
        END 
  
      P<FREEBUF> = 0; 
      IF (FREFBBP+FRBBS[FREFBBP]) EQ CTLSLWA
        AND FRBBS[FREFBBP] GQ 2*RSBUF 
      THEN
        REDUCEFL = 1; # CALL MGBGCLT TO REDUCE FL                      #
# 
      IF PP-CALL-RING EXISTS AND COMPLETION BIT IS SET IN A REQUEST 
      PARAMETER BLOCK, DELINK BLOCK FROM THE PCR AND RELEASE IT.
# 
      NEXTBLK = PCRHEAD[0];            # INITIALIZE NEXT PCR BLOCK     #
      FOR INDEX=INDEX WHILE NEXTBLK NQ 0
                        AND NEXTBLK NQ LOC(PCRHEAD[0])
      DO
        BEGIN                          # SCAN PP-CALL-RING             #
        P<PARAMB> = NEXTBLK + BLKHSIZE;# PARAMETER BLOCK ADDRESS       #
        P<DRHDRWD> = NEXTBLK;          # CURRENT PCR BLOCK             #
        NEXTBLK = NEXTPTR[0];          # NEXT BLOCK IN PCR             #
        LASTBLK = BACKPTR[0];          # PREVIOUS BLOCK IN PCR         #
  
        IF FET$CB[0]
        THEN                           # IF COMPLETION BIT IS SET      #
          BEGIN 
  
          IF BLKID[0] EQ DPCRIDVALUE
          THEN                         # A DSP CALL                    #
            BEGIN 
            TMP = FET$DSPERR[0];       # DSP ERROR CODE                #
            TMP1 = PP$DSP;
            END 
          ELSE                         # A CIO CALL                    #
            BEGIN 
            TMP = FET$CIOERR[0];       # CIO ERROR CODE                #
            TMP1 = PP$CIO;
            END 
  
          IF TMP NQ 0 
          THEN                         # DSP OR CIO CALL ERROR         #
            BEGIN 
            QFPPNAME[0] = TMP1; 
            TMP1 = TMP/8; 
            QFERRNN[0] = TMP1*O"100" + TMP - TMP1*8 + O"3333";
            QFERRLFN[0] = FET$LFN[0]; 
            OMSG(QFERRMSG,0);            # DAYFILE MESSAGE             #
            END 
  
          MRELS(P<DRHDRWD>);           # RELEASE PCR BLOCK             #
  
          IF PCRHEAD[0] EQ PCRTAIL[0] 
          THEN
            BEGIN                      # ONLY PCR BLOCK REMAINS        #
            PCRHEAD[0] = 0;            # ZERO PCR POINTERS             #
            PCRTAIL[0] = 0; 
            END 
  
          ELSE                         # MORE THAN ONE PCR BLOCK EXIST #
            BEGIN                      # UPDATE RING POINTERS          #
            P<DRHDRWD> = 0; 
            NEXTPTR[LASTBLK] = NEXTBLK; 
            BACKPTR[NEXTBLK] = LASTBLK; 
            END 
          END 
        END 
# 
      CHECK EVERY CONNECTION OF EVERY APPLICATION FOR ELIGIBLE CAND 
      TO SEND FC/INACT TO 
# 
      IF INACTVAL NQ 0
         OR SETTIMER               # APP SET INACTIVITY TIMER          #
      THEN
        BEGIN                      # CHECK FOR INACTIVE TERMINALS      #
        SETTIMER = FALSE;          # REINITIALIZE APP SET TIMER FLAG   #
  
        FOR LASTAN = 1 STEP 1 UNTIL ATHAN[0]
        DO
          BEGIN 
          P<ACB> = ATACBA[LASTAN];# NEXT ACB IN AT                     #
          IF P<ACB> NQ 0 AND NOT ATNVFN[LASTAN] AND NOT ATNVFF[LASTAN]
          THEN
            BEGIN              # APP CONTROL BLOCK EXISTS              #
  
  #         TIME TO LOOK FOR ACNT TO SHRINK                            #
  
            P<ACNT> = ACBACNT[0];# APP CONNECTION TABLE ADDRESS        #
  
  #         CHECK CONNECTIONS ACTIVITIES                               #
  
            IF ACBNCN[0] NQ 0 
            THEN
              BEGIN            # CONNECTIONS EXIST                     #
              FOR NXTACNB = ACNTHSIZE STEP 1 # ENTRY SIZE OF ACNT # 
                            UNTIL ACNTHCN[0]-ACNTMINACN[0]+ACNTHSIZE
              DO
                BEGIN 
                P<ACNB> = ACNTACNB[NXTACNB];
                IF P<ACNB> NQ 0 
                THEN
                  BEGIN      # THERE IS A CONNECTION                   #
                  IF ( ACNBINACT[0] LQ RTSECS[0]    ) AND 
                     ( ( (NOT ACNBTIMERF[0]) AND
                         (INACTVAL NQ 0    )    ) OR
                       ( (ACNBTIMERF[0]    ) AND
                         (ACNBTIMER[0] NQ 0)    )   ) 
                  THEN
                    BEGIN 
                    RCBRK = RCCB"I" ;      # REASON CODE 9 TO BREAK THE#
                                     # CONNECTION IF IT NEEDS TO BE TER#
                                     # ONLY WHEN CONNECTION STILL IN NV#
                    HCSTTP(P<ACB>,ACNBACN[0],HCTMOUT,0) ; # SEND FC/INA#
                    ACNBTIMERF[0] = ACNBTIMERP[0]; # RESET APP TIMER FL#
                    IF ACNBTIMERF[0]
                    THEN           # APP TIMER STILL IN EFFECT         #
                      BEGIN 
                      ACNBINACT[0] = RTSECS[0] + ACNBTIMER[0]; # NEW TI#
                      END 
                    ELSE           # NAM INACTIVITY TIMER IN EFFECT    #
                      BEGIN 
                      ACNBINACT[0] = RTSECS[0] + INACTVAL;
                      END 
                    END 
                  IF ACNBTIMERF[0]
                  THEN             # APP TIMER STILL IN EFFECT         #
                    BEGIN 
                    SETTIMER = TRUE;  # APP SET INACTIVITY TIMER       #
                    END 
                  END 
                END 
              END 
            END 
          END 
        END                              # CHECK FOR INACTIVE TERMINAL #
  
  
      P<LLCB> = TNTLLAD[0]; 
      IF P<LLCB>  NQ 0 AND LLCBNC[0] EQ 0 
      THEN
        BEGIN                # NO CONNECTIONS ON INTRA HOST LLK        #
        FOR TN=0 STEP 1 WHILE (TN LQ 1) 
        DO
          BEGIN 
          IF TN EQ 0
          THEN
            HN = 1; 
          ELSE
            HN = 0; 
          LOCLLCB(HN,TN,P<LLCB>);  # FIND LLCB                         #
          IF LLCBNC[0] EQ 0 
          THEN
            BEGIN            # RELEASE DATA QUEUED ON FAKE LLK         #
            P<DRHDRWD> = 0; 
            CURR = LLCBSHFP[0]; 
            FOR CURR = CURR WHILE CURR NQ 0 
            DO
              BEGIN 
              NEXT = NEXTPTR[CURR]; 
              MRELS(CURR);
              CURR = NEXT;
              END 
            END 
          #  RELEASE INTRA HOST LOGICAL LINKS                          #
          PARAMS2 = P<LLCB>;
          OVLNAME = RELLLCBP;  # OVERLAY NAME                          #
          OVLCALL;
          END 
        END 
# 
      SCAN THROUGH PIT TABLE LOOKING FOR PRU BUFFERS THAT ARE TO BE 
      RELEASED. 
# 
      FOR INDEX = 1 STEP 1 UNTIL MAXPIP 
      DO                               # CHECK ALL PIT ENTRIES         #
        BEGIN 
        IF PITPUF[INDEX]
        THEN                           # THIS PIT ENTRY IS IN USE      #
          BEGIN 
          P<PRUNIPWD> = LOC(PITW5[INDEX]);  # ADDR OF 1ST NIP WORD     #
          P<PRUPIPWD> = LOC(PITW8[INDEX]);  # ADDR OF 1ST PIP WORD     #
          FOR NEXT = 0 STEP 1 UNTIL MAXPRU-1
          DO                           # CHECK EACH PRU BUFFER SIZE    #
            BEGIN 
            TMP = PRUNIPNCA[NEXT] - PRUPIPNRA[NEXT]; # NO OF BUF TO REL#
            IF TMP GR 0 
            THEN                       # PIP HAS PRU BUFS FOR RELEASE  #
              BEGIN 
              P<PRUBUFF> = PRUPIPRPB[NEXT];  # ADDR OF BUF TO RELEASE  #
              IF (TMP EQ 1       ) AND  # PIP ONLY RELEASES 1 AT A TIME#
                 (P<PRUBUFF> NQ 0)     # ADDR OF BUF TO RELEASE EXISTS #
              THEN                     # RELEASE PRU BUFFER            #
                BEGIN 
                MRELS(P<PRUBUFF>);     # RELEASE BUFFER                #
                PRUNIPNCA[NEXT] = PRUNIPNCA[NEXT] - 1;
                IF PRUNIPNCA[NEXT] EQ 0 
                THEN                   # RELEASED LAST PRU BUFFER      #
                  BEGIN 
                  PRUNIPFPB[NEXT] = 0; # ZERO 1ST BUFFER POINTER       #
                  END 
                END 
              ELSE                     # PIP MAY HAVE RELEASED ALL BUFS#
                BEGIN 
                IF P<PRUBUFF> NQ 0
                THEN                   # PIP HAS NOT DROPPED OUT       #
                  BEGIN 
                  D27M2[0] = "XCHKPCR"; 
                  OMSG(DFMSG27,0);     # NIP INTERNAL ERROR            #
                  ABORT(0,0);          # ABORT NIP                     #
                  END 
                END 
              END 
            END 
          END 
        END 
  
      CONTROL IFEQ STAT,1;
        OTIME(ETIME);        # GET SYSTEM TIME AT END OF PROC          #
        ST$NXP = ST$NXP + 1; # INCREMENT NUMBER OF TIMES XCHKPCR CALLED#
        STTEMP = EMILS[0] - SMILS[0];  # TIME SPENT IN THIS ROUTINE    #
        ST$TXP = ST$TXP + STTEMP;  # TOTAL TIME SPENT IN THIS ROUTINE  #
        IF ST$LXP LS STTEMP 
        THEN                 # FOUND LARGER TIME INTERVAL IN ROUTINE   #
          BEGIN 
          ST$LXP = STTEMP;   # NEW LARGEST TIME INTERVAL               #
          END 
      CONTROL FI; 
  
  
      GOTO RJMAIN;
      END 
TERM
