*DECK GETFREE 
USETEXT COMCBEG 
USETEXT COMRQUE 
PROC GETFREE; 
# TITLE GETFREE - GET FREE QUEUE ENTRY. # 
  
      BEGIN  # GETFREE #
  
# 
**    GETFREE - GET FREE QUEUE ENTRY. 
* 
*     GET FREE QUEUE ENTRY. 
* 
*     PROC GETFREE. 
* 
*     ENTRY   - NONE
* 
*     EXIT    - QU$ADDRESS IS BASED ARRAY POINTING TO ASSIGNED
*                 QUEUE ENTRY.
* 
*     PROCESS - IF NO FREE ENTRY
*               THEN: 
*                 MAKE MEM REQUEST FOR MORE FIELD LENGTH. 
*                 LINK NEW MEMORY INTO FREE QUEUE.
*               DEQUEUE ENTRY FROM FREE QUEUE.
*               RETURN. 
* 
*     NOTES   - THE MEM REQUEST IS MADE WITH AUTORECALL BECAUSE 
*               PROCESSING CAN NOT CONTINUE WITHOUT QUEUE ENTRIES.
*               AUTORECALL IS ALSO MANDATORY FOR ANY MEM REQUEST
*               FROM A CONTROL POINT. 
# 
  
# 
****  PROC GETFREE - XREF LIST BEGIN. 
# 
      XREF
        BEGIN 
        PROC CALLSYS;                # SYSTEM REQUEST # 
        PROC DEQUEUE;                # DEQUEUE #
        PROC QUEUE;                  # QUEUE #
        END 
  
# 
****  PROC GETFREE - XREF LIST END. 
# 
  
      DEF EXTENDLEN  #O"400"#;       # MEMORY EXTEND LENGTH # 
                                     # IF QU$LENGTH IS 8 THEN THIS #
                                     # ADDS 32 QUEUE ENTRIES.  #
  
  
      ITEM I          I;             # I IS A LOOP VARIABLE # 
  
      ARRAY MEMCALL[0:0] S(1);       # MEM CALL REQUEST # 
        BEGIN 
        ITEM MEMNAME    C(00,00,03) = ["MEM"];
        ITEM MEMRCL     B(00,19,01) = [TRUE]; 
        ITEM MEMADDR    I(00,42,18);
        END 
  
      ARRAY MEMPARM[0:0] S(1);       # MEM PARAMETER WORD # 
        BEGIN 
        ITEM MEMWD      I(00,00,60) = [0];
        ITEM MEMWORDS   I(00,00,30); # WORDS REQUESTED IN FL #
        ITEM MEMCOMPL   B(00,59,01); # MEM COMPLETE # 
        END 
  
CONTROL EJECT;
  
      IF FREEQ EQ 0 
      THEN
        BEGIN  # NO FREE ENTRIES #
        MEMCOMPL = FALSE; 
        MEMWORDS = FIELDLEN + EXTENDLEN;
        MEMADDR = LOC(MEMPARM); 
        CALLSYS(MEMCALL); 
  
# 
*       NOTE - MEMWORDS MUST BE ROUNDED UP TO THE NEXT MULTIPLE OF 100B 
*       FOR NOS/BE BECAUSE *MEM* DOES NOT UPDATE THE CALL BLOCK UPON
*       COMPLETION OF A MEMORY REQUEST. (SEE ROUTINE FREEMEM) 
# 
  
        MEMWORDS = (MEMWORDS + O"77") / O"100" * O"100";
  
# 
*       NOTE - THAT WHEN LINKING QUEUE ENTRIES THAT THE LAST 10B
*       WORDS OF MEMORY WILL NOT BE USED.  THIS IS IMPORTANT BECAUSE
*       THE QUEUE ENTRIES MUST BE CONTIGUOUS AND WHEN ADDING TO THE 
*       EXISTING FREEQ THE FIRST QUEUE ENTRY GENERATED WILL BE THE
*       LAST 10B WORDS OF THE PREVIOUS FIELD LENGTH SIZE (SEE ROUTINE 
*       FREEMEM). 
# 
  
        FOR I=FIELDLEN-4 STEP QU$LENGTH UNTIL MEMWORDS-(2*QU$LENGTH)
        DO
          BEGIN 
          P<QU$ADDRESS> = I;
          QU$TYPE = QT$EMPTY; 
          QU$PREVTYP = QT$EMPTY;
          QUEUE(LOC(FREEQ));
          END 
  
        FIELDLEN = MEMWORDS - 4;
        END 
  
      DEQUEUE(LOC(FREEQ));
      QU$AUXPTR = 0;
      RETURN; 
      END  # GETFREE #
  
      TERM
