Trailing-Edge
-
PDP-10 Archives
-
dec-10-omona-u-mc9
-
ipcser.mac
There are 12 other files named ipcser.mac in the archive. Click here to see a list.
TITLE IPCSER -- INTER PROCESS COMMUNICATION FACILITY V121
SUBTTL J. SAUTER/T WACHS/LSS/CDO 15 FEB 77
SEARCH F,S
$RELOC
$HIGH
;***COPYRIGHT 1973,1974,1975,1976,1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
XP VIPCSR,121 ;VERSION NUMBER FOR GLOB AND MAP
ENTRY IPCSER ;LOAD THIS MODULE IF REQUESTED
IPCSER::
;IPCSER PROVIDES A FACILITY WHICH PERMITS TWO JOBS TO EFFICIENTLY
; EXCHANGE LIMITED AMOUNTS OF DATA. THE MONITOR MAY ALSO PARTICIPATE
; IN THIS EXCHANGE BY MEANS OF "EXEC PSEUDO-PROCESSES".
;DATA STRUCTURES:
XX=. ;REMEMBER LOCATION
;EXECUTIVE PROCESS CONTROL BLOCK
PHASE 0
;NOTE THAT .EPIPC,.EPIPA, .EPIPQ MUST REMAIN IN THIS ORDER
; (SAME ORDER AS .PDIPC,.PDIPA, .PDIPQ)
.EPIPC:!BLOCK 1 ;LH=POINTER TO OLDEST PACKET
;18-26 = PACKETS SENT & NOT RECEIVED
;27-35 = PACKETS WAITING TO BE REC.
.EPIPA:!BLOCK 1 ;LH = COUNT OF SENDS SINCE LOGIN
;RH = COUNT OF RECEIVES SINCE LOGIN
.EPIPQ:!BLOCK 1 ;FLAGS AND QUOTAS
IP.DSB==(1B0) ;RECEIVER IS DISABLED
IP.HBS==(1B1) ;QUOTAS HAVE BEEN SET
IP.DPR==(1B2) ;AT LEAST 1 PID FOR JOB IS TO BE DROPPED ON RESET
IP.DPL==(1B3) ;AT LEAST 1 PID TO BE DROPPED ON LOGOUT
;18-26 = SEND QUOTA
;27-35 = RECEIVE QUOTA
IP.SBT==1000 ;1ST BIT IN SEND QUOTA/COUNT BYTE
;THE .EPXXX WORDS ABOVE HAVE CORRESPONDING .PDXXX WORDS IN
; THE PDB FOR USER JOBS.
.EPADR:!BLOCK 1 ;PUSHJ @ HERE WHEN A PACKET ARRIVES
; FOR THIS PROCESS.
DEPHASE
;DEFINITION OF PACKET DESCRIPTOR BLOCK
PHASE 0
.IPCFL::!BLOCK 1 ;LINK AND FLAGS
IP.CFB==(1B0) ;UUO BLOCK: DONT BLOCK READ UUO
IP.IAS==(1B1) ;UUO BLOCK: INDIRECT ADDRESS FOR SENDER'S PID
IP.IAR==(1B2) ;UUO BLOCK: INDIRECT ADDRESS FOR RECEIVER'S PID
;IN PACKET, LH = POINTER TO NEXT
IP.LPC==(1B3) ;UUO BLOCK: "LAST PHONE CALL" - SEND EVEN THO QUOTA
; IS OVERDRAWN (ONLY ALLOWS OVERDRAW OF 1)
IP.TTL==(1B4) ;UUO BLOCK-TRUNCATE PACKET IF TOO LONG
IP.LPK==(1B5) ;PACKET IS LONGER THAN MAX SYSTEM SIZE (PRIVID)
IP.SIP==1B18 ;SENDER IS PRIVLEGED
IP.CFV==1B19 ;VM PAGE MODE
IP.CFZ==1B20 ;DATA LENGTH=0
IP.AKR==1B21 ;SENDER REQUESTS ACKNOWLEGEMENT FROM RECEIVER
IP.CFE==77B29 ;(UNPRIV) ERROR RETURN
IP.CFM==77B35 ;SPECIAL MESSAGE FIELD
.IPCMN==1 ;MESSAGE 1: MESSAGE WAS UNDELIVERABLE
.IPCFS::!BLOCK 1 ;SENDER'S PID
.IPCFR::!BLOCK 1 ;RECEIVER'S PID
.IPCFP::!BLOCK 1 ;LH = LENGTH OF PACKET'S DATA
;IN UUO BLOCK, RH = USER'S PACKET BUFFER
;IN PACKET, RH = RESERVED FOR VIRTUAL FEATURE
.IPCFM::!BLOCK 0 ;MINIMUM LENGTH OF DESCRIPTOR BLOCK
.IPCFU::!BLOCK 1 ;SENDER'S PPN. FILLED IN BY MONITOR ON SEND
;UUO NEVER FILLED IN BY USER.
.IPCFC::!BLOCK 1 ;SENDER'S CAPABILITIES WORD. FILLED IN SAME
;FASHION AS .IPCFU.
IP.JAC==(1B0) ;SENDER HAS JACCT ON
IP.JLG==(1B1) ;SENDER IS LOGGED-IN
IP.SXO==(1B2) ;SENDER IS EXECUTE-ONLY
IP.POK==(1B3) ;SENDER CAN POKE THE MONITOR
IP.IPC==(1B4) ;SEND HAS IPCF PRIVS
;BITS 27:35 = JOB NO OF SENDER
.IPCFD::!BLOCK 0 ;IN PACKET ONLY, START OF DATA.
DEPHASE
RELOC XX ;DONT WASTE ANY SPACE
TRNPTR: POINT 9,.IPCFC(P1),35
TRNPT2: POINT 9,.IPCFC(P2),35
IFN FTGALAXY,<
;DESCRIPTION OF SPOOL, LOGIN AND LOGOUT MESSAGES
; ALL MESSAGES FROM IPCC TO QUASAR HAVE A TWO WORD HEADER AS
; DESCRIBED BELOW. THE LOGOUT MESSAGE CONSISTS SOLELY OF THESE
; TWO WORDS, AND THE SPOOL MESSAGE HAS FILE INFORMATION APPENDED,
; THE LOGIN MESSAGE HAS JOB INFORMATION APPENDED.
XX=. ;REMEMBER LOCATION
PHASE 0 ;START AT 0
GALMSG:!BLOCK 1 ;MESSAGE HEADER
; XWD LENGTH,,FUNCTION
GALSTS:!BLOCK 1 ;STATUS WORD
GALJOB==-1,,0 ;BITS 0-17 IS JOB NUMBER
GALLOC==777000 ; 18-26 IS LOCATION
GALFLG==777 ; 27-35 ARE FLAGS
GALBAT==1B27 ;BATCH JOB
GALDFR==1B28 ;DEFERRED SPOOLING
GALIUD==1B29 ;SPOOLED FILE IN USERS DIRECTORY
LGMSIZ==.-GALMSG ;SIZE OF LOGOUT MESSAGE
SPMUSR:!BLOCK 2 ;USER NAME IN 6BIT
SPMIDV:!BLOCK 1 ;INITED DEVICE
SPMSTR:!BLOCK 1 ;STRUCTURE NAME
SPMFIL:!BLOCK 1 ;FILENAME
SPMEFN:!BLOCK 1 ;ENTER'ED FILE NAME
SPMFSZ:!BLOCK 1 ;FILE SIZE IN BLOCKS
SPMFRM:!BLOCK 1 ;FORMS
SPMPRM:!BLOCK 1 ;PARAMS
SPMCOP==777 ;COPIES
SPMSIZ==.-GALMSG ;SIZE OF SPOOL MESSAGE
PHASE GALSTS+1
LOMUSR:!BLOCK 2 ;USER NAME IN 6BIT
LOMCTL:!BLOCK 1 ;CONTROLLERS JOB NUMBER
LOMTTY:!BLOCK 1 ;TTY
LOMSIZ==.-GALMSG
DEPHASE
RELOC XX ;RECLAIM SPACE
> ;END OF IFN FTGALAXY
;ERROR CODES:
IPCAC%==1 ;ADDRESS CHECK (UUO BLOCK OR PACKET BUFFER)
IPCNL%==2 ;NOT LONG ENOUGH (UUO BLOCK)
IPCNP%==3 ;NO PACKET IN LIST (READ UNBLOCKED)
IPCIU%==4 ;(PAGE) IN USE (PART OF VIRTUAL FEATURE)(PAGE IS LOCKED)
IPCTL%==5 ;(PACKET) TOO LONG (FOR USER'S BUFFER)
IPCDU%==6 ;DESTINATION UNKNOWN (SEND)
IPCDD%==7 ;DESTINATION DISABLED (SEND)
IPCRS%==10 ;(NO) ROOM (IN) SENDER'S (QUOTA)
IPCRR%==11 ;(NO) ROOM (IN) RECEIVER'S (QUOTA)
IPCRY%==12 ;(NO) ROOM (IN) SYSTEM (STORAGE)
IPCUP%==13 ;UNKNOWN PAGE (SEND) EXISTING PAGE (REC)
IPCIS%==14 ;INVALID SEND ADDRESS
IPCPI%==15 ;PRIVLEGES INSUFFICIENT
IPCUF%==16 ;UNKNOWN FUNCTION
IPCBJ%==17 ;BAD JOB NUMBER
IPCPF%==20 ;PIDTAB FULL
IPCPR%==21 ;PAGED PACKET REQUESTED, REGULAR PACKET IN QUEUE OR VICE VERSA(VM)
IPCIE%==22 ;PAGING IO ERROR (VM)
IPCBI%==23 ;BAD INDEX SPECIFIED FOR SYSTEM PID TABLE
IPCUI%==24 ;UNDEFINED ID IN SYSTEM PID TABLE
;SUBROUTINE TO VALIDATE ARGUMENTS AND FETCH THEM INTO P1-P4.
; SKIP RETURN ON OK, LEAVES ADDR OF ARG IN M.
VALARG: HLRZ T2,T1 ;GET USER'S AC LEFT HALF
CAIGE T2,.IPCFM ;LONG ENOUGH?
JRST ERRNL ;NO.
MOVE P4,T1 ;YES, COPY USER'S AC
HRRI M,.IPCFL(P4) ;FIRST LOCATION OF BLOCK
PUSHJ P,GETWRD## ;FETCH .IPCFL
JRST ERRAC ;ADDRESS CHECK
MOVE P1,T1 ;PUT .IPCFL IN P1
IFE FTVM,<
TRNE T1,IP.CFV ;TRYING TO DO A WHOLE PAGE?
JRST ERRNL ;YES, ERROR
>
PUSHJ P,GETWR1## ;FETCH SENDER'S PID
JRST ERRAC ;ADDRESS CHECK
TLNN P1,IP.IAS ;IS SENDER'S PID INDIRECTED?
JRST VALAR1 ;NO.
HRR M,T1 ;YES, GET ADDRESS
TLNN T1,-1 ;LH = 0?
PUSHJ P,GETWRD## ;YES, FETCH THAT WORD.
JRST ERRAC ;ADDRESS CHECK
VALAR1: MOVE P2,T1 ;PUT .IPCFS IN P2
HRRI M,.IPCFR(P4) ;THIRD LOCATION OF BLOCK
PUSHJ P,GETWRD## ;FETCH RECEIVER'S PID
JRST ERRAC ;ADDRESS CHECK
TLNN P1,IP.IAR ;IS RECEIVER'S PID INDIRECTED?
JRST VALAR2 ;NO.
HRR M,T1 ;YES, PUT ADDRESS IN M
TLNN T1,-1 ;IS LH = 0?
PUSHJ P,GETWRD## ;YES, GET THE WORD.
JRST ERRAC ;ADDRESS CHECK
VALAR2: MOVE P3,T1 ;GET RECEIVER PID
CAMN P3,%IPCFP## ;PUBLIC VALUE FOR [SYSTEM]IPCF?
MOVE P3,PIDTAB## ;YES, CONVERT TO ACTUAL VALUE
HRRI M,.IPCFP(P4) ;FOURTH LOCATION OF BLOCK
PUSHJ P,GETWRD## ;FETCH PACKET DESCRIPTOR
JRST ERRAC ;ADDRESS CHECK
HRRI M,.IPCFL(P4) ;POINT BACK TO FRONT OF BLOCK
MOVE P4,T1 ;PUT .IPCFP IN P4
IFN FTVM,<
TRNN P1,IP.CFV ;ASKING FOR A PAGE?
JRST VALAR3 ;NO
HLRZ T1,P4 ;YES, EXACTLY 1 PAGE?
TLNE P1,IP.TTL ;TRUNCATE IF TOO LONG?
JUMPE T1,VALAR3 ;YES, LENGTH =0 IS OK
CAIE T1,PAGSIZ##
JRST ERRTL ;CANT DO MORE THAN 1 PAGE AT A TIME
HRRZS P4 ;OK, SET LENGTH OF DATA TO 0 (NO DATA WDS IN PACKET)
MOVSI T1,NSHF!NSWP ;LOCKED BITS
SKIPLE T2,JBTSGN##(J) ;DOES JOB HAVE A HIGH SEG
TLNE T2,SHRSEG ;YES, IS IT SHAREABLE
MOVEI T2,0 ;NO HIGH SEG OR NOT SHAREABLE
TDNN T1,JBTSTS##(J) ;LOW SEG LOCKED
TDNE T1,JBTSTS(T2) ;OR HIGH SEG LOCKED
PJRST ERRIU ;YES, GIVE ERROR
HRLI P4,-1
JRST VALAR4
VALAR3:
>
HRRZ T1,P4 ;START ADR
PUSHJ P,CHKADR ;CHECK IT
PJRST ERRAC
HLRE T2,P4
JUMPLE T2,VALAR4 ;OK IF NO DATA WORDS
ADDI T1,-1(T2) ;TOP ADR
PUSHJ P,CHKADR ;CHECK
PJRST ERRAC
VALAR4: MOVSI T1,JP.IPC ;NO PRIV BIT DEFINED
PUSHJ P,PRVBIT## ;IS THIS JOB PRIV?
CAIA ;YES
TRNN P1,-1-IP.CFE-IP.CFV-IP.AKR ;NO, PRIV'D FUNCTION?
AOSA (P) ;NOT PRIV'D FNC, OR JOB HAS PRIVS
JRST ERRPI ;PRIV'D FNC, NON-PRIV'D JOB
PJRST FNDPDS## ;SET UP W AND RETURN
;SUBROUTINE TO ADDRESS CHECK
CHKADR: PUSH P,T1
PUSH P,M ;SAVE M
HRR M,T1
PUSHJ P,GETWRD##
SOS -2(P)
POP P,M
PJRST TPOPJ1##
;SUBROUTINE TO LOAD J AND W BASED ON PID IN T1.
;RETURNS CPOPJ ON ERROR, ERROR CODE IN T1
;RETURNS CPOPJ1 IF OK
VALPID: JUMPE T1,VALPD4 ;ZERO PID IS INVALID
CAIG T1,JOBMAX## ;SEE IF JOB NUMBER
JUMPG T1,VALPD1 ;JOB NO
MOVE T2,T1 ;COPY OF PID
AND T2,%IPCPM## ;MASK TO INDEX
CAMGE T2,%IPCMP## ;IN RANGE?
SKIPN T2,PIDTAB##(T2) ;YES, PICK UP ENTRY.
JRST VALPD4 ;NO ENTRY HERE
MOVE T3,T2 ;SAVE IT FOR LATER
XOR T2,T1 ;CLEAR BITS IN COMMON
TDZ T2,%IPCPM## ;CLEAR UNWANTED BITS
JUMPN T2,VALPD4 ;SEQ # ARE THE SAME IF 0
AND T3,%IPCPM ;GET JOB NUMBER
SKIPA J,T3 ;SET J
VALPD1: MOVE J,T1
JUMPE J,VALPD3 ;EXECUTIVE PROCESS
PUSHJ P,FNDPDB## ;FIND JOB'S PDB
JRST VALPD4 ;NONE - PID IS BAD
VALPD2: MOVE T2,.PDIPQ##(W) ;GOOD--CHECK QUOTA FOR SET UP
TLON T2,IP.HBS ;HAS QUOTA BEEN SET?
HRR T2,%CNIPQ## ;NO, SET IT TO DEFAULT VALUE
MOVEM T2,.PDIPQ##(W)
PJRST CPOPJ1## ;AND GIVE GOOD RETURN
VALPD3: HLRZ W,T1 ;POINT TO EXECUTIVE PROCESS CTL BLK
HRLS W ;SAVE LOC OF EXEC CTL BLOCK
SUBI W,.PDIPC## ;FIX OFFSET SO .PDXXX POINTS TO .EPXXX
JRST VALPD2
;HERE ON ERROR
VALPD4: MOVEI T1,IPCIS% ;ERROR CODE
POPJ P,
;ERROR ROUTINES. THESE LOAD IPCXX% INTO T1 FOR EACH ERRXX.
; ERROR ROUTINES ARE CALLED VIA PUSHJ, BUT THEY NEVER RETURN.
;THE POSITION RELATIVE TO ERRAC DEFINES THE ERROR VALUE.
ERCODE ERRAC,IPCAC% ;(1) ADDRESS CHECK
ERCODE ERRNL,IPCNL% ;(2) NOT LONG ENOUGH
ERCODE ERRNP,IPCNP% ;(3) NO PACKET IN QUEUE
ERCODE ERRIU,IPCIU% ;(4) PAGE IN USE (VIRTUAL FEATURE)
ERCODE ERRTL,IPCTL% ;(5) PACKET TOO LONG
ERCODE ERRDU,IPCDU% ;(6) DESTINATION UNKNOWN
ERCODE ERRDD,IPCDD% ;(7) DESTINATION DISABLED
ERCODE ERRRS,IPCRS% ;(10) NO ROOM IN SENDER'S QUOTA
ERCODE ERRRR,IPCRR% ;(11) NO ROOM IN RECEIVER'S QUOTA
ERCODE ERRRY,IPCRY% ;(12) NO ROOM IN SYSTEM FOR PACKET
ERCODE ERRUP,IPCUP% ;(13) UNKNOWN PAGE (SEND) OR ALREADY EXISTING (REC)
ERCODE ERRIS,IPCIS% ;(14) INVALID SENDER'S ADDRESS
ERCODE ERRPI,IPCPI% ;(15) INSUFFICIENT PRIVILEGES
ERCODE ERRUF,IPCUF% ;(16) - UNKNOWN FUNCTION
ERCODE ERRBJ,IPCBJ% ;(17) - BAD JOB NUMBER
ERCODE ERRPF,IPCPF% ;(20) - PIDTAB FULL
ERCODE ERRPR,IPCPR% ;(21) - PAGE REQUESTED, NOT-A-PAGE IN QUEUE
ERCODE ERRIE,IPCIE% ;(22) - PAGING IO ERROR
ERCODE ERRBI,IPCBI% ;(23) - BAD INDEX FOR .GTSID
ERCODE ERRUI,IPCUI% ;(24) - UNDEFINED ID REQUESTED
SUBTTL IPCFR - RECEIVE UUO
UIPCFR::PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,T1 ;SAVE USER ARG ON THE STACK
PUSHJ P,VALARG ;LOAD ARGS
JRST [POP P,(P) ;BRING STACK INTO PHASE
POPJ P,] ;AND RETURN
POP P,T4 ;RESTORE T1 INTO T4
HLRZS T4 ;JUST NEED THE LENGTH
IPFR1: HLRZ P2,.PDIPC##(W) ;POINTER TO OLDEST PACKET
JUMPE P2,IPFR7 ;NONE.
HRRZ T1,.IPCFL(P2) ;GET FLAG WORD
TRNE T1,IP.CFV ;PAGED PACKET?
TRZE P1,IP.CFV ;MUST HAVE REQUESTED A PAGE
TRNE P1,IP.CFV ;ERR IF REQUESTED A PAGE
JRST ERRPR ;WRONG MODE
MOVE P3,T1
TRNN P1,IP.SIP ;IS CALLER PRIV AND ASKING FOR PRIVS?
TRZ T1,IP.SIP ;NO, HE DOESNT CARE IF PACKET PRIV
HLRZ T2,P4 ;SPACE PROVIDED
HLRZ T3,.IPCFP(P2) ;LENGTH OF PACKET
SUB T3,T2
SKIPG T3 ;LONG ENOUGH?
TLZA P1,IP.TTL ;YES, CLEAR TTL BIT
TLO T1,IP.TTL ;NO, SET TTL IN UUO BLOCK
PUSHJ P,PUTWDU## ;STORE IN USER'S ARG BLOCK
MOVE T1,.IPCFS(P2) ;GET SENDER'S PID
PUSHJ P,PUTWD1## ;STORE SENDER'S PID
MOVE T1,.IPCFR(P2) ;RECEIVER'S PID
PUSHJ P,PUTWD1## ;STORE RECEIVER'S PID
TLNN P1,IP.TTL ;TRUNCATE IF TOO LONG?
JUMPG T3,ERRTL ;NO, ERROR IF TOO LONG
;COME HERE TO COPY PACKET TO USER'S CORE.
MOVE T1,.IPCFP(P2) ;LENGTH IN LH
HRR T1,P4 ;HDR
IFN FTVM,<
TRNE P3,IP.CFV
HRLI T1,PAGSIZ## ;WHOLE PAGE
>
TLNE P1,IP.TTL ;PACKET TOO LONG?
HLL T1,P4 ;YES, TELL TRUNCATED LENGTH
PUSHJ P,PUTWD1## ;TELL USER THE LENGTH
MOVE T1,.IPCFU(P2) ;GET SENDER'S PPN
CAILE T4,.IPCFU ;DID HE ASK FOR IT?
PUSHJ P,PUTWD1## ;YES, GIVE IT TO HIM
MOVE T1,.IPCFC(P2) ;GET CAPABILITIES WORD
CAILE T4,.IPCFC ;DID HE ASK FOR IT ALSO?
PUSHJ P,PUTWD1## ;YES, GIVE IT TO HIM
HLRE T1,.IPCFP(P2) ;LENGTH
TLNE P1,IP.TTL ;TOO LONG?
HLRE T1,P4 ;YES, JUST FILL HIS BLOCK
JUMPLE T1,IPFR4 ;NOTHING TO STORE IF 0 WDS IN PACKET
HRRI M,-1(P4) ;USER'S ADDRESS
MOVN T2,T1 ;FORM AOBJN WORD
HRLZS T2
HRR T2,P2 ;ADR OF PACKET
IPFR3: MOVE T1,.IPCFD(T2) ;FETCH DATA FROM EXEC
PUSHJ P,PUTWD1## ;STORE IN USER'S AC
AOBJN T2,IPFR3 ;COPY WHOLE PACKET
IPFR4:
IFN FTVM,<
TRNN P3,IP.CFV ;WHOLE PAGE?
JRST IPFR5 ;NO
TLNE P1,IP.TTL ;TOO LONG?
JRST [HRRZ T2,.IPCFP(P2) ;YES, DELETE THE PAGE
PUSHJ P,IPCDEL##
JRST IPFR5]
HRRZ T1,P4 ;NO, GET VIRTUAL PAGE NO
HRRZ T2,.IPCFP(P2) ;DSK OR CORE ADR
JUMPE T2,ERRIE ;ERROR PAGING OUT THE PAGE
PUSHJ P,IPCINS## ;PUT PAGE INTO THIS MAP
JRST [JUMPE T1,ERRUP ;T1=0 IF NO SUCH PAGE
JRST ERRIE] ;OTHERWISE PAGING IO ERROR
IPFR5:>
;COME HERE TO DECREMENT RECEIVER'S AND SENDER'S COUNTERS,
; FREE EXEC COPY OF PACKET, ETC. NO ERROR EXITS ARE
; PERMITTED BEYOND THIS POINT SINCE EXEC INFORMATION IS
; ALTERED.
HLRZ T1,.IPCFL(P2) ;POINTER TO NEXT BLOCK
HRLM T1,.PDIPC##(W) ;MAKE IT THE OLDEST
JUMPE T1,IPFR5A
HLL T1,.IPCFP(T1) ;LENGTH OF NEXT PACKET
HRR T1,.IPCFL(T1) ;FLAGS FOR NEXT PACKET
IFN FTVM,<
TRNE T1,IP.CFV ;PAGE?
HRLI T1,PAGSIZ## ;YES, SET LENGTH
>
IPFR5A: PUSHJ P,STOTAC## ;RETURN INFO ABOUT NEXT PACKET IN AC
HLRE T1,.IPCFP(P2) ;GET LENGTH OF THIS BLOCK
IFN FTVM,<
SKIPGE T1 ;PAGE?
SETZ T1, ;YES, NO DATA WORDS
>
ADDI T1,.IPCFD ;PLUS OVERHEAD WORDS
HRRZ T2,P2 ;ADDRESS
PUSH P,.IPCFS(P2) ;SAVE SENDERS PID
PUSHJ P,GIVWDS## ;FREE THE PACKET SPACE
SOS .PDIPC##(W) ;DEC COUNT OF PACKETS WAITING
AOS T1,.PDIPA##(W) ;INCR RECEIVE COUNT
TRNN T1,-1
SOS .PDIPA##(W) ;OVERFLOW, COUNT IT DOWN AGAIN
;NOW MOVE TO THE SENDER'S ENVIRONMENT TO DECREMENT THE
; COUNT OF HIS UNRECEIVED SENDS. SENDER'S PID HAS BEEN
; KEPT IN P1 FROM WAY BACK.
POP P,T1 ;SENDERS PID
MOVE T2,T1 ;IS SENDER A SYSTEM PROCESS?
AND T2,%IPCPM##
CAIGE T2,%IPCNS##
TDZA T2,T2 ;YES, DON'T USE .IPCFC
LDB T2,TRNPT2 ;IF TURNED-AROUND MSG THE PID
SKIPE T2 ; MAY HAVE BEEN DESTROYED,
MOVE T1,T2 ;SO GET W FROM JOB NUMBER
PUSH P,J ;SAVE J
PUSHJ P,VALPID ;SET UP J & W
JRST IPFR6 ;NO GOOD, SENDER MUST BE GONE.
MOVNI T1,IP.SBT ;DECREMENT COUNT OF PACKETS SENT BUT
MOVE T2,.PDIPC##(W) ;ANY SEND-COUNT OUTSTANDING?
TRNE T2,777000 ; (SEND FROM JOB-NO,LOGOUT;NEW JOB SAME SLOT)
ADDM T1,.PDIPC##(W) ; NOT YET RECEIVED
IPFR6: SOSL %CNIIP## ;DEC COUNT OF PACKETS OUTSTANDING
PJRST JPOPJ1##
STOPCD .+1,DEBUG,PCN, ;++PACKET COUNT NEGATIVE
SETZM %CNIIP## ;CONTINUED - ZERO COUNT SO WONT STOP AGAIN
PJRST JPOPJ1## ;RESTORE J AND SKIP-RETURN
;COME HERE IF THERE IS NO PACKET IN THE USER'S LIST.
IPFR7: JUMPL P1,ERRNP ;BIT 0 = DONT BLOCK
MOVSI T1,IPCACE## ;FLAG HIBERNATING FOR IPCF
IORB T1,JBTRTD##(J)
MOVEI T1,SLPQ## ;PUT JOB IN SLEEP QUEUE
DPB T1,PJBSTS##
PUSHJ P,CLRIPT## ;ZAP IN-CORE PROTECT SO JOB CAN BE SWAPPED
PUSHJ P,WSCHED## ;WAIT FOR AWAKENING
IFN FTPI,<
MOVEI T1,(JFCL)
XCT NOPISK## ;IF PSISER INSTALLED
HLRZ T1,@JBTPIA##(J) ;PICK UP INTERRUPT INSTRUCTION
CAIN T1,(JFCL) ;SKIP IF INTERRUPT PENDING
>
JRST IPFR1 ;GO TRY AGAIN.
IFN FTPI,<
SOS JOBPD1##(R) ;BACK UP USER PC
POPJ P, ;EXIT SO INTERRUPT WILL HAPPEN
>
SUBTTL IPCFS - SEND UUO
UIPCFS::PUSHJ P,SAVE4## ;SAVE P1-P4
PUSHJ P,VALARG ;LOAD ARGS
POPJ P, ;WRONG
MOVE T2,.PDIPQ##(W) ;CHECK FOR QUOTA NOT SET
TLON T2,IP.HBS ;HAS QUOTA BEEN SET?
HRR T2,%CNIPQ ;NO, SET TO DEFAULT VALUE
MOVEM T2,.PDIPQ##(W)
LDB T1,[POINT 9,T2,26] ;SEND QUOTA
LDB T2,[POINT 9,.PDIPC##(W),26] ;SEND COUNT
TLNE P1,IP.LPC ;"LAST PHONE CALL"?
ADDI T1,1 ;YES, ADD 1 TO QUOTA
CAMG T1,T2 ;QUOTA DEPLETED?
JRST ERRRS ;YES, DON'T SEND
JUMPN P3,IPCS0 ;IF REC'R FIELD IS 0,
SKIPN P3,.PDIPI##(W) ; SEND MSG TO [SYSTEM]INFO FOR THIS JOB
MOVE P3,%SIINF## ; (LOCAL OR GLOBAL)
JUMPE P3,ERRDU ;DESTINATION UNKNOWN IF NO [SYSTEM]INFO
;COME HERE TO VALIDATE SENDER'S PID
IPCS0: JUMPN P2,IPCS3 ;"SENDER'S PID" SPECIFIED?
MOVN T1,%IPCMP## ;NO, FIND A DEFAULT PID
HRLZS T1
SKIPN T2,PIDTAB##(T1) ;SEARCH FOR A VALID PIDTAB ENTRY
IPCS1: AOBJN T1,.-1
JUMPGE T1,IPCS2 ;DONE, NO PIDS FOR THIS JOB
AND T2,%IPCPM## ;ISOLATE JOB NO.
CAME T2,J ;THIS JOB?
JRST IPCS1 ;NO.
MOVE P2,PIDTAB##(T1) ;PUT ENTRY IN P2
ANDCM P2,%IPCPM## ;REMOVE JOB NUMBER
TROA P2,(T1) ;INCLUDE PID INDEX
IPCS2: MOVE P2,J ;NO PIDS, USE JOB NUMBER
IPCS3: PUSH P,J ;SAVE J
MOVE T1,P2 ;GET SENDER'S PID
PUSHJ P,VALPID ;CHECK OUT SENDER
JRST [TRNE P1,IP.SIP ;PRIV'D?
JRST IPCS4 ;YES, OK (TURNING AROUND A MSG CAUSE REC'R DIED)
POP P,J ;NO - INVALID SENDER
JRST ERRIS]
SUB J,(P) ;PID IS LEGAL, IS IT HIS?
TRNN P1,IP.SIP ;IF SENDER ISN'T PRIV'D,
JUMPN J,[POP P,J
PJRST ERRIS] ; SEND MUST BE FROM HIS JOB
;COME HERE TO VALIDATE RECEIVER
IPCS4: MOVE T1,P3 ;PUT PID INTO T1
PUSHJ P,VALPID ;SET UP J AND W
JRST [POP P,J ;RESTORE J
JRST ERRDU] ;DESTINATION UNKNOWN
POP P,J ;RESTORE J (REAL JOB NO OF SENDER)
;COME HERE TO CHECK THAT THE THE RECEIVER'S QUOTA IS NOT
; EXHAUSTED AND THAT THE RECEIVER IS NOT DISABLED.
LDB T1,[POINT 9,.PDIPC(W),35] ;RECEIVE COUNT
LDB T2,[POINT 9,.PDIPQ(W),35] ;RECEIVE QUOTA
CAML T1,T2 ;QUOTA EXHAUSTED?
JRST ERRRR
SKIPGE .PDIPQ##(W) ;NO, IS RECEIVER DISABLED?
JRST ERRDD
HLRE T2,P4 ;GET DATA LENGTH
CAMLE T2,%CNIPL## ;TOO LONG?
JRST [TLNN P1,IP.LPK ;TRYING TO SEND A LONG MESSAGE?
JRST ERRTL ;NO, PACKET IS TO LONG
MOVSI T1,JP.IPC ;YES, REQUIRES PRIVILEGES
PUSHJ P,PRVBT## ;PRIVILEGED?
JRST IPCS4B ;YES, PROCEED
JRST ERRTL] ;NO
JUMPN T2,IPCS4B
TRNN P1,IP.CFV
TRO P1,IP.CFZ
IPCS4B: ADDI T2,.IPCFD ;NO, GET ROOM TO HOLD BLOCK
PUSHJ P,GETWDS## ;IN EXEC CORE
JRST ERRRY ;NO ROOM.
TRNE P1,70 ;SENDER FIELD 0?
JRST IPCS4A
CAMN P2,%SIINF## ;YES, SENDER =[SYSTEM]INFO?
TRO P1,20 ;YES
CAMN P2,.PDIPI##(W) ;SENDER=LOCAL[SYSTEM]INFO?
TRO P1,30 ;YES
IPCS4A: HRRZM P1,.IPCFL(T1) ;STORE FLAGS (LH=INTERNAL POINTER)
MOVEM P2,.IPCFS(T1) ;STORE SENDER'S PID (FUDGED)
MOVEM P3,.IPCFR(T1) ;STORE RECEIVER'S PID
HLLZM P4,.IPCFP(T1) ;STORE LENGTH (RH RESERVED)
MOVE T3,JBTPPN##(J) ;GET SENDER'S PPN
MOVEM T3,.IPCFU(T1) ;SAVE IT
PUSHJ P,IPCSCA ;STORE CAPABILITIES
HRRI M,-1(P4) ;POINTER TO BLOCK IN USER CORE
MOVE P3,T1 ;COPY ADDR OF CORE BLOCK
HLLZ P2,P4 ;FORM AOBJN WORD
JUMPE P2,IPCS6 ;DONT STORE DATA IF LENGTH=0
MOVNS P2
HRR P2,T1
IPCS5: PUSHJ P,GETWD1## ;GET WORD FROM USER CORE
MOVEM T1,.IPCFD(P2) ;STORE DATA WORD
AOBJN P2,IPCS5 ;COPY WHOLE BLOCK
;COME HERE WITH P3 POINTING TO A BLOCK IN EXEC CORE
; CONTAINING THE UUO ARGS AND THE DATA. MOVE TO RECEIVER'S
; ENVIRONMENT AND PUT THE PACKET ON HIS LIST.
IPCS6:
IFN FTVM,<
TRNN P1,IP.CFV
JRST IPCS7 ;NOT A PAGE
HRRZ T1,P4 ;PAGE - GET ITS VIRTUAL PAGE NUMBER
PUSHJ P,IPCRMV## ;REMOVE FROM SENDERS MAP
JRST [HRRZ T2,P3 ;ERROR - GET ADR OF 4-WD BLOCK
MOVEI T1,.IPCFD ;LENGTH OF BLOCK
PUSHJ P,GIVWDS## ;RETURN THE SPACE
JRST ERRUP] ;AND ERROR RETURN
MOVE P2,T2 ;SAVE CORE ADR
TRNE T2,400000 ;PAGE ON DSK?
JRST IPCS6C ;YES
MOVE T1,.IPCFR(P3) ;RECEIVER
PUSHJ P,VALPID ;SET UP J AND W
JRST IPCS6A ;SHOULD NEVER HAPPEN
SKIPGE T1,JBTSTS##(J) ;JOB RUNNING?
TLNE T1,SWP ; AND IN CORE?
JRST IPCS6A ;NO, PAGE THE PAGE OUT
IFN FTLOCK,<
SKIPN T1,LOCK## ;ALWAYS PAGE IT IF SOMEONE IS LOCKING
>
HLRZ T1,.PDIPC##(W) ;YES
JUMPN T1,IPCS6A ;PAGE OUT PACKET IF WONT BE FIRST ON 0
MOVSI T1,IPCACE## ;1ST IN QUEUE, IS REC'R HIBERING FOR IPC?
TDNE T1,JBTRTD##(J)
JRST IPCS6D ;YES, DONT PAGE OUT THE PAGE
IFN FTPI,<
HRROI T1,C$IPC ;NO, IS HE PSI'ING FOR IPC?
PUSHJ P,PSITST##
JRST IPCS6A ;NOT ENABLED, PAGE OUT THE PAGE
> ;END IFN FTPI
;ENABLED OR HIBERING FOR THE PAGE, SEE IF ROOM IN CORE
IPCS6D: MOVE T1,MAXMAX## ;TOTAL USER CORE ON SYSTEM
SUB T1,CORMAX## ;MAX SIZE A JOB CAN BECOME
LSH T1,W2PLSH## ;NUMBER OF PAGES AVAILABLE FOR IPCF
MOVE T2,%CNPIC## ;NUMBER OF PAGES IN USE BY IPCF
ADDI T2,1 ;NUMBER WHICH WILL BE IN USE
CAMLE T2,T1 ;ENOUGH ROOM?
JRST IPCS6A ;NO, PAGE OUT THE PAGE
MOVEM T2,%CNPIC## ;IPCF PAGES IN CORE
JRST IPCS6C ;LEAVE THE PAGE IN CORE
IPCS6A: MOVE J,.C0JOB## ;RESTORE J
MOVE T2,P2
PUSHJ P,IPCPAG## ;PAGE OUT THE PAGE
MOVEI T2,0 ;PAGING I/O ERROR
MOVE P2,T2
IPCS6C: HRRM P2,.IPCFP(P3) ;SAVE DSK ADR IN THE PACKET
IPCS7:> ;END FTVM
MOVEI T2,.PDIPC##-.IPCFL(W) ;PRESET PREDECESSOR
IPCS8: HLRZ T1,.IPCFL(T2) ;NEXT PACKET IN QUEUE
JUMPE T1,IPCS9 ;END OF QUEUE IF 0
MOVE T2,T1 ;NOT END, STEP TO NEXT
JRST IPCS8
IPCS9: HRLM P3,.IPCFL(T2) ;SAVE THIS PACKET ON END OF QUEUE
;COME HERE AFTER THE PACKET IS ON THE RECEIVER'S LIST.
AOS .PDIPC##(W) ;INC COUNT
MOVE T1,.IPCFS(P3) ;SENDER (MIGHT NOT BE SAME J)
PUSHJ P,VALPID ;SET UP (PRIV'D JOB CAN SEND FROM ANOTHER JOB)
PJRST IPCS9A ;BAD - TURNING AROUND MSG TO A DROPPED PID
MOVEI T1,IP.SBT ;INCREMENT SEND COUNT
ADDM T1,.PDIPC##(W)
HLRZ T1,.PDIPA##(W) ;COUNT OF SEND UUOS
ADDI T1,1
TRNE T1,-1 ;OVERFLOW?
HRLM T1,.PDIPA##(W) ;NO, STORE INCREMENTED COUNT
IPCS9A: AOS %CNIIP## ;INCREMENT OUTSTANDING PACKETS
AOS %CNIPS## ;INCREMENT SENT PACKETS
;COME HERE TO AWAKEN A USER JOB OR PUSHJ TO AN EXEC PROCESS
; THAT HAS JUST HAD A PACKET ARRIVE ON ITS LIST.
MOVE T1,.IPCFR(P3) ;RECEIVER'S PID
PUSHJ P,VALPID ;SET UP J AND W
PJRST CPOPJ1## ;SHOULD NEVER HAPPEN
JUMPE J,EXECPR ;SPECIAL HANDLING FOR EXEC PROCESS
PUSHJ P,WAKEUP
PJRST CPOPJ1## ;AND GIVE SKIP RETURN
;SUBROUTINE TO STORE CAPABILITIES OF THE SENDER
;CALLING SEQUENCE:
; MOVEI T1,ADDRESS OF THE PACKET HEADER
; MOVE J,JOB NUMBER OF THE SENDER
; PUSHJ P,IPCSCA
;ALWAYS RETURN CPOPJ
IPCSCA: MOVE T4,J ;CLEAR CAPABILITIES
MOVE T3,JBTSTS##(J) ;GET JBTSTS
TLNE T3,JACCT ;SENDER HAS JACCT?
TLO T4,IP.JAC ;YES
TLNE T3,JLOG ;SENDER HAS JLOG?
TLO T4,IP.JLG ;YES
TRNE T3,JS.XO ;IS SENDER XCT ONLY?
TLO T4,IP.SXO ;YUP!
MOVE T3,JBTPRV##(J) ;GET JBTPRV WORD
TLNE T3,JP.POK ;CAN SENDER POKE MONITOR?
TLO T4,IP.POK ;YES,
TLNE T3,JP.IPC ;DOES HE HAVE IPCF PRIVS?
TLO T4,IP.IPC ;YES
MOVEM T4,.IPCFC(T1) ;AND STORE SENDER'S CAPABILITIES
POPJ P, ;RETURN
;COME HERE IF EXEC PROCESS.
EXECPR: HLRZ T1,W ;NON-OFFSET LOC OF EXEC CTL BLOCK
PUSHJ P,@.EPADR(T1) ;CALL THE PACKET HANDLER
PJRST CPOPJ1## ;GIVE SKIP-RETURN
WAKEUP:
PUSHJ P,WAKEJB## ;YES, AWAKEN IT.
IFN FTPI,<
SIGNAL C$IPC ;SIGNAL MESSAGE AVAILABLE
PUSHJ P,STRSIG
>;END IFN FTPI
POPJ P,
IFN FTPI,<
;SUBROUTINE TO STORE REASON WORD IN INTERRUPT VECTOR
STRSIG::MOVE T1,JBTPDB##(J) ;PDB LOC
MOVEI T2,0 ;IN CASE NO PACKETS
HLR T1,.PDIPC##(T1) ;LOC OF 1ST PACKET
JUMPE T1,STRSG1
MOVE T2,.IPCFP(T1) ;LENGTH OF TOP PACKET TO LH
HRR T2,.IPCFL(T1) ;FLAGS
IFN FTVM,<
TRNE T2,IP.CFV ;PAGE?
HRLI T2,PAGSIZ## ;YESM LENGTH = 1 PAGE
>
STRSG1: EXCTXU <MOVEM T2,3(M)> ;STORE LEN,,FLAGS
POPJ P, ; AND RETURN
>
SUBTTL IPCFQ - QUERY UUO
UIPCFQ::HRR M,T1 ;ADDRESS OF UUO BLOCK
HLRZ T4,T1 ;SAVE COUNT
PUSHJ P,GETWRD ;GET WORD 0
JRST ERRAC
MOVE T3,T1 ;SAVE PRIV BIT
HLRZ T2,.PDIPC##(W) ;IS THERE A PACKET?
SKIPE T1,T2 ;NO
HRRZ T1,.IPCFL(T2) ;YES, PASS INFO TO CALLER
TRNN T3,IP.SIP ;IS HE PRIV?
TRZ T1,IP.SIP ;NO, SUPPRESS PRIV BIT IN PACKET
PUSHJ P,PUTWRD## ;STORE .IPCFL
JRST ERRAC ;ADDRESS CHECK.
SKIPE T1,T2
MOVE T1,.IPCFS(T2) ;SENDER'S PID
PUSHJ P,PUTWR1## ;STORE SENDER'S PID
JRST ERRAC
SKIPE T1
MOVE T1,.IPCFR(T2) ;RECEIVER'S PID
PUSHJ P,PUTWR1## ;STORE RECEIVER'S PID
JRST ERRAC ;ADDRESS CHECK
JUMPE T1,IPCFQ2
LDB T1,[POINT 9,.PDIPC##(W),35] ;COUNT
IFN FTVM,<
MOVE T3,.IPCFL(T2) ;FLAGS
TRNE T3,IP.CFV ;PAGE?
TLOA T1,PAGSIZ## ;YES, LENGTH = 1 PAGE
>
HLL T1,.IPCFP(T2) ;LENGTH
IPCFQ2: PUSHJ P,PUTWR1## ;STORE IN USER'S CORE
JRST ERRAC ;ADDRESS CHECK
MOVE T1,.IPCFU(T2) ;GET SENDERS PPN
CAIG T4,.IPCFU ;DID HE ASK FOR IT?
PJRST CPOPJ1## ;NO, JUST RETURN
PUSHJ P,PUTWR1## ;YES, GIVE IT TO HIM
JRST ERRAC
MOVE T1,.IPCFC(T2) ;GET SENDERS PRIVS
CAIG T4,.IPCFC ;DID HE ASK FOR THEM?
PJRST CPOPJ1## ;NO, RETURN
PUSHJ P,PUTWR1## ;YES, GIVE THEM TO HIM
JRST ERRAC
PJRST CPOPJ1## ;SKIP RETURN TO USER
SUBTTL [SYSTEM]IPCF - THE EXEC PROCESS
IPCFPR::PUSHJ P,SAVE3##
IPCF1: TLO M,400000 ;SET SO ERR WONT CALL STOTAC
PUSHJ P,GETPAK ;GET OLDEST PACKET
POPJ P, ;NONE, EXIT.
HRRZ P1,T1 ;PACKET ADDRESS
HRRZ T4,.IPCFD(P1) ;PICK UP CODE (WORD 0)
IFN FTVM,<
MOVE T1,.IPCFL(P1) ;PASSING A PAGE TO [SYSTEM] IPCF?
TRNN T1,IP.CFV ;YES, THAT ISN'T LEGAL
>
CAILE T4,IPCFM ;VALID?
SKIPA T4,BADCOD ;NO, SET FOR ERROR
MOVE T4,BADCOD(T4) ;YES, GET DISPATCH ADR
MOVE T1,.IPCFS(P1) ;SENDER
HLRZ T2,.IPCFP(P1) ;LENGTH
MOVE T3,.IPCFL(P1) ;FLAGS
TRNE T3,1 ;TURNED-AROUND MSG?
JRST IPCF3 ;YES, JOB MUST HAVE LOGGED OUT
PUSH P,W ;PRESERVE W
TRNN T3,400000 ;JOB HAVE PRIV'S?
JUMPL T4,PRVERR ;NO, ERROR IF FUNCTION REQUIORES PRIVS
LDB P2,[POINT 3,T4,17] ;GET NEEDED LENGTH OF UUO BLOCK
CAIGE T2,(P2) ;UUO BLOCK LONG ENOUGH?
JRST SHRTER ;NO, ERROR
PUSHJ P,(T4) ;DISPATCH
IPCF2: DPB T1,[POINT 6,.IPCFL(P1),29] ;BAD - STORE ERROR CODE IN FLAG WORD
PUSHJ P,DECSND ;DECREMENT SENDER'S COUNTS
POP P,W ;RESTORE W
;IN ORDER FOR THE JOB TO RECEIVE THE MSG IT MUST BE ENABLED
;ANSWER WILL THUS ENABLE THE JOB. IN ORDER TO PREVENT THIS
;BIT 0 OF P1 MUST BE LIT BY THE SUBROUTINE (DISABLE FUNCTION)
PUSHJ P,ANSWER ;TURN PACKET AROUND TO USER
JRST IPCF1 ;AND CHECK FOR ANOTHER.
;SUBROUTINE TO GET POINTER TO PACKET INTO T1.
GETPAK: HLRZ T1,.PDIPC##(W) ;POINTER OR ZERO
JUMPE T1,CPOPJ## ;NONE.
PJRST CPOPJ1## ;HAVE ONE - SKIP RETURN
;DISPATCH ERRORS -
SHRTER: SKIPA T1,[IPCNL%] ;UUO BLOCK NOT LONG ENOUGH
PRVERR: MOVEI T1,IPCPI% ;PRIV'S INSUFFICIENT
JRST IPCF2 ;STORE ERROR CODE IN PACKET AND ANSWER
IPCF3: HLRZ T1,.IPCFL(P1) ;NEXT PACKET
HRLM T1,.PDIPC##(W) ;MAKE IT THE OLDEST
SOS .PDIPC##(W) ;FIX UP THE COUNTS
PUSH P,W
LDB T1,TRNPTR ;SENDER JOB NO
PUSHJ P,VALPID ;SET W
JRST IPCF4 ;OOPS, HE REALLY IS GONE
MOVNI T1,IP.SBT
MOVE T2,.PDIPC##(W) ;ANY SENDS NOT YET REC'D?
TRNE T2,777000
ADDM T1,.PDIPC##(W) ;YES, DECREMENT COUNT
IPCF4: POP P,W
PUSHJ P,REMPAK ;GET RID OF THIS PACKET
JRST IPCF1 ;AND GO LOOK AT NEXT PACKET
;SUBROUTINE TO DECREMENT COUNT OF PACKETS SENT BUT NOT RECEIVED
DECSND: MOVE T1,.IPCFS(P1) ;SENDERS PID
PUSHJ P,VALPID ;GET W
TDZA T1,T1 ;SHOULDN'T HAPPEN
MOVNI T1,IP.SBT ;DEC COUNT OF SENT BUT NOT
ADDM T1,.PDIPC##(W) ; REC'D PACKETS FOR SENDER
POPJ P, ;RETURN
DECSSW: PUSH P,W
PUSHJ P,DECSND
JRST WPOPJ##
;DISPATCH TABLE FOR [SYSTEM]IPCF
;EACH SUBROUTINE IS CALLED WITH P1 POINTING TO THE PACKET
; IN EXEC STORAGE
;P2-P4 ARE AVAILABLE FOR USE
;T1=PID OF SENDER T2=LENGTH OF DATA T3=FLAGS
;W AND J ARE SET UP FOR RECEIVER, BUT MAY BE CHANGED
BADCOD: EXP ERRUF ;(BAD CODE) - UNKNOWN FNCTN
IPCFTB: XWD 000000,ENABL ;(1)ENABLE
XWD 000000,DISAB ;(2)DISABLE
XWD 000003,WHOIS ;(3)TELL PID OF [SYSTEM]INFO
XWD 400003,MKINFO ;(4)MAKE [SYSTEM]INFO
XWD 400002,DESTRY ;(5)DESTROY A PID
XWD 400003,CREATE ;(6)CREATE A PID
XWD 400003,QUOTA ;(7) SET QUOTA
XWD 400003,OWNER ;(10)CHANGE OWNERSHIP OF A PID
XWD 000003,JOBNO ;(11)FIND JOB NUBER FOR A PID
XWD 000004,RDPIDS ;(12)FIND PID(S) FOR A JOB
XWD 000003,RDQTA ;(13)FIND QUOTA FOR A JOB
XWD 400002,CPOPJ1## ;(14)WAKE UP JOB HIB'ING FROM RESET
IPCFRF: EXP ERRUF ;(15)SENT BY IPCF ON RESET
EXP ERRUF ;(16)
EXP ERRUF ;(17)
EXP ERRUF ;(20)
EXP ERRUF ;(21)
EXP ERRUF ;(22)
EXP ERRUF ;(23)
XWD 400003,SIDSET ;(24)SET SYSTEM PID TABLE
XWD 000003,SIDRD ;(25)READ SYSTEM PID TABLE
IPCFSM: EXP ERRUF ;(26)SPOOL MSG SENT "TO" QUASAR
IPCFLM: EXP ERRUF ;(27)LOGOUT MESSAGE SENT "TO" QUASAR
IPCFTM: EXP ERRUF ;(30)TAPE LABELING MESSAGE
IPCFUO: EXP ERRUF ;(31)MOUNTABLE UNIT ON-LINE
IPCFON: EXP ERRUF ;(32)LOGON MESSAGE SENT "TO" QUASAR
IPCFAC: EXP ERRUF ;(33)ACCOUNTING MESSAGES
.IPCTL==:IPCFTM-IPCFTB+1
.IPCUO==:IPCFUO-IPCFTB+1
IPCFM==.-IPCFTB ;LENGTH OF TABLE
;SUBROUTINE TO GIVE ANSWER TO AN EXEC CALL
ANSWER: MOVEI T2,1
REPEAT 0,< ;NOT NEEDED TILL OTHER EXEC PROCESSES EXIST
CAMN T1,PIDTAB## ;SENDER = [SYSTEM]IPCF?
>
;ENTER HERE TO INDICATE MESSAGE SENT BY OTHER THAN IPCC (SENDER'S CODE IN T2)
ANSWE1: MOVE T1,.IPCFR(P1) ;SWITCH SENDER & RECEIVER
DPB T2,[POINT 3,.IPCFL(P1),32] ;TELL REC'R THAT MSG IS FROM IPCF
EXCH T1,.IPCFS(P1)
MOVEM T1,.IPCFR(P1)
IFN FTVM,<
MOVE T1,.IPCFL(P1) ;IF A WHOLE PAGE PASSED,
TRNN T1,IP.CFV ; DON'T CLEAR ITS ADDRESS
>
HLLZS .IPCFP(P1) ;ZERO PACKET ADR
HLRZ T1,.IPCFL(P1) ;POINTER TO NEXT PACKET
HRLM T1,.PDIPC##(W) ;MAKE IT THE OLDEST.
SETZM .IPCFC(P1) ;CLEAR FLAG WRDS ON SEND FROM
SETZM .IPCFU(P1) ; AN EXEC PROCESS
PUSHJ P,SNDMSG ;RETURN PACKET TO SENDER OF ORIGINAL MSG
PUSHJ P,REMPAK ;COULDNT DO IT - REMOVE THE PACKET
SOS .PDIPC##(W)
AOS T1,.PDIPA##(W) ;COUNT OF RECEIVES SINCE LOGIN
TRNN T1,-1 ;OVERFLOW?
SOS .PDIPA##(W) ;YES, SET IT BACK
POPJ P, ;AND RETURN TO CALLER
;SUBROUTINE TO REMOVE THE OLDEST PACKET.
REMPAK::HRRZ T2,P1 ;ADR OF PACKET TO REMOVE
SOS %CNIIP## ;DEC COUNT OF OUTSTANDING PACKETS
HLRZ T1,.IPCFP(T2) ;LENGTH OF DATA
ADDI T1,.IPCFD ;PLUS OVERHEAD
IFE FTVM,<
PJRST GIVWDS## ;FREE THE BLOCK AND RETURN
>
IFN FTVM,<
HRL T3,.IPCFP(P1) ;SAVE LOC OF DATA FOR MSG
HRR T3,.IPCFL(P1) ;SAVE FLAGS
PUSH P,T3
PUSHJ P,GIVWDS## ;RETURN THE PACKET (OR HEADER)
POP P,T1
TRNN T1,IP.CFV ;IS IT A PAGE?
POPJ P, ;NO, RETURN
HLRZ T2,T1 ;YES, GET CORE OR DSK ADR OF THE PAGE
PJRST IPCDEL## ;AND RETURN IT
>
;SUBROUTINE TO SEND A PACKET. ADDRESS OF UUO ARGS AND PACKET
; DATA IN P1. SOURCE MUST BE AN EXEC PROCESS, TARGET
; MAY BE EITHER EXEC OR USER. TARGET MUST BE USER
; IF AT INTERRUPT LEVEL. SKIP RETURN ON OK,
; NON-SKIP RETURN HAS T1=ERROR CODE.
SNDMSG: PUSHJ P,SAVE3## ;SAVE P2 AND 3
MOVE P2,J ;SAVE J
MOVE P3,W ;SAVE W
MOVE T1,.IPCFR(P1) ;CHECK RECEIVER
PUSHJ P,VALPID ;SET UP J AND W
JRST SNDERR ;DESTINATION UNKNOWN
MOVSI T1,400000 ;SET TO ENABLE RECEIVER
TLNN P1,400000 ;UNLESS BIT 0 ON IN P1
ANDCAM T1,.PDIPQ##(W) ;HE IS NOW ENABLED
LDB T1,[POINT 9,.PDIPQ##(W),35] ;RECEIVE QUOTA
LDB T2,[POINT 9,.PDIPC##(W),35] ;RECEIVE COUNT
CAMG T1,T2 ;ROOM LEFT?
JRST SNDERR
AOS .PDIPC##(W) ;INCR COUNT OF REC'D MSGS
;COME HERE TO PUT THE MESSAGE ON THE RECEIVER'S LIST
SND0: CONO PI,PION## ;TURN PI SYSTEM ON IN CASE IT WAS OFF
MOVEI T2,.PDIPC##-.IPCFL(W) ;PRESET PREDECESSOR
SND1: HLRZ T1,.IPCFL(T2) ;NEXT PACKET ON QUEUE
JUMPE T1,SND2 ;GO IF END
MOVE T2,T1 ;NOT END, SAVE PRED.
JRST SND1 ;AND STEP TO NEXT
SND2: CONO PI,PIOFF## ;NO INTERRUPT HERE
HLRZ T1,.IPCFL(T2) ;LAST PACKET ON QUEUE
JUMPN T1,SND0 ;JUMP IF NOT THE LAST PACKET
; (QUEUE WAS CHANGED AT INTERRUPT LEVEL
HRLM P1,.IPCFL(T2) ;SAVE THIS PACKET ON END OF QUEUE
HRRZS .IPCFL(P1) ;ZERO LINK OF THE PACKET
CONO PI,PION## ;ALLOW INTERRUPTS AGAIN
;COME HERE AFTER PUTTING PACKET ON LIST. UPDATE COUNTERS.
HLRZ W,.IPCFS(P1) ;RETURN TO SENDER'S PDB
HRRZ T1,.EPIPC(W) ;INCREMENT COUNT OF MSGS SENT
ADDI T1,IP.SBT
HRRM T1,.EPIPC(W) ;GUARD AGAINST OVERFLOW
HLRZ T1,.EPIPA(W) ;COUNT OF SENDS
ADDI T1,1 ;INCREMENT IT
TRNE T1,-1 ;OVERFLOW?
HRLM T1,.EPIPA(W) ;NO, STORE INCREMENTED COUNT
JUMPN J,SND3 ;IS DEST A USER JOB?
PUSHJ P,@.EPADR(W) ;NO, GO RUN EXEC PROCESS.
JRST SND4 ;RETURN TO MAIN LINE.
;COME HERE TO AWAKEN A USER'S JOB.
SND3: PUSHJ P,WAKEUP
SND4: AOS %CNIPS## ;INC TOTAL PACKETS SENT
AOS (P) ;SKIP RETURN
JRST SNDER1 ;RESTORE AC'S
;HERE ON A SEND ERROR
SNDERR: HRRZ T1,.IPCFD(P1) ;CODE
CAIE T1,6 ;CREATE A PID?
JRST SNDER1 ;NO
MOVE T2,.IPCFL(P1) ;FLAGS WORD
TRNE T2,IP.CFE ;IF NO ERROR ON CREATING THE PID,
JRST SNDER1
MOVE T1,.IPCFD+2(P1) ;GET RID OF IT
AND T1,%IPCPM## ;INDEX INTO TABLE
SETZM PIDTAB##(T1)
SOS %IPCNP## ;DECR CURRENT # OF PIDS
SNDER1: MOVE W,P3 ;RESTORE W
MOVE J,P2 ;RESTORE J
POPJ P,0 ;RETURN
;ENABLE THE OWNER OF THE PID IN WORD 1, OR THE SENDER IF WORD
; 1 IS NOT PROVIDED. USE OF WORD 1 IS A PRIV. FUNCTION.
ENABL:
CAIGE T2,2 ;WORD 1 SUPPLIED?
PJRST CPOPJ1 ;NO, SENDER IS AUTOMATICALLY ENABLED
TRNN T3,IP.SIP ;NO, PRIV'D?
PJRST ERRPI ;NO, ERROR
MOVE T1,.IPCFD+1(P1) ;YES, GET PID SUPPLIED
PUSHJ P,VALPID ;SET UP J AND W.
POPJ P, ;BAD PID, FLUSH
MOVSI T1,IP.DSB ;CLEAR JOB'S DISABLE BIT
ANDCAM T1,.PDIPQ##(W)
PJRST CPOPJ1 ;AND GOOD RETURN
;DISABLE THE OWNER OF THE PID IN WORD 1, OR SENDER IF NO WORD 1.
; USE OF WORD 1 IS A PRIV. FUNCTION.
DISAB: TRNE T3,IP.SIP ;PRIV'D?
CAIGE T2,2 ;YES, WORD 1 SUPPLIED?
TLOA P1,400000 ;NO, USE SENDER (ALREADY IN T1), DONT ENABLE HIM
MOVE T1,.IPCFD+1(P1) ;YES, GET PID SUPPLIED
CAIL T2,2 ;TRYING TO DISABLE ANOTHER JOB?
JUMPL P1,ERRPI ;YES, ERR IF NOT PRIV'D
PUSHJ P,VALPID ;SET UP J AND W
POPJ P, ;WRONG, FLUSH
MOVSI T1,IP.DSB ;SET JOB'S DISABLE BIT
IORM T1,.PDIPQ##(W)
PJRST CPOPJ1## ;GOOD RETURN
;MAKE A [SYSTEM]INFO. ARG IS NOT CHECKED SINCE IT MAY BE
; DELIBERATELY INVALID (I.E., 0) TO TERMINATE A LOCAL
; [SYSTEM]INFO OR TO INDICATE THAT THE REAL [SYSTEM]INFO IS LOGGING
; OUT.
MKINFO: SKIPN T1,.IPCFD+2(P1) ;USER OR SYS?
JRST MKINF2 ;SYS.
PUSHJ P,VALPID ;SET UP J AND W FOR TARGET
POPJ P, ;NONE SUCH, FLUSH
JUMPE J,CPOPJ## ;NOT VALID FOR EXEC PROCESSES
SKIPN %SIINF## ;IF NO GLOBAL OR LOCAL [SYSTEM]INFO
SKIPE .PDIPI##(W) ; IS RUNNING THEN MAKING A LOCAL IS OK
SKIPA T1,.IPCFS(P1) ;IF SENDER CHECKS OUT
JRST MKINF1 ;NONE RUNNING NOW - OK
CAME T1,%SIINF## ;IS SENDER GLOBAL [SYSTEM]INFO?
CAMN T1,.PDIPI##(W) ; OR LOCAL [SYSTEM]INFO?
MKINF1: SKIPA T2,.IPCFD+1(P1) ;YES, GET PID TO BECOME THE LOCAL [SYSTEM]INFO
JRST ERRPI ;NO, ERROR RETURN
MOVEM T2,.PDIPI##(W) ;STORE WITHOUT CHECKING
PJRST CPOPJ1## ;GOOD RETURN
;COME HERE TO MAKE SYSTEM'S [SYSTEM]INFO
MKINF2: MOVE T1,.IPCFD+1(P1) ;THE PID
MOVEM T1,.IPCFD+2(P1) ;MOVE IT OVER
MOVEI T1,1 ;SYSID INDEX
MOVEM T1,.IPCFD+1(P1) ;INTO BLOCK
PJRST SIDSET ;USE COMMON CODE
;SEND MESSAGE IDENTIFYING [SYSTEM]INFO
WHOIS: TRNE T3,IP.SIP ;PRIV'D?
SKIPN T1,.IPCFD+1(P1) ;YES, GET JOB NO WHOSE INFO IS WANTED
MOVE T1,.IPCFS(P1) ;NO, TELL HIM HIS OWN [SYSTEM]INFO
PUSHJ P,VALPID ;LOAD J AND W
POPJ P, ;BAD PACKET
SKIPE J ;EXEC PROCESS HAS NO PDB
SKIPN T2,.PDIPI##(W) ;PID OF [SYSTEM]INFO
MOVE T2,%SIINF## ;EXEC OR NO LOCAL SPECIFIED
MOVEM T2,.IPCFD+1(P1) ;THE ONE WORD OF DATA
PJRST CPOPJ1## ;GOOD RETURN
;CREATE A PID. WORD 1 HAS JOB NUMBER, BIT 0=1 IF DROP PID ON RESET
CREATE: MOVN P2,%IPCMP## ;SET AOBJN WORD TO SCAN TABLE
HRLZS P2
SKIPE PIDTAB##(P2) ;FIND AN EMPTY SLOT
AOBJN P2,.-1
JUMPGE P2,ERRPF ;ERROR IF TABLE FULL
MOVE T1,.IPCFD+1(P1) ;USER ARG
TLZ T1,400000 ;REMOTE TYPE FLAG
JUMPE T1,ERRBJ
TLNN T1,377777 ;ONLY SIGN BIT IS GOOD
PUSHJ P,FPDBT1## ;GET ITS PDB (INTO T1)
PJRST ERRBJ ;BAD JOB NUMBER OR NO PDB
AOS T2,%IPCTP## ;TOTAL # OF PIDS SINCE RELOAD
LSH T2,%IPCLS## ;POSITION PAST JOB #/INDEX SLOT
IOR T2,.IPCFD+1(P1) ;ADD JOB NO, (BIT 0 IF DROP ON RESET)
MOVEM T2,PIDTAB##(P2)
ANDCM T2,%IPCPM## ;REMOVE JOB NUMBER
IORI T2,(P2) ;INSERT INDEX INTO TABLE FOR PID AS TOLD
MOVEM T2,.IPCFD+2(P1) ; TO USER ("PUBLIC" PID)
MOVSI T3,IP.DPR
SKIPL T2 ;DROP PID ON RESET?
MOVSI T3,IP.DPL ;NO, DROP ON LOGOUT
IORM T3,.PDIPQ##(T1) ;REMEMBER THAT FACT
AOS %IPCNP## ;INCR CURRENT # OF PIDS
PJRST CPOPJ1## ;AND GOOD RETURN
;FIND JOB NUMBER ASSOCIATED WITH A PID
JOBNO: MOVE T1,.IPCFD+1(P1) ;PID
PUSHJ P,VALPID ;LEGAL?
PJRST ERRBJ ;NO
MOVEM J,.IPCFD+2(P1) ;YES, RETURN JOB NO TO CALLER
PJRST CPOPJ1## ;AND TAKE GOOD RETURN
;TELL QUOTA FOR A JOB
RDQTA: MOVE T1,.IPCFD+1(P1) ;JOB NUMBER (OR SOME PID FOR JOB)
PUSHJ P,VALPID ;LEGAL?
PJRST ERRBJ ;NO
MOVE T1,.PDIPQ##(W) ;YES, GET QUOTA
HRRZM T1,.IPCFD+2(P1) ;SAVE IN PACKET
PJRST CPOPJ1## ;AND GOOD RETURN
;SET QUOTA FOR PID IN WORD 2.
QUOTA: MOVE T1,.IPCFD+1(P1) ;PICK UP JOB NUMBER
PUSHJ P,VALPID ;SET UP J + W
PJRST ERRBJ ;ERROR, FLUSH
MOVE T2,.IPCFD+2(P1) ;GET QUOTA WORD
HRRM T2,.PDIPQ##(W) ;STORE AS NEW QUOTA
PJRST CPOPJ1## ;GOOD RETURN
;TELL PID(S) ASSOCIATED WITH A JOB
RDPIDS: MOVEI P2,-2(T2) ;NUMBER OF VALUES TO RETURN
SKIPN T1,.IPCFD+2(P1) ;STARTING PID
JRST RDPID1 ;START AT BEGINNING OF TABLE
PUSHJ P,VALPID ;CHECK IT OUT
PJRST ERRDU ;CANT START AT AN ILLEGAL PID
MOVE T1,.IPCFD+2(P1) ;OK, GET PID AGAIN
AND T1,%IPCPM## ;GET START INDEX INTO TABLE
RDPID1: SKIPLE T2,.IPCFD+1(P1) ;DESIRED JOB NUMBER
CAILE T2,JOBMAX##
PJRST ERRBJ ;BAD JOB NUMBER
MOVNS P2
HRLZS P2 ;SET AN AOBJN WORD FOR STORING VALUES
HRR P2,P1
MOVN T3,%IPCMP ;MAKE AN AOBJN WORD
HRLZS T3 ; FOR SCANNING PIDTAB
ADDI T1,1
HRLS T1
ADD T1,T3
RDPID2: SKIPE T3,PIDTAB##(T1) ;GET A PID
AND T3,%IPCPM## ;JOB NUMBER
CAIE T3,(T2) ;TARGET JOB NO?
JRST RDPID3 ;NO
MOVE T3,PIDTAB##(T1) ;YES, GET FULL PID AGAIN
ANDCM T3,%IPCPM## ;REMOVE JOB NO
IORI T3,(T1) ;ADD INDEX
MOVEM T3,.IPCFD+2(P2) ;SAVE IN PACKET
AOBJP P2,CPOPJ1## ;DONE IF NO MORE ROOM
RDPID3: AOBJN T1,RDPID2 ;SCAN WHOLE TABLE
SETZM .IPCFD+2(P2) ;TERMINATE WITH A 0
PJRST CPOPJ1## ;AND TAKE GOOD RETURN
;DESTROY A PID.
DESTRY: MOVE T1,.IPCFD+1(P1) ;PID BEING DESTROYED
PUSHJ P,CHKSID ;SEE IF A SYSTEM PID
PJRST ERRPI ;YES, CAN'T DO THAT
PUSHJ P,VALPID ;VALIDATE IT
PJRST ERRBJ ;NO GOOD, FLUSH
MOVE P3,W ;OLD PDB LOC IN P3
MOVE P2,.IPCFD+1(P1) ;PID
MOVE T1,.IPCFS(P1) ;SENDER
PUSHJ P,VALPID ;SET UP W
POPJ P, ;NO GOOD (SHOULD NEVER HAPPEN)
CAMN P2,.IPCFS(P1) ;SENDER DESTROYING HIS OWN PID?
MOVEM J,.IPCFS(P1) ;YES, SEND ANSWER BACK TO THE JOB NO.
MOVE T2,P2
AND T2,%IPCPM## ;MASK TO INDEX
SETZM PIDTAB##(T2)
PUSHJ P,CHANGE ;PUT ANY MSGS FOR PID INTO SENDER'S QUEUE
SOS %IPCNP## ;DECREMENT COUNT OF CURRENT PID'S
MOVE J,HIGHJB## ;DO ALL JOBS
DSTRY1: PUSHJ P,FNDPDB## ;SET UP W
JRST DSTRY2 ;NO JOB
CAMN P2,.PDIPI##(W) ;DESTROY LOCAL INFO FOR THIS JOB?
SETZM .PDIPI##(W) ;CLEAR IT!
DSTRY2: SOJG J,DSTRY1 ;LOOP FOR ALL JOBS.
PJRST CPOPJ1## ;AND GOOD RETURN
;CHANGE THE OWNERSHIP OF A PID. WORD 1 HAS THE PID, WORD 2 THE NEW
; JOB NUMBER.
OWNER: MOVE T1,.IPCFD+1(P1) ;PID TO CHANGE
PUSHJ P,CHKSID ;SEE IF A SYSTEM PID
PJRST ERRPI ;YES, CAN'T DO THAT
PUSHJ P,VALPID ;SET UP J + W
PJRST ERRDU ;BAD PID
MOVE T2,.IPCFD+1(P1) ;GET PID BEING CHANGED
CAMN T2,.IPCFS(P1) ;GIVING SELF AWAY?
MOVEM J,.IPCFS(P1) ;YES, SEND BACK TO JOB
JUMPE J,ERRDU ;CANNOT CHANGE OWNERSHIP OF EXEC PROC.
MOVE P3,W ;SOURCE PDB
SKIPLE J,.IPCFD+2(P1)
PUSHJ P,FNDPDB## ;FIND JOB'S PDB
PJRST ERRBJ ;CANT FIND PDB, BAD JOB NO
MOVE P2,.IPCFD+1(P1) ;PID TO CHANGE IN P2
PUSHJ P,CHANGE ;CHANGE THE OWNERSHIP OF THE PID
MOVE T1,P2 ;GET OLD PID
AND T1,%IPCPM## ;MASK TO INDEX
MOVE T2,PIDTAB##(T1) ;GET OLD PID
ANDCM T2,%IPCPM## ;REMOVE OLD JOB
IOR T2,.IPCFD+2(P1) ;INCLUDE NEW JOB
MOVEM T2,PIDTAB##(T1) ;STORE BACK IN PID TABLE
PJRST CPOPJ1## ;AND GOOD RETURN
;SUBROUTINE TO CHANGE THE OWNERSHIP OF A PID
;ENTER W=PDB OF NEW OWNER P2=PID TO CHANGE P3=PDB OF OLD OWNER
CHANGE: MOVEI T1,.PDIPC##-.IPCFL(W) ;PRESET PREDECESSOR
CHNGE1: HLRZ T2,.IPCFL(T1) ;STEP TO NEXT
JUMPE T2,CHNGE2
MOVE T1,T2 ;NEW PREDECESSOR
JRST CHNGE1 ;FIND END OF QUEUE FOR NEW OWNER
CHNGE2: MOVEI T2,.PDIPC##-.IPCFL(P3) ;WHERE TO UNQUEUE FROM
CHNGE3: HLRZ T3,.IPCFL(T2) ;NEXT ITEM FROM QUEUE
JUMPE T3,CPOPJ## ;DONE IF 0
CAME P2,.IPCFR(T3) ;FOR THE PID BEING CHANGED?
JRST CHNGE4 ;NO
CAMN W,P3 ;CHANGING OWNERSHIP TO SAME JOB NO?
MOVEM J,.IPCFR(T3) ;YES, MAKE REC'R BE THE JOB ITSELF
; (OTHERWISE A LOOP MAY RESULT)
HRLM T3,.IPCFL(T1) ;YES, PUT ON NEW QUEUE
MOVE T4,.IPCFL(T3) ;QUEUE POINTER OF THIS PACKET
HLLM T4,.IPCFL(T2) ;REMOVE FROM OLD QUEUE
HRRZS .IPCFL(T3) ;LAST ENTRY ON NEW QUEUE
PUSH P,T2
PUSH P,T3
PUSHJ P,WAKEUP ;PSI OR UNHIBER NEW RECEIVER
POP P,T1
POP P,T2
SOS .PDIPC##(P3) ;UPDATE COUNTS FOR OLD AND NEW OWNERS
AOSA .PDIPC##(W)
CHNGE4: MOVE T2,T3 ;STEP TO NEXT ENTRY IN (OLD) QUEUE
JRST CHNGE3 ;AND TEST IT
;FUNCTION 24: SET SYSTEM PID TABLE
SIDSET: PUSHJ P,CHKIDX ;GET INDEX AND CHECK IT
JRST ERRBI ;BAD INDEX
JUMPE T2,ERRBI ;DON'T LET HIM SET IPCC
SETZ J, ;IN CASE CLEARING THE TABLE
SKIPN T1,.IPCFD+2(P1) ;GET PID FROM USER
JRST SETST1 ;ZERO MEANS CLEAR THE ENTRY
PUSHJ P,VALPID ;VALIDATE THE PID
POPJ P, ;RETURN ERROR CODE
MOVE T2,.IPCFD+1(P1) ;GET INDEX BACK
MOVE T1,.IPCFD+2(P1) ;GET THE PID
SETST1: MOVE T3,SIDJOB##(T2) ;CHECK OWNER
CAME T3,.C0JOB## ;AGAINST CALLER
JUMPN T3,ERRPI ;ERROR IF NOT OWNER OF TABLE ENTRY
MOVEM T1,.GTSID##(T2) ;STORE IT
MOVEM J,SIDJOB##(T2) ;AND IN JOB NUMBER TABLE
CAIN T2,1 ;[SYSTEM]INFO
MOVEM T1,%CNIPI## ;YES, UPDATE OLD GETTAB
JRST CPOPJ1 ;AND RETURN SUCCESS
;FUNCTION 25: READ SYSTEM PID TABLE
SIDRD: PUSHJ P,CHKIDX ;GET INDEX AND CHECK IT
JRST ERRBI ;BAD INDEX
MOVE T1,.GTSID##(T2) ;GET THE PID
MOVEM T1,.IPCFD+2(P1) ;GIVE IT TO THE USER
PJRST CPOPJ1 ;AND RETURN SUCCESSFUL
;CHKIDX -- ROUTINE TO VALIDATE INDEX AND RETURN IT IN T2.
; SKIP IF OK, NON-SKIP IF NO GOOD.
CHKIDX: MOVEI T1,SIDMXL## ;GET <MAX>B26
LSH T1,-^D9 ;SHIFT IT OVER
SKIPL T2,.IPCFD+1(P1) ;GET THE INDEX
CAMLE T2,T1 ;IN RANGE?
POPJ P, ;NO
PJRST CPOPJ1 ;YES
;HERE FROM UUOCON ON A LOGOUT UUO
IPCLGO::PUSHJ P,SAVE2## ;SAVE P1
IFN FTGALAXY,<
PUSHJ P,QSRLGO ;SEND LOGOUT MESSAGE TO QUASAR
>
SETO P1, ;SETUP MASK TO TEST PIDS
MOVSI T1,IP.DPL ;LOAD UP THE LOGOUT FLAG
JRST IPCFR1 ;SEND MSG TO INFO, DROP PIDS ETC.
;HERE FROM UUOCON ON A RESET UUO. SEND A MESSAGE TO INFO AND
; DESTROY THE APPROPRIATE PIDS.
IPCFRS::PUSHJ P,SAVE2## ;SAVE P1
MOVSI P1,(1B0) ;MASK FOR PIDS TO DROP
MOVSI T1,IP.DPR ;SET UP CONDITION FOR TEST
;COMMON CODE FOR RESET AND LOGOUT STARTS HERE
IPCFR1: PUSHJ P,FNDPDS## ;SET UP W
PUSHJ P,TURNQ ;TURN ANY MSGS AROUND FOR THIS JOB
TDNN T1,.PDIPQ##(W) ; IF CONDITIONS AREN'T MET
POPJ P, ;DONT SEND A MSG TO ANYBODY
ANDCAM T1,.PDIPQ##(W) ;AND SAY "NO MORE"
MOVEI T2,IPCFRF-IPCFTB+1 ;CODE FOR RESET/LOGOUT
MOVEM T2,INFMSG## ;SAVE IT
HRR T1,J ;GET FLAG,,JOB
MOVEM T1,INFMSG##+1 ;STORE
MOVN P2,%IPCMP ;SET AN AOBJN WORD FOR LOOKING
HRLZS P2 ; AT ALL OF PIDTAB
IPCLG1: MOVE T2,PIDTAB##(P2) ;PIDTAB ENTRY
TDNN P1,T2 ;DROP THIS PID?
JRST IPCLG2 ;NO--KEEP LOOKING
MOVE T1,T2 ;COPY PID
AND T2,%IPCPM ;JOB NUMBER
CAIE T2,(J) ;FOR THIS JOB?
JRST IPCLG2 ;NO
SETZM PIDTAB##(P2) ;YES, CLEAR IT
SOS %IPCNP## ;1 LESS PID CURRENTLY ACTIVE
TDZ T1,%IPCPM ;REMOVE JOB NUMBER
IORI T1,0(P2) ;INSERT PIDTAB INDEX
MOVEI T2,SIDMXL## ;NUMBER OF SYSTEM PIDS
LSH T2,-^D9 ;POSITION IT
CAMN T1,.GTSID##(T2) ;THIS IT
JRST [SETZM .GTSID##(T2) ;YES, CLEAR ENTRY
SETZM SIDJOB##(T2) ;AND THE JOB NUMBER
JRST .+1] ;RETURN A LINE
SOJGE T2,.-2 ;TRY THE NEXT
MOVE T2,%SIINF## ;UUO'S PID
MOVEM T2,%CNIPI## ;KEEP THE GETTAB STRAIGHT
IPCLG2: AOBJN P2,IPCLG1 ;DO FOR ALL ENTRIES IN PIDTAB
MOVEI T1,%SIINF## ;LOCATION OF INFO'S PID
SKIPE .PDIPI##(W) ;PRIVATE INFO?
MOVEI T1,.PDIPI##(W) ;YES, USE IT
MOVE T2,[2,,INFMSG##] ;POINT TO MESSAGE
PJRST SENDSN ;SEND IT AND RETURN
;SUBROUTINE TO TURN MESSAGES AROUND FOR A JOB ON RESET/LOGOUT
;CALL WITH T1=IP.DPR OR IP.DPL IN T1
;IF IP.DPR, TURNS AROUND ONLY THOSE MESSAGES FOR PIDS TO BE DROPPED ON RESET
;IF IP.DPL, TURNS AROUND ALL MESSAGES
;PRESERVES T1
TURNQ: PUSHJ P,SAVE3## ;SAVE P1,-P3
PUSH P,J ;SAVE J
MOVE P3,J
PUSH P,T1
MOVEI P2,.PDIPC##-.IPCFL(W) ;PRESET PREDECESSOR
TLNN T1,IP.DPR
TLO P2,-1 ;P2 NEGATIVE IF LOGOUT
TURNQ0: HLRZ P1,.IPCFL(P2) ;GET NEXT ENTRY IN QUEUE FOR JOB
TURNQ1: JUMPE P1,TURNQ7 ;DONE IF 0
SKIPL T1,.IPCFR(P1) ;IF REC'R IS TO BE DROPPED ON LOGOUT,
JUMPGE P2,TURNQ6 ; STEP TO NEXT PACKET IF THIS IS RESET
AOS T2,.IPCFL(P1) ;SET BIT 35 (UNDELIVERABLE) IN PACKET HEADER
TRNE T2,2 ;ALREADY BEEN THIS WAY?
JRST TURNQ5 ;YES, MAKE THE PACKET GO AWAY
EXCH T1,.IPCFS(P1)
MOVEM T1,.IPCFR(P1)
PUSH P,W ;SAVE W
PUSHJ P,VALPID ;SET W FOR REC'R (ORIGINAL SENDER)
JRST TURNQ4 ;HE'S GONE TOO - REMOVE THE PACKET
DPB P3,TRNPTR ;SAVE JOB NUMBER FOR TURN-AROUND RCV.
MOVE T2,.PDIPC##(W) ;CURRENT COUNT OF SENDS & REC'S
TRNN T2,777000 ;ANY PACKETS SENT, NOT REC'D?
AOSA T2 ;NO, JUST INCR REC'S (SEND FROM JOB NUMBER N)
SUBI T2,777 ;YES, DECR SEND COUNT, INCR REC COUNT
MOVEM T2,.PDIPC##(W) ;STORE UPDATED NUMBER
MOVEI T1,.PDIPC##-.IPCFL(W) ;SET TO FIND END OF NEW QUEUE
EXCH W,(P) ;RESTORE W OF LOGGING-OUT JOB
MOVEI T2,777 ;ADJUST COUNT OF OLD JOB
ADDM T2,.PDIPC##(W)
TURNQ2: HLRZ T2,.IPCFL(T1)
JUMPE T2,TURNQ3 ;FOUND END IF NEXT=0
MOVE T1,T2 ;NOT END, GET NEXT
JRST TURNQ2
TURNQ3: HRLM P1,.IPCFL(T1) ;STICK THIS PACKET ON END OF QUEUE
MOVE T1,.IPCFL(P1) ;LINK TO NEXT IN OLD JOB'S QUEUE
HRRZS .IPCFL(P1) ;THIS IS END IN FORMER SENDER'S QUEUE
HLRZ P1,T1 ;POINT P1 TO NEXT IN OLD QUEUE
HRLM P1,.IPCFL(P2) ;LINK NEXT TO PREDECESSOR IN OLD Q
JUMPN J,[POP P,(P)
PUSHJ P,WAKEUP ;WAKE UP ORIGINAL SENDER
JRST TURNQ1] ;GO TURN AROUND NEXT MSG
EXCH W,(P)
HLRZ T1,W ;LOC OF EXEC PID
PUSHJ P,@.EPADR(T1) ;CALL THE EXEC PROCESS
POP P,W
JRST TURNQ1 ;GO TURN AROUND NEXT MSG IN QUEUE
;HERE IF MSG COULDN'T BE TURNED AROUND
TURNQ4: POP P,W ;RESTORE W
TURNQ5: HLRZ T1,.IPCFL(P1) ;LINK TO NEXT PACKET
HRLM T1,.IPCFL(P2) ;MAKE NEXT IN QUEUE
PUSHJ P,REMPAK ;REURN THIS PACKET TO FREE CORE
JRST TURNQ0 ;AND TRY NEXT PACKET
;HERE IF PACKET IS FOR A PID TO BE DROPPED ON LOGOUT, THIS IS RESET
TURNQ6: HRR P2,P1 ;SAVE POINTER TO LAST ON OLD QUEUE
JRST TURNQ0 ;GO PROCESS NEXT QUEUE ENTRY
;HERE WHEN DONE
TURNQ7: POP P,T1 ;RESET T1
PJRST JPOPJ## ;AND RETURN TO CALLER
SUBTTL IPCC INTERFACE FOR GALAXY-10
IFN FTGALAXY,<
IFN FTSPL,<
;HERE ON THE CLOSE OF A SPOOLED FILE FROM FILUUO. CALLED WITH F
; CONTAINING THE ADDRESS OF THE SPOOLED DDB.
QSRSPL::PUSHJ P,SAVT## ;SAVE T1 - T4
PUSH P,J ;SAVE J
LDB J,PJOBN## ;LOAD UP J
MOVSI T1,SPMSIZ ;MESSAGE SIZE
HRRI T1,IPCFSM-IPCFTB+1 ;SPOOL FUNCTION
PUSHJ P,SETQSR ;SETUP THE PACKET
PUSHJ P,FNPDBS## ;SETUP W
MOVE T1,.PDNM1##(W) ;GET FIRST HALF OF USER NAME
MOVEM T1,QSRMSG##+SPMUSR ;STORE IT
MOVE T1,.PDNM2##(W) ;GET SECOND HALF OF USER NAME
MOVEM T1,QSRMSG##+SPMUSR+1 ;STORE IT
MOVE T1,DEVNAM(F) ;GET INITED DEVICE
MOVEM T1,QSRMSG##+SPMIDV ;AND SAVE IT
HLRZ T1,DEVUNI##(F) ;GET ADR OF UDB
HRRZ T1,UNISTR##(T1) ;GET ADR OF SDB
MOVE T1,STRNAM##(T1) ;GET STRUCTURE NAME
MOVEM T1,QSRMSG##+SPMSTR ;STORE IT
MOVE T1,DEVFIL(F) ;GET FILENAME
MOVEM T1,QSRMSG##+SPMFIL ;STORE IT
MOVE T1,DEVPPN(F) ;GET THE PPN OF FILE
MOVEI T2,GALIUD ;GET "IN USER'S DIRECTORY" BIT
CAME T1,QUEPPN## ;IS FILE IN THE QUE DIRECTORY?
IORM T2,QSRMSG##+GALSTS ;NO, SET BIT
SKIPN T1,DEVSPN##(F) ;GET ENTER'ED NAME IF SETUP
MOVE T1,JBTNAM##(J) ;USE PROG NAME IF 0.
MOVEM T1,QSRMSG##+SPMEFN ;AND SAVE IT
MOVE T1,DEVACC##(F) ;GET ADDRESS OF ACCESS TABLE
MOVE T1,ACCWRT##(T1) ;GET BLOCKS WRITTEN
MOVEM T1,QSRMSG##+SPMFSZ ;AND SAVE FILE SIZE
MOVE T1,DEVFRM##(F) ;GET FORMS
MOVEM T1,QSRMSG##+SPMFRM ;STORE IT
MOVE T1,DEVSPM##(F) ;GET OTHER SPOOLING PARAMETERS
MOVEM T1,QSRMSG##+SPMPRM ;AND STORE
MOVEI T1,%SIQSR## ;GET LOCATION OF QUASAR'S PID
MOVE T2,[SPMSIZ,,QSRMSG##] ;GET LEN,,ADR
PUSHJ P,SENDSN ;AND SEND THE MESSAGE
JRST JPOPJ##
> ;END IFN FTSPL
;STILL IN IFN FTGALAXY
;STILL IN IFN FTGALAXY
;HERE ON LOGOUT UUO. LOGOUT MESSAGE IS SENT TO QUASAR IF %SIQSR
; CONTAINS A VALID PID.
QSRLGO: MOVSI T1,LGMSIZ ;SIZE OF MESSAGE
HRRI T1,IPCFLM-IPCFTB+1 ;CODE
PUSHJ P,SETQSR ;SETUP THE MESSAGE
MOVEI T1,%SIQSR## ;GET ADR OF QUASAR'S PID
MOVE T2,[LGMSIZ,,QSRMSG##] ;GET LEN,,ADR
PJRST SENDSN ;SEND THE MESSAGE
;HERE ON LOGIN UUO TO SEND MESSAGE TO QUASAR
QSRLGI::MOVSI T1,LOMSIZ ;SIZE OF MESSAGE
HRRI T1,IPCFON-IPCFTB+1 ;CODE
PUSHJ P,SETQSR ;SETUP THE MESSAGE
DMOVE T1,.PDNM1(W) ;GET USER NAME
DMOVEM T1,QSRMSG+LOMUSR ;STORE
PUSH P,F
MOVE F,TTYTAB##(J)
PUSHJ P,CTLJBD##
MOVEM T1,QSRMSG##+LOMCTL
MOVE T1,DEVNAM(F)
MOVEM T1,QSRMSG##+LOMTTY
POP P,F
MOVEI T1,%SIQSR
MOVE T2,[LOMSIZ,,QSRMSG##]
PJRST SENDSN ;AND SEND MESSAGE TO QUASAR
;SETQSR -- ROUTINE TO SETUP A PACKET TO SEND TO QUASAR. CALL
; WITH T1 CONTAINING SIZE,,CODE, RETURN QSRMSG BLOCK
; WITH GALMSG AND GALSTS ALL SETUP.
SETQSR: MOVEM T1,QSRMSG##+GALMSG ;AND STORE FIRST WORD
HRLZ T1,J ;GET JOB,,0
IFN FTNET,<
HRRZ T2,JBTLOC##(J) ;GET HIS LOCATION
LSH T2,^D9 ;SHIFT OVER 9 BITS
IOR T1,T2 ;OR IT IN
> ;END IFN FTNET
MOVSI T2,(JB.LBT) ;GET BATCH BIT
TDNE T2,JBTLIM##(J) ;IS HE A BATCH JOB?
TRO T1,GALBAT ;YES, SET THE FLAG
MOVEI T2,JB.DFR ;GET DEFERED BIT
TDNE T2,JBTSPL##(J) ;TEST IT
TRO T1,GALDFR ;ITS ON
MOVEM T1,QSRMSG##+GALSTS ;AND STORE 2ND DATA WORD
POPJ P, ;AND RETURN
> ;END OF IFN FTGALAXY
IFN FTMDA,<
;SUBROUTINE TO SEND THE CONTENTS OF T1 AND T2 TO [SYSTEM]MDC
;CALLING SEQUENCE: (MAY BE CALLED AT INTERRUPT LEVEL)
; MOVE T1,UNIT NAME
; MOVEI T2,DEVICE TYPE
; PUSHJ P,SNDMDC
;RETURNS CPOPJ IF THE MESSAGE COULDN'T BE SENT, CPOPJ1 IF OK
SNDMDC::PUSH P,T1 ;SAVE ARGUMENTS
PUSH P,T2
MOVEI T2,3 ;GET THREE WORDS OF FREE STORAGE
PUSHJ P,GETWDS##
JRST [POP P,T2 ;FAIL
JRST TPOPJ##]
MOVEI T2,.IPCUO
MOVEM T2,(T1)
POP P,2(T1) ;DEVICE TYPE
POP P,1(T1) ;UNIT NAME
PUSH P,T1 ;SAVE FREE CORE ADDRESS
MOVE T2,T1 ;ADDRESS OF THE MESSAGE
MOVEI T1,%SIMDC## ;PID OF [SYSTEM]MDC
HRLI T2,3 ;LENGTH OF THE MESSAGE
PUSH P,J ;SAVE J
SETZB J,T4 ;JOB NUMBER AND PPN OF SENDER ARE ZERO
PUSHJ P,SENDS0 ;SEND THE MESSAGE
SOS -2(P) ;FAILED
POP P,J ;RESTORE J
POP P,T2 ;AND FREE CORE ADDRESS
MOVEI T1,3 ;RETURN THREE WORDS TO FREE CORE
AOS (P) ;SKIP RETURN IF SUCCESSFUL
PJRST GIVWDS## ;RETURN FREE CORE
>
;SUBROUTINE TO SEND A PACKET TO A PID AND WAIT FOR A RESPONSE
; FROM THE RECEIVER
;CALLING SEQUENCE:
; MOVE T1,["SENT BY",,%SIDXXX]
; OR MOVE T1,RECEIVER'S PID
; MOVE T2,[LENGTH,,ADDRESS]
; MOVE T3,SENDER'S PID
; MOVE T4,SENDER'S PPN
; PUSHJ P,SENDSP ;IF SENDING TO A SPECIAL SYSTEM PROCESS
; OR PUSHJ P,SENDAP ;IF SENDING TO AN ARBITRARY PID
;RETURNS CPOPJ IF THE MESSAGE COULLD NOT BE DELIVERED
; RETURNS CPOPJ1 IF THE MESSAGE WAS SUCCESSFULLLY SENT AND A REPLY
; HAS BEEN RECEIVED. THE POINTER TO THE PACKET RECEIVED IS IN .PDEPA.
; IT IS THE CALLLER'S RESPONSIBILLITY TO RETURN THE PACKET TO MONITOR
; FREE CORE AFTER PROCESSING ITS CONTENTS
SENDAP::PUSHJ P,SAVE4##
MOVE P4,T3
MOVE P3,T1
MOVE P2,T2
PUSHJ P,VALPID
POPJ P,
AND P3,%IPCPM##
ADDI P3,PIDTAB## ;ADDRESS OF THE PID IN PIDTAB
MOVE J,.C0JOB##
PUSHJ P,SENDS1
POPJ P,
JRST SENDP1
SENDSP::MOVE J,.C0JOB##
PUSHJ P,SENDS0
POPJ P,
SENDP1: MOVEI T1,EV.IPC
PUSHJ P,ESLEEP##
HRRZ T1,.PDEPA##(W)
JUMPN T1,SENDP1 ;THIS DEPENDS ON A SYSTEM PROCESS NOT SENDING TO
;[SYSTEM]IPCC
PJRST CPOPJ1##
;HERE ON RECEIPT OF A MESSAGE SENT TO THE EXEC PSUEDO-PROCESS
; [SYSTEM]GOPHER IF THE INTENDED RECEIVING PROCESS IS BLOCKED WAITING
; FOR A RESPONSE, STORE THE ADDRESS OF THE PACKET IN THE RECEIVER'S
; PDB AND WAKEUP THE RECEIVER. OTHERWISE, RETURN THE PACKET AS
; UNDELIVERABLE.
IPCSPR::PUSHJ P,SAVE1##
IPCSP1: PUSHJ P,GETPAK
POPJ P,
HRRZ P1,T1
MOVE T1,.IPCFD(P1)
MOVE J,T1
PUSHJ P,FPDBT1## ;VALIDATE JOB NUMBER AND GET OBJECT JOB'S PDB
JRST IPCSP2
MOVE T2,.IPCFS(P1)
LDB T3,JBYEWT##
CAMN T2,.PDEPA##(T1)
CAIE T3,EV.IPC
JRST IPCSP2
HRLZM P1,.PDEPA##(T1)
MOVE T1,J
PUSHJ P,EWAKE##
SOS .PDIPC(W)
HLRZ T1,.IPCFL(P1)
HRLM T1,.PDIPC##(W)
PUSHJ P,DECSSW
SOS %CNIIP
JRST IPCSP1
IPCSP2: MOVEI T1,IPCDU%
DPB T1,[POINT 6,.IPCFL(P1),29]
PUSHJ P,DECSSW
MOVEI T2,4
PUSHJ P,ANSWE1
JRST IPCSP1
SUBTTL MONITOR INTERFACE ROUTINES
;SENDSI -- ROUTINE TO SEND A MESSAGE TO ANY SPECIAL SYSTEM PROCESS
;
;CALL:
; MOVEI T1,%SIXXX
; HRLI T1,"SENT BY [SYSTEM]?", 0 IF IPCC
; MOVE T2,[XWD LEN,ADR]
; MOVE T3,SYSTEM PID, IGNORED IF IPCC
; PUSHJ P,SENDSI
;
; ALWAYS RETURN HERE
;
;USES T1-T4
;
;NOTE: THE BLOCK SPECIFIED BY THE CALLER BELONGS "TO THE CALLER".
; IT IS COPIED AND RETURNED TO THE CALLER INTACT. SPECIFICALLY,
; IF THE CALLER GOT THE BLOCK FROM THE SYSTEM FREE SPACE, "HE"
; MUST RETURN IT.
;
SENDSN::PUSHJ P,SENDSI
POPJ P,
POPJ P,
SENDSI::MOVE T4,JBTPPN##(J) ;SENDER'S PPN
;ENTER HERE WITH (T4) = SENDER'S PPN
SENDS0: SKIPN 0(T1)
POPJ P,
PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P4,T3
MOVE P3,T1 ;SAVE T1
MOVE P2,T2 ; AND T2
MOVE P1,T4
TLNE P3,-1
JRST SENDS1
HRLI P3,10
MOVE P4,PIDTAB##
;FALL INTO SENDS1
SENDS1: HLRZ T2,P2 ;GET LENGTH
ADDI T2,.IPCFD ;ADD HEADER
PUSHJ P,GETPKT ;GET FREE SPACE
POPJ P,
MOVEM P1,.IPCFU(T1)
HLRZM P3,.IPCFL(T1)
MOVEM P4,.IPCFS(T1)
HRL P1,P2 ;GET SOURCE,,0
HRRI P1,.IPCFD(T1) ;GET SOURCE,,DEST
HLRZ P4,P2 ;GET LEN
MOVSI T2,IP.LPK ;GET "LARGE PACKET"
CAMLE P4,%CNIPL## ;IS IT LARGE?
IORM T2,.IPCFL(T1) ;YES, SET IT
ADDI P4,.IPCFD-1(T1) ;GET END OF MSG
BLT P1,(P4) ;MOVE THE MSG OVER
MOVE T2,(P3) ;GET RECEIVER'S PID
MOVEM T2,.IPCFR(T1) ;SAVE IT
PUSHJ P,FNDPDS## ;SENDER'S PDB
MOVEM T2,.PDEPA##(W) ;STORE THE PID OF WHO CAN ANSWER
HLLZM P2,.IPCFP(T1) ;STORE LENGTH
PUSHJ P,IPCSCA ;SET CAPABILITIES OF THE JOB PACKET IS BEING SENT FOR
MOVE P1,T1 ;PUT ADDRESS IN P1
PUSHJ P,SNDMSG ;SEND IT
JRST SENDS2 ;LOSE!
AOS %CNIIP ;ONE MORE IN
JRST CPOPJ1##
SENDS2: HLRZ T1,P2 ;GET MSG LENGTH
ADDI T1,.IPCFD ;ADD HDR SIZE
HRRZ T2,P1 ;GET ADR
PJRST GIVWDS## ;RETURN SPACE AND RETURN
;GETPKT -- GET A PACKET OF FREE CORE. CALL WITH T2 CONTAINING
; NUMBER OF WORDS NEEDED. RETURNS WITH ADDRESS OF PACKET
; IN T1. GETPKT "WAITS" IF NO FREE SPACE IS AVAILABLE. ALWAYS
; RETURNS CPOPJ.
GETPKT: PUSHJ P,GETWDS## ;GET THE FREE SPACE
JRST GETPK1 ;LOSE, WAIT
JRST CPOPJ1## ;WIN!!
GETPK1: JUMPE J,CPOPJ## ;LOSE IF AT INTERRUPT LEVEL
PUSH P,T2
MOVEI T1,1 ;ONE SECOND
PUSHJ P,SLEEP## ;SLEEP
POP P,T2
JRST GETPKT ;AND TRY AGAIN
;CHKSID -- CHECK IF PID IS ONE OF THE "FRIENDS OF THE MONITOR"
;CALLED WITH T1=THE PID
;DESTROYS T2
;RETURNS CPOPJ IF TRUE, CPOPJ1 OTHERWISE
CHKSID: MOVEI T2,SIDMXL## ;NUMBER OF PIDS<B26>
LSH T2,-^D9 ;POSITION IT
CHKS.1: CAMN T1,.GTSID##(T2) ;THIS IT
POPJ P, ;YES, RETURN
SOJGE T2,CHKS.1 ;NO, TRY THE NEXT
JRST CPOPJ1## ;NOT A SYSTEM
LIT
IPCEND: END