;
PURGEWS.MAR purge the workingset for a given process
;
; Kernel mode code to queue an AST to another process to purge the other
; process working-set. This routine is tested under VMS 5.2. I'm not shure
; if it will work under VMS 4.x.
;
; Input argument:
; PID of target process, passed by reference.
;
; Return status:
; SS$_NORMAL or any error messages...
;
; Usage (from fortran):
;
; external purge_ws, sys$cmkrnl
; integer*4 purge_ws, sys$cmkrnl
; integer*4 arg_list(2), pid
; .
; .
; pid = [pid of target process]
; arg_list(1) = 1
; arg_list(2) = %loc(pid)
; status = sys$cmkrnl (purge_ws,arg_list)
; if ( status .ne. ss$_normal ) call lib$stop (%val(status))
;
; Written by
; Joern Yngve Dahl-Stamnes
; The University of Trondheim
; The Norwegian Institute of Technology
; division of Physical Electronics
;
; e-mail:
; dahl-stamnes@elab-runit.sintef.no
; PSI%02422530001005::DAHLS
;
; fax:
; +7 59 14 41
;
.LIBRARY "SYS$LIBRARY:LIB"
;
; Some symbols are defined in SYS.STB.
; Declear some external symbols.
;
.LINK "SYS$SYSTEM:SYS.STB"/SELECTIVE_SEARCH
.EXTERNAL EXE$ALONONPAGED
.EXTERNAL EXE$DEANONPAGED
.EXTERNAL EXE$EPID_TO_IPID
.EXTERNAL SCH$QAST
.EXTERNAL SYS$PURGWS
$ACBDEF ; AST Control Block defs.
$IPLDEF ; IPL defs.
$SSDEF
;
; AP offset value.
;
PID = 4 ; Passed by reference.
.PSECT $CODE, PIC,CON,REL,LCL,SHR,EXE,RD,NOWRT,LONG
.ENTRY PURGE_WS, ^M
MOVL @PID(AP),R6 ; PID value --> R6.
;
; Allocate a block in non-paged pool for holding the AST Control Block
; (ACB) and the kernel mode code, both in the same block.
;
MOVAB ACSTART,R8 ; Start adr. to code --> R8.
MOVAB ACEND,R9 ; End adr. to code --> R9.
SUBL2 R8,R9 ; Calc. length of code.
ADDL3 #ACB$K_LENGTH, - ; Calc. length of block in non-paged pool
R9,R1 ; --> R1.
;
; Raise IPL to ASTDEL to avoid paging (Poor man's lockdown).
;
SETIPL $120 ; Raising IPL.
JSB G^EXE$ALONONPAGED ; Allocate block in non-paged pool
BLBC R0,$130 ; Go home if error...
;
; Fill data in ACB.
;
MOVL R2,R10 ; Save ACB/code adr. --> R10.
MOVZWL R1,ACB$W_SIZE(R10); Size of block.
MOVB #ACB$M_KAST, - ; Set KAST mode.
ACB$B_RMOD(R10)
MOVAB ACB$K_LENGTH(R10),-
ACB$L_KAST(R10) ; Adr. to code.
CLRL ACB$L_ASTPRM(R10) ; No arguments.
;
; Copy code to non-paged pool.
;
MOVC3 R9,(R8), -
ACB$K_LENGTH(R10)
;
; Convert EPID to IPID.
;
MOVL R6,R0 ; R0 = external PID.
JSB G^EXE$EPID_TO_IPID
TSTL R0 ; Does PID exist?
BNEQ $100 ; Yes, go on...
MOVL #SS$_NONEXPR,R0 ; No, report error
BRB $110 ; and deallocate block.
;
; Queue AST.
;
$100: MOVL R0,ACB$L_PID(R10) ; Insert IPID in ACB.
MOVL #2,R2 ; Prioritet boost class --> R2.
MOVL R10,R5 ; ACB adr. --> R5.
JSB G^SCH$QAST
BLBS R0,$130
;
; Error queueing AST or process does not exist, deallocate block in
; non-paged pool.
;
$110: MOVL R0,R9 ; Save condition code in R9.
MOVL R10,R0 ; ACB adr. --> R0.
JSB G^EXE$DEANONPAGED ; Deallocate ACB.
MOVL R9,R0 ; Restore condition code from R9.
BRB $130
$120: .LONG IPL$_ASTDEL ; IPL Level for above code.
;
; Set IPL to 0 and return.
;
$130: SETIPL #0
RET
;
; AST code. This code will be copied into non-paged pool by the above code
; and will be executed in the context of the target process in kernel mode.
; The purpose of this code is to:
;
; 1. Purge the working set to a minimum.
; 2. Deallocate block in non-paged pool.
;
ACSTART:
DSBINT #0, -
ENVIRON=UNIPROSESSOR
SUBL2 #8,SP ; Allocate space on stack.
MOVL SP,R0 ; R0 --> scratch space on stack.
CLRL (R0) ; Purge adr. range from 00000000
MOVL #^X7FFFFFFF,4(R0) ; to 7FFFFFFF.
PUSHR #^M ; Save argument adr. on stack.
CALLS #1,G^SYS$PURGWS ; Purger working set.
ADDL2 #8,SP ; Restore stack.
;
; Deallocate block from non-paged pool.
; R5 --> ACB.
;
MOVL R5,R0 ; Adr. to the block --> R0.
ENBINT
JMP G^EXE$DEANONPAGED
ACEND:
.END