; PROGRAM ZEROACC ; This program writes an accounting record for each process on the system ; and then resets the accounting data fields of each process. The main ; loop scans the PCB vector table from start to finish. For each process ; it finds it checks to see if it should skip that process. If not, ; nonpaged memory is allocated, a special kernel mode AST is constructed ; in the allocated memory, and the AST is queued to the target process. ; ; The special kernel mode AST writes an accounting record for the process ; and then resets the accounting fields of the process. From an accounting ; point of view, the result is as if the user had logged out and then ; logged back in again. ; ; The accounting fields reset are: ; CPU time used ; CPU time limit apropriately adjusted (if there is a CPU time limit) ; Direct I/O count ; Buffered I/O count ; Page fault I/O count ; Page fault count ; Image activation count ; Login time ; Working set peak size ; Virtual page file peak size ; Volumes mounted ; PHD$L_TIMREF (08-OCT-1990. Thanks to Cindy Vandersleen) ; ; SIDE EFFECTS ; The accounting fields of each process are reset. If the user was ; using the accounting fields to obtain statistics on program ; efficiency at the time the accounting fields get reset, he may get ; very preplexing results. For instance, the CPU time used is one of ; the fields reset to zero. If the user were checking the CPU time ; before and after running a program to determine how much CPU time it ; used, he may be surprised to find that after running the program the ; CPU time field was less than it was before running the program. ; Aside from that, the user should remain undisturbed and unaware that ; his accounting fields have been reset. ; ; WARNING ; This code executes in kernel mode at elevated IPL. Mistakes can cause ; the system to crash. ; ; STANDARD DISCLAIMER ; Use at your own risk. ; ; © David Deley October, 1988 ; © David Deley March, 1989 VMS 5.0 Multiprocessing compatible ; © David Deley October, 1990 Add PHD$L_TIMREF. Thanks to Cindy Vandersleen. ;------------------------------------------------------------------------------ ; ; PCB VECTOR TABLE ; ----------------------------------------------------- ; | address of PCB of NULL process | SCH$GL_PCBVEC ; ----------------------------------------------------- ; | address of PCB of SWAPPER process | ; ----------------------------------------------------- ; | address of PCB of existing process or null process| ; ----------------------------------------------------- ; | address of PCB of existing process or null process| ; ----------------------------------------------------- ; | . (more pointers) | ; | . | ; | . | ; ----------------------------------------------------- ; | address of PCB of existing process or null process| SCH$GL_PCBVEC + 4*SCH$GL_MAXPIX ; ----------------------------------------------------- ; ; ; When the system is initialized, an array of MAXPROCESSCNT longwords is ; allocated from nonpaged pool. This array locates the PCB of each process ; in the system at any given time. The first two entries in the table ; point to the PCBs of the null process and the swapper process. All other ; entries initially point to the PCB of the null process. An entry which ; points to the PCB of the null process (except for the first one) is ; considered an empty slot. ; ; The global value SCH$GL_PCBVEC points to the start of the PCB vector. ; The global value SCH$MAXPIX is the maximum process index for this system. ; ;------------------------------------------------------------------------------ ; (Note there is a misprint in the book VAX/VMS Internals and Data Structures ; version 4.4, page 922, figure E-14, "Layout of a process control block". ; The layout shown below should be correct.) ; ; PROCESS CONTROL BLOCK (PCB) ; ----------------------------------------------------- ; | PCB$L_SQFL | 00000000 PCB$L_SQFL ; ----------------------------------------------------- ; | PCB$L_SQBL | 00000004 PCB$L_SQBL ; ----------------------------------------------------- ; | PCB$B_PRI | PCB$B_TYPE | PCB$W_SIZE | 00000008 PCB$W_SIZE ; ----------------------------------------------------- ; | PCB$_MTXCNT |PCB$B_ASTEN |ACB$B_ASTACT| 0000000C PCB$B_ASTACT ; ----------------------------------------------------- ; | PCB$L_ASTQFL | 00000010 PCB$L_ASTQFL ; ----------------------------------------------------- ; | PCB$L_ASTQBL | 00000014 PCB$L_ASTQBL ; ----------------------------------------------------- ; | PCB$L_PHYPCB | 00000018 PCB$L_PHYPCB ; ----------------------------------------------------- ; | PCB$L_OWNER | 0000001C PCB$L_OWNER ; ----------------------------------------------------- ; | PCB$L_WSSWP | 00000020 PCB$L_WSSWP ; ----------------------------------------------------- ; | PCB$L_STS | 00000024 PCB$L_STS ; ----------------------------------------------------- ; | PCB$L_WTIME | 00000028 PCB$L_WTIME ; ----------------------------------------------------- ; | PCB$B_PRIB | PCB$B_WEFC | PCB$W_STATE | 0000002C PCB$W_STATE ; ----------------------------------------------------- ; | PCB$W_TMBU | PCB$W_APTCNT | 00000030 PCB$W_APTCNT ; ----------------------------------------------------- ; | PCB$W_PPGCNT | PCB$W_GPGCNT | 00000034 PCB$W_GPGCNT ; ----------------------------------------------------- ; | PCB$W_BIOCNT | PCB$W_ASTCNT | 00000038 PCB$W_ASTCNT ; ----------------------------------------------------- ; | PCB$W_DIOCNT | PCB$W_BIOLM | 0000003C PCB$W_BIOLM ; ----------------------------------------------------- ; | PCB$W_PRCCNT | PCB$W_DIOLM | 00000040 PCB$W_DIOLM ; ----------------------------------------------------- ; | PCB$T_TERMINAL | 00000044 PCB$T_TERMINAL ; - - ; | | ; ----------------------------------------------------- ; | PCB$L_PQB | 0000004C PCB$L_PQB ; ----------------------------------------------------- ; | PCB$L_EFCS | 00000050 PCB$L_EFCS ; ----------------------------------------------------- ; | PCB$L_EFCU | 00000054 PCB$L_EFCU ; ----------------------------------------------------- ; | unused |PCB$B_PGFLINDEX| PCB$W_PGBLCHAR | 00000058 PCB$W_PGFLCHAR ; ----------------------------------------------------- ; | PCB$L_SWAPSIZE | 0000005C PCB$L_SWAPSIZE ; ----------------------------------------------------- ; | PCB$L_PID | 00000060 PCB$L_PID ; ----------------------------------------------------- ; | PCB$L_EPID | 00000064 PCB$L_EPID ; ----------------------------------------------------- ; | PCB$L_EOWNER | 00000068 PCB$L_EOWNER ; ----------------------------------------------------- ; | PCB$L_PHD | 0000006C PCB$L_PHD ; ----------------------------------------------------- ; | PCB$T_LNAME | 00000070 PCB$T_LNAME ; - (16 bytes) - ; | | ; - - ; | | ; - - ; | | ; ----------------------------------------------------- ; | PCB$L_JIB | 00000080 PCB$L_JIB ; ----------------------------------------------------- ; | PCB$Q_PRIV | 00000084 PCB$Q_PRIV ; ----------------------------------------------------- ; | PCB$L_ARB | 0000008C PCB$L_ARB ; ----------------------------------------------------- ; | (44 bytes) | ; . ; | . | ; ----------------------------------------------------- ; | PCB$L_UIC | 000000BC PCB$L_UIC ; ----------------------------------------------------- ; | (60 bytes) | ; . ; | . | ; ----------------------------------------------------- ; | PCB$L_ACLFL | 000000FC PCB$L_ACLFL ; ----------------------------------------------------- ; | PCB$L_ACLBL | 00000100 PCB$L_ACLBL ; ----------------------------------------------------- ; | PCB$L_LOCKQFL | 00000104 PCB$L_LOCKQFL ; ----------------------------------------------------- ; | PCB$L_LOCKQBL | 00000108 PCB$L_LOCKQBL ; ----------------------------------------------------- ; | PCB$L_DLCKPRI | 0000010C PCB$L_DLCKPRI ; ----------------------------------------------------- ; | PCB$L_IPAST | 00000110 PCB$L_IPAST ; ----------------------------------------------------- ; | PCB$L_DEFPROT | 00000114 PCB$L_DEFPROT ; ----------------------------------------------------- ; | PCB$L_WAITIME | 00000118 PCB$L_WAITIME ; ----------------------------------------------------- ; | PCB$L_PMB | 0000011C PCB$L_PMB ; ----------------------------------------------------- ; ; The Process Control Block (PCB) contains permanently resident information ; about a process. The PCB for each process is pointed to by one of the ; PCB vector elements. The PCB is allocated from nonpaged pool. ; ; The fields we are interested in are: ; PCB$L_STS - If the PCB$V_NOACNT bit is set then no accounting is ; performed for this process. ; If the PCB$V_DELPEN bit is set then the process is ; pending deletion. ; ; PCB$T_TERMINAL - If this field is zero then we have a detached process. ; ; PCB$L_JIB - Address of the process's Job Information Block. ; ;------------------------------------------------------------------------------ ; ; JOB INFORMATION BLOCK (JIB) ; ----------------------------------------------------- ; | JIB$L_MTFL | 00000000 JIB$L_MTLFL ; ----------------------------------------------------- ; | JIB$L_MTBL | 00000004 JIB$L_MTLBL 7FFEDF68 SYS$IMGSTA ; ----------------------------------------------------- ; |JIB$B_DAYTYPES|JIB$B_TYPE| JIB$W_SIZE | 00000008 JIB$W_SIZE ; ----------------------------------------------------- ; | JIB$T_USERNAME | 0000000C JIB$T_USERNAME ; - (12 bytes) - ; | | ; - - ; | | ; ----------------------------------------------------- ; | JIB$T_ACCOUNT | 00000018 JIB$T_ACCOUNT ; - - ; | | ; ----------------------------------------------------- ; | JIB$L_BYTCNT | 00000020 JIB$L_BYTCNT ; ----------------------------------------------------- ; | JIB$L_BYTLM | 00000024 JIB$L_BYTLM ; ----------------------------------------------------- ; | JIB$L_PBYTCNT | 00000028 JIB$L_PBYTCNT ; ----------------------------------------------------- ; | JIB$L_PBYTLIM | 0000002C JIB$L_PBYTLIM ; ----------------------------------------------------- ; | JIB$W_FILLM | JIB$W_FILCNT | 00000030 JIB$W_FILCNT ; ----------------------------------------------------- ; | JIB$W_TQLM | JIB$W_TQCNT | 00000034 JIB$W_TQCNT ; ----------------------------------------------------- ; | JIB$L_PGFLQUOTA | 00000038 JIB$L_PGFLQUOT ; ----------------------------------------------------- ; | JIB$L_PGFLCNT | 0000003C JIB$L_PGFLCNT ; ----------------------------------------------------- ; | JIB$L_CPULIM | 00000040 JIB$L_CPULIM ; ----------------------------------------------------- ; | JIB$W_PRCLIM | JIB$W_PRCCNT | 00000044 JIB$W_PRCCNT ; ----------------------------------------------------- ; | JIB$W_SHRFLIM | JIB$W_SHRFCNT | 00000048 JIB$W_SHRFCNT ; ----------------------------------------------------- ; | JIB$W_ENQLM | JIB$W_ENQCNT | 0000004C JIB$W_ENQCNT ; ----------------------------------------------------- ; | JIB$W_MAXDETACH | JIB$W_MAXJOBS | 00000050 JIB$W_MAXJOBS ; ----------------------------------------------------- ; | JIB$L_MPID | 00000054 JIB$L_MPID ; ----------------------------------------------------- ; | JIB$L_JLNAMFL | 00000058 JIB$L_JLNAMFL ; ----------------------------------------------------- ; | JIB$L_JLNAMBL | 0000005C JIB$L_JLNAMBLS ; ----------------------------------------------------- ; | JIB$L_PDAYHOURS | 00000060 JIB$L_PDAYHOURS ; ----------------------------------------------------- ; | JIB$L_ODAYHOURS | 00000064 JIB$L_ODAYHOURS ; ----------------------------------------------------- ; | unused |JIB$B_JOBTYPE| 00000068 JIB$B_JOBTYPE ; ----------------------------------------------------- ; | JIB$L_ORG_BYTLM | 0000006C JIB$L_ORG_BYTLM ; ----------------------------------------------------- ; | JIB$L_ORG_PBYTLM | 00000070 JIB$L_ORG_PBYTLM ; ----------------------------------------------------- ; ; The Job Information Block contains information and quotas pooled by all ; processes in the same job. The JIB is pointed to by the PCB$L_JIB field ; of the PCB. The JIB is allocated from nonpaged pool. ; ; The fields we are interested in are: ; JIB$T_ACCOUNT - This field contains the account name for the process. If ; the account name is , then this process was created ; during system startup. ; ; JIB$T_USERNAME - This field contains the username of the process. We check ; for usernames SYSTEM and DECNET. ; ; JIB$L_CPULIM - This field contains the CPU time limit for the process. If ; the field is zero, then there is no CPU time limit. ; ;------------------------------------------------------------------------------ ; AST CONTROL BLOCK (AST) ; ----------------------------------------------------- ; | ASTQFL | ; ----------------------------------------------------- ; | ASTQBL | RMOD bits ; ----------------------------------------------------- 7 6 5 4 3 2 1 0 ; | RMOD | TYPE | SIZE | | | | | | | | | ; ----------------------------------------------------- K Q N P s s M | ; | PID | A U O K p p O ; ----------------------------------------------------- S O D A a a D ; | AST | T T E S r r E ; ----------------------------------------------------- A L T e e ; | ASTPRM | E ; ----------------------------------------------------- T ; | KAST | E ; ----------------------------------------------------- ; ; The Asynchronous System Trap Control Block (ACB) describes a pending AST ; for a process. An AST is linked into a process's PCB by procedure SCH$QAST. ; ; Fields we are interested in are: ; ASTQFL - AST queue forward link reference ; ASTQBL - AST queue backward link reference ; RMOD - bits <0:1> (ACB$V_MODE) contain the value corresponding to the ; access mode in which the AST routine is to execute. ; bit <4> (ACB$V_PKAST) when set, indicates the presence of a ; piggyback "special" kernel mode AST. ; bit <5> (ACB$V_NODELETE) when set, indicates that the ACB should ; not be deallocated after the AST is delivered. ; bit <6> (ACB$V_QUOTA) when set, indicates that the process AST ; quota, PCB$W_ASTCNT, has been charged for this ACB. ; bit <7> (ACB$V_KAST) when set, indicates the presence of a special ; kernel mode AST. ; ;------------------------------------------------------------------------------ ; Routine SCH$QAST in module ASTDEL in image SYS$SYSTEM:SYS.EXE ; ; Calling Sequence: ; JSB SCH$QAST ; ; Input Parameters: ; R2 - Priority increment class ; R5 - Pointer to AST control block ; ; Implicit Inputs: ; PCB of process [to queue AST to] identified by PID field [in AST] ; ; Output Parameters: ; R0 - Completion status code ; R4 - PCB address of process for which AST was queued ; ; Side Effects: ; The process identified by the PID in the AST control block ; will be made executable if not suspended. ; ; Completion Codes: ; SS$_NORMAL - Normal successful completion status ; SS$_NONEXPR - Non-existent process ; ;------------------------------------------------------------------------------ ; Routine EXE$ALONONPAGED in module MEMORYALC in image SYS$SYSTEM:SYS.EXE ; ; Description: ; This routine is called to allocate a block of memory from ; the nonpaged pool. ; ; Inputs: ; R1 = Size of block requested in bytes. ; ; Outputs: ; R0 = Return status. SS$_INSFMEM if memory not available. ; If success status then: ; R1 = size of allocated block ; R2 = address of allocated block ; ;------------------------------------------------------------------------------ ; Routine EXE$DEANONPAGED in module MEMORYALC in image SYS$SYSTEM:SYS.EXE ; ; Description: ; This routine is called to deallocate a block of memory to ; the nonpaged pool. ; ; Inputs: ; R0 = Address of block to be deallocated ; IRP$W_SIZE(R0) = Size of block to be deallocated ; IRP$B_TYPE(R0) = Type of block to be deallocated ; ; Side effecs: ; The specified block is returned to nonpaged pool. ; ;------------------------------------------------------------------------------ ; Routine EXE$EXCMSG in module EXCEPTMSG.LIS in image SYS$SYSTEM:SYS.EXE ; ; This routine prints a summary of the current process state and why the ; process received the exception. ; ; Calling Sequence: ; CALLS/CALLG EXE$EXCMSG ; ; Input Parameters: ; (AP) = 2 ; 4(AP) = ADDRESS OF ASCIZ STRING ; 8(AP) = ADDRESS OF SIGNAL ARGUMENT LIST ; ; SIGNAL ARGUMENT LIST ; ----------------------------------------- ; | | 2 | ; ----------------------------------------- ; | address of signal array | ; ----------------------------------------- ; | address of mechanism array | ; ----------------------------------------- ; ; SIGNAL ARRAY ; ----------------------------------------- ; | | n | ; ----------------------------------------- ; | condition name | ; ----------------------------------------- ; | arguments for condition | ; . handler, if any . ; . . ; . . ; | | ; ----------------------------------------- ; | PC | ; ----------------------------------------- ; | PSL | ; ----------------------------------------- ; ; MECHANISM ARRAY ; ----------------------------------------- ; | | 4 | ; ----------------------------------------- ; | establisher frame | ; ----------------------------------------- ; | depth | ; ----------------------------------------- ; | R0 | ; ----------------------------------------- ; | R1 | ; ----------------------------------------- ; ; ;------------------------------------------------------------------------------ ; Routine EXE$PRCPURMSG in module ACCOUNT.LIS in image SYS$SYSTEM:SYS.EXE ; ; This routine sends a message to the job controller telling it to write ; an accounting for this process. ; ; Calling Sequence: ; JSB EXE$PRCPURMSG ; ; Input Parameters: ; R4 = PCB address ; ; Output Parameters: ; R0 = status ; ; Side Effects: ; Routine returns at IPL #0 ; (Even though this technically violates the rule of never lowering ; IPL below the module's entry level IPL, closer analysis shows ; that no loss of synchronization can occur. In fact, this is the ; exact method used by VMS to dispatch a normal kernel mode AST. ; See VAX/VMS Internals and Data Structures version 4.4 pg 156 ; discussion on AST delivery flow.) ; ;------------------------------------------------------------------------------ ; ; NOTES: ; 1. Establishing a crash handler works only as long as the process is ; at or below IPL$_ASTDEL. When IPL is above IPL$_ASTDEL, the system ; crashes anyway. ; ; 2. No page faults are allowed when IPL is above IPL$_ASTDEL. All code ; and data that might be referenced while at elevated IPL must be locked ; in memory. ; ; 3. Raise IPL to IPL$_SYNCH when accessing system data structures. ; Aquire SCHED spinlock when in multiprocessing environment. ; ; 4. Don't drop IPL below ASTDEL while we have nonpaged pool allocated. ; Otherwise our process may be deleted and the nonpaged pool will be ; lost forever. ; (However, we can never be deleated while in a special kernel mode ; AST since no other AST can squeeze in front of a special kernel ; mode AST). ; ;------------------------------------------------------------------------------ .TITLE ZEROACC .LIBRARY /SYS$LIBRARY:LIB/ .LINK 'SYS$SYSTEM:SYS.STB' /SELECTIVE_SEARCH ; Global symbol definitions $ACBDEF $DSCDEF $DYNDEF $IPLDEF $JIBDEF $PCBDEF $PHDDEF $PRIDEF $RSNDEF $SSDEF $STATEDEF .PSECT STATIC RD,NOWRT,NOEXE,LONG,PIC LCKPGS: .ADDRESS MAIN_LOOP ;Lock in memory all code between MAIN_LOOP .ADDRESS NEXT ;and NEXT START: .ASCII // SYSTEM: .ASCII /SYSTEM/ DECNET: .ASCII /DECNET/ ;----------------------------------------------------------------------- .PSECT MAINCODE NOWRT,EXE,LONG .ENTRY RESETALL, ^M<> ;^M MOVAL HANDLER,(FP) ; Establish crash handler MOVL G^SCH$GL_PCBVEC,R10 ; R10 = Base address of PCB vector table MOVL G^SCH$GL_MAXPIX,R6 ; R6 = Number of vectors in PCB vector table MOVL (R10),R9 ; R9 = Address of PCB of NULL process ; Do the NULL and SWAPPER processes (NULL means slot not currently used) CLRL R11 ; Initialize offset MOVL R9,R7 ; R7 = Address of PCB of NULL process MOVL #RATE__NULL,R0 ; Set status JSB SIGMSG ; Signal status for this PCB INCL R11 ; Next PCB MOVL (R10)[R11],R7 ; R7 = Address of PCB of SWAPPER process MOVL #RATE__SWAPPER,R0 ; Set status JSB SIGMSG ; Signal status for this PCB INCL R11 ; Next PCB MAIN_LOOP: ;;; SETIPL #IPL$_SYNCH ; Synchronize access to PCBs LOCK SCHED,IPL$_SYNCH ; VMS 5.0 MOVL (R10)[R11],R7 ; Get address of next PCB to check ; R4 = Used for address of our PCB (destroyed by MOVC3 statement) ; R6 = Number of vectors in PCB vector table ; R7 = Address of PCB we're checking ; R8 <- Address of JIB of PCB we're checking ; R9 = Address of PCB of NULL process ; R10 = base address of PCB vector table ; R11 = offset into PCB vector table. Used as counter from 0 to maxpix ; ; Test to see if this is a process we want to skip ; We skip processes which have any of the following: ; PCB same as null process (test removed for VMS 5) ; accounting disabled ; account name ; username SYSTEM or DECNET ; delete pending ; Check for PCB same as NULL process CMPL R7,R9 ; Compare address of PCB with address of NULL process PCB BNEQ 10$ ; PCB not same as NULL process PCB MOVL #RATE__NULLPCB,R0 ; PCB same as NULL process BRW NEXT ; Set status and branch ; Check for accounting disabled 10$: BBC #PCB$V_NOACNT,- ; Check if accounting disabled PCB$L_STS(R7), 20$ ; MOVL #RATE__ACCDIS,R0 ; Set status BRW MSG ; and branch ; Check for no JIB (08-OCT-1990) 20$: MOVL PCB$L_JIB(R7),R8 ; Get JIB address BNEQ 30$ ; branch if JIB <> 0 MOVL #RATE__NOJIB,R0 ; else set status to NOJIB BRW MSG ; and branch ; Check for account (R8 = JIB) 30$: CMPC5 #8,JIB$T_ACCOUNT(R8),- ; Is account name ? #^x20,#7,START ; (CMPC5 destroys R0 - R3) BNEQ 40$ ; No. Go to next check MOVL #RATE__STARTUP,R0 ; Yes. Set status BRW MSG ; and branch ; Check for username SYSTEM 40$: CMPC5 #12,JIB$T_USERNAME(R8),-; Is username SYSTEM? #^x20,#6,SYSTEM ; (CMPC5 destroys R0 - R3) BNEQ 50$ ; No. Go to next test. MOVL #RATE__SYSTART,R0 ; Yes. Set status BRW MSG ; and branch ; Check for username DECNET 50$: CMPC5 #12,JIB$T_USERNAME(R8),-; Is username DECNET? #^x20,#6,DECNET ; (CMPC5 destroys R0 - R3) BNEQ 60$ ; No. Go to next test MOVL #RATE__DECSTART,R0 ; Yes. Set status BRW MSG ; and branch ; Check for delete pending 60$: BBC #PCB$V_DELPEN,- ; Check for delete pending PCB$L_STS(R7), QAST ; MOVL #RATE__DELPEN,R0 ; Delete pending. Set status BRW MSG ; and branch ; Process passed all checks. Queue AST to it. ; Allocate nonpaged pool for AST QAST: MOVZWL #,R1 ;Size of memory needed. JSB G^EXE$ALONONPAGED ;Allocate nonpaged memory to put BLBS R0,BLDAST ;Branch on success ; Wait for free memory MOVL #RSN$_NPDYNMEM,R0 ; R0 = resource to wait for MOVL G^CTL$GL_PCB,R4 ; R4 = address of our PCB (destroyed by MOVC3) MOVPSL -(SP) ; 04(SP) = PSL with which to resume PUSHAL QAST ; 00(SP) = PC at which to resume JMP G^SCH$RWAIT ; Wait for nonpaged pool. (IPL must be at #IPL$_SYNCH) ; When resource is available we resume at QAST ; Initialize AST header ; R1 = Size of nonpaged pool allocated (returned from EXE$ALONONPAGED) ; R2 = Address of nonpaged pool allocated (returned from EXE$ALONONPAGED) ; R7 = Address of PCB we're checking BLDAST: MOVW #,- ACB$W_SIZE(R2) ; Set size of block MOVB #DYN$C_ACB,- ; Set type of block ACB$B_TYPE(R2) ; MOVB #ACB$M_KAST,- ; Set RMOD to kernel mode AST ACB$B_RMOD(R2) ; MOVL PCB$L_PID(R7),- ; PID of process to send this to ACB$L_PID(R2) ; MOVAL ACB$K_LENGTH(R2),- ; Entry point of AST (AST code is placed right after ACB) ACB$L_KAST(R2); ; PUSHL R2 ; Save ACB address MOVC3 #AST_SIZE, AST_CODE,- ; Copy AST code into nonpaged pool. ACB$K_LENGTH(R2) ; (MOVC3 destroys R0 - R5) POPL R5 ; R5 = ACB address (was in R2) MOVL #PRI$_TICOM, R2 ; Set AST priority increment class JSB G^SCH$QAST ; Queue the AST BLBC R0,MSG ; Check status MOVL #RATE__QAST,R0 ; Set status MSG: ;;; SETIPL #0 ; Lower IPL UNLOCK SCHED,#0,,YES ; Save R0 to signal JSB SIGMSG ; Signal status for this PCB NEXT: ;;; SETIPL #0 ; Lower IPL (alternate entry point) UNLOCK SCHED,#0 AOBLEQ R6,R11,199$ ; Loop until all PCBs checked MOVL #RATE__NORMAL,R0 ; Set final status RET ; Normal exit here 199$: BRW MAIN_LOOP ;----------------------------------------------------------------------- .SUBTITLE ASTCODE .PSECT STATIC RD,NOWRT,NOEXE,LONG,PIC ; This is the SPECIAL KERNEL mode AST routine that will record and ; then reset the users accounting information. ; ; Inputs: ; R4 = Address of PCB (supplied by AST delivery) ; R5 = Address of ACB (supplied by AST delivery) ; ; Notes: ; Special kernel mode AST's enter at IPL$_ASTDEL (2) ; Return at IPL$_ASTDEL. ; Return with stack aligned as upon entry. ; Restore R6 - R11 if modified before returning. ; ; Register Usage: ; R3 = Address of JIB (Job Information Block) ; R4 = Address of PCB (Process Control Block) ; R5 = Address of ACB, Address of PHD ; LCKAST: .ADDRESS AST_CODE .ADDRESS AST_END AST_CODE: ; Write the process termination accounting record. ;;; DSBINT #IPL$_ASTDEL ; Save entry IPL PUSHL R5 ; Save ACB address CLRL R5 ; Do not let EXE$PRCPURMSG deallocate this AST. We're not done yet. JSB G^EXE$PRCPURMSG ; Let VMS write the accounting record. Routine returns at IPL #0. BLBC R0, EXIT ; Now clear the accounting data ; Check if process has a CPU time limit. ;;; SETIPL #IPL$_SYNCH ; Synchronize access to PCBs LOCK SCHED,IPL$_SYNCH,-(SP) ; VMS 5.0 MOVL G^CTL$GL_PHD,R5 ; R5 = process header address MOVL PCB$L_JIB(R4),R3 ; R3 = JIB address TSTL JIB$L_CPULIM(R3) ; Is there a CPU time limit? BEQL 10$ ; If =0 then no CPU limit ; Decrement CPU limit by amount already used. SUBL2 PHD$L_CPUTIM(R5),- ; Decrement CPU limit JIB$L_CPULIM(R3) ; TSTL JIB$L_CPULIM(R3) ; Test for no limit left BGTR 10$ ; Did not reduce limit<1 MOVL G^SGN$GL_EXTRACPU,- ; Put limit at SYSGEN parameter EXTRACPU JIB$L_CPULIM(R3) ; Reset accounting info back to zero. 10$: MOVZBL #1,PHD$L_CPUTIM(R5) ; Clear accumulated CPU time for process ; NOTE: We set CPUTIM to 1 instead of ; zero since 0 is displayed as ; November 17, 1858 by DCL command ; SHOW PROCESS/ACCOUNTING MOVL PHD$L_CPUTIM(R5),- PHD$L_TIMREF(R5) ; Set TIMREF to CPUTIM (08-OCT-1990) CLRL PHD$L_DIOCNT(R5) ; Clear direct I/O count CLRL PHD$L_BIOCNT(R5) ; Clear buffered I/O count CLRL PHD$L_PGFLTIO(R5) ; Clear page fault I/O count CLRL PHD$L_PAGEFLTS(R5) ; Clear page fault count CLRL PHD$L_IMGCNT(R5) ; Clear image activation count MOVQ G^EXE$GQ_SYSTIME,- ; Reset login time G^CTL$GQ_LOGIN ; CLRL G^CTL$GL_WSPEAK ; Reset working set peak size CLRL G^CTL$GL_VIRTPEAK ; Reset virtual page file peak size CLRL G^CTL$GL_VOLUMES ; Reset volumes mounted EXIT: ;;; ENBINT ; Restore original IPL UNLOCK SCHED,(SP)+ POPL R0 ; RESTORE ACB address (was in R5) JMP G^EXE$DEANONPAGED ; Deallocate nonpaged memory this AST ; was loaded in. At the end of ; EXE$DEANONPAGED is a RSB which ; returns control from this AST ; routine back to the user. AST_END: AST_SIZE = . - AST_CODE ;------------------------------------------------------------------------------ .SUBTITLE SIGMSG ;++ ; ; Functional Description: ; This routine prints the message for each PCB vector tested. ; ; Calling Sequence: ; JSB SIGMSG ; ; Inputs: ; R0 = Message ID by value ; R7 = Address of PCB ; ; Registers used: ; R8 <= Address of JIB ;-- .PSECT DATA RD,WRT,NOEXE,LONG BUFLEN=255 MSGBUFD: .WORD BUFLEN .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_S .ADDRESS MSGBUF MSGBUF: .BLKB BUFLEN FAOBUFD: .WORD BUFLEN .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_S .ADDRESS FAOBUF FAOBUF: .BLKB BUFLEN ; / NUM: PID PRC USR ACC MSG/ CTLPSD: .ASCID /!3SL: !XL !15AC !AF !AF !AS/ CTLNULD: .ASCID /!3SL: !XL !15AC !+!+ !+!+ !AS/ .PSECT MAINCODE NOWRT,EXE,LONG ; Call sys$getmsg SIGMSG: PUSHL #0 ;outadr PUSHL #1 ;flags (get text only) PUSHAQ MSGBUFD ;bufadr (address of descriptor) PUSHAW MSGBUFD ;msglen (by reference) PUSHL R0 ;msgid (by value) CALLS #5,G^SYS$GETMSG ;get message text ; Call sys$fao MOVL PCB$L_JIB(R7),R8 ;R8 points to the JIB PUSHAQ MSGBUFD ;message string PUSHAL JIB$T_ACCOUNT(R8) ;Account name PUSHL #8 ;Length of account name PUSHAL JIB$T_USERNAME(R8) ;Username PUSHL #12 ;Length of username PUSHAL PCB$T_LNAME(R7) ;Process name PUSHL PCB$L_EPID(R7) ;Extended PID by value PUSHL R11 ;Loop index by value PUSHAQ FAOBUFD ;outbuf PUSHAW FAOBUFD ;outlen SUBL2 #4,SP ;Adjust stack pointer for next argument MOVAQ CTLPSD,(SP) ;ctrstr TSTL R8 ;See if there was a JIB BNEQ 5$ ;There was a JIB MOVAQ CTLNULD,(SP) ;No JIB, use alternate control string 5$: CALLS #11,G^SYS$FAO ;format message string PUSHAL FAOBUFD ;Address of output descriptor CALLS #1,G^LIB$PUT_OUTPUT ;Output the string ; Reset buffer sizes MOVW #BUFLEN,MSGBUFD MOVW #BUFLEN,FAOBUFD RSB ;------------------------------------------------------------------------------ .SBTTL CONDITION HANDLER ;++ ; ; Functional Description: ; This routine handles unexpected errors that are signaled. ; Note if IPL is currently at or above ASTDEL the system will ; still crash. ; ; Inputs: ; CHF$L_SIGARGLST(AP) - Address of sigargs array ;-- .PSECT STATIC RD,NOWRT,NOEXE,LONG,PIC $CHFDEF ;Include CHF$ definitions HEADNG: .ASCIZ /ZEROACC KERNEL MODE ERROR/ .PSECT MAINCODE NOWRT,EXE,LONG .ENTRY HANDLER ^M<> MOVL CHF$L_SIGARGLST(AP),R0 ;Get address of signal args CMPL #SS$_UNWIND,- ;Check for unwind operation CHF$L_SIG_NAME(R0) BEQL 1$ ;Return if unwinding PUSHL AP ;Address of sigargs PUSHAL HEADNG ;Address of ASCIZ string CALLS #2,G^EXE$EXCMSG ;Dump error message CALLG (AP),G^LIB$SIG_TO_RET ;Unwind stack and return to caller 1$: RET ;------------------------------------------------------------------------------ .SUBTITLE MAIN ; This is the main entry point into the program. .PSECT STATIC RD,NOWRT,NOEXE,LONG,PIC STMSG1: .ASCID /Indx Extended Process name Username Account Status/ STMSG2: .ASCID /---- --PID -- --------------- ------------ -------- --------------------------/ ENDSTA: .ASCID /Final status was: !AS/ .PSECT MAINCODE NOWRT,EXE,LONG .ENTRY MAIN,^M<> ; Print header PUSHAL STMSG1 CALLS #1,G^LIB$PUT_OUTPUT PUSHAL STMSG2 CALLS #1,G^LIB$PUT_OUTPUT ;Lock pages in memory so we won't page fault at elevated IPL. $LKWSET_S inadr=LCKPGS BLBC R0,1$ $LKWSET_S inadr=LCKAST BLBS R0,2$ 1$: $EXIT_S R0 ; Abort with error status in R0 ; Enter main kernel mode routine 2$: $CMKRNL_S routin=RESETALL ; Call sys$getmsg PUSHL #0 ;outadr PUSHL #0 ;flags PUSHAQ MSGBUFD ;bufadr (address of descriptor) PUSHAW MSGBUFD ;msglen (by reference) PUSHL R0 ;msgid (by value) CALLS #5,G^SYS$GETMSG ;get message text ; Call sys$fao PUSHAQ MSGBUFD ;message string PUSHAQ FAOBUFD ;outbuf PUSHAW FAOBUFD ;outlen PUSHAQ ENDSTA ;ctrstr CALLS #4,G^SYS$FAO ;format message string ; Print final message and exit PUSHAL FAOBUFD CALLS #1,G^LIB$PUT_OUTPUT $EXIT_S .END MAIN