adelman@LBL-CSA1.ARPA (Kenneth Adelman) (07/10/87)
The following code allows you to set the CPU limit of a process
already executing. Unpack the files SETCPULIM.C and SETCPULIM-KERNEL.MAR,
compile them, and link them:
$ LINK/NOTRACE SETCPULIM,SETCPULIM-KERNEL,SYS$SYSTEM:SYS.STB/SELECTIVE
Define a foreign symbol to run SETCPULIM. First argument is the
PID of the target, second is the new CPU limit in SECONDS. Zero
implies infinite.
Could use some work on the user interface, but serves as a good
example of queueing special kernel ASTs to other processes. This is
necessary because the CPU limit is in the PHD, which might not be in
memory.
As always... Use at your own risk.
Kenneth Adelman
LBL
$ Write Sys$Output "Creating setcpulim.c"
$ Copy Sys$Input setcpulim.c
$ Deck/Dollars="*setcpulim.c*"
/* Program to poke the cpu limit of another process
This program queues a special kernel AST to the target process
to change its cpu limit.
*/
#include stdio
main(argc,argv)
int argc;
char *argv[];
{
long status, sys$cmkrnl(), arglst[3];
extern long pokecpulim();
if (argc != 3) {
fprintf(stderr,"Usage: %s pid cpulimt\n",argv[0]);
exit(0x10000000);
}
arglst[0] = 1;
if(!sscanf(argv[1],"%x",&arglst[1])) {
fprintf(stderr,"%s: error parsing pid\n",argv[0]);
exit(0x10000000);
}
if(!sscanf(argv[2],"%d",&arglst[2])) {
fprintf(stderr,"%s: error parsing cpulimit\n",argv[0]);
exit(0x10000000);
}
arglst[2] *= 100;
status = sys$cmkrnl(pokecpulim,arglst);
if (!(status&1)) return(status);
}
*setcpulim.c*
$ Write Sys$Output "Creating setcpulim-kernel.mar"
$ Copy Sys$Input setcpulim-kernel.mar
$ Deck/Dollars="*setcpulim-ker*"
.title setcpulim-kernel
;
; 4(AP) = PID
; 8(AP) = LIMIT
;
.library /SYS$LIBRARY:LIB/
$acbdef
spec_limit = acb$c_length
code_off = acb$c_length+4
$dyndef
$ipldef
$ssdef
$pcbdef
$phddef
$pridef
.entry pokecpulim,^m<r2,r3,r4,r5,r6>
;
; Get the internal PID of the process to queue the nASTy by
;
movl 4(ap),r0
jsb g^exe$epid_to_ipid
tstl r0
beql nonproc
movl r0,r6 ;save ipid
;
; Allocate a buffer to hold the ACB, three longwords of data, and the
; AST code.
;
movl #codelen+code_off,r1
jsb g^exe$allocbuf
blbs r0,10$
ret
10$: movl r2,r5 ;save address
;
; Fill in the ACB
;
movl r6,acb$l_pid(r5)
movb #dyn$c_acb,acb$b_type(r5)
movw #acb$c_length,acb$w_size(r5)
movb #1@acb$v_kast,acb$b_rmod(r5)
movab code_off(r5),acb$l_kast(r5)
;
; Copy the code and the new CPU limit.
;
movl 8(ap),spec_limit(r5)
pushl r5
movc3 #codelen,w^code,@acb$l_kast(r5)
popl r5
;
; Queue the nASTy
;
movzbl #pri$_ticom,r2 ;set priority increment class
movzwl acb$l_pid(r5),r0 ;destination pid
begin_lock:
dsbint lock_ipl
jsb g^sch$qast
enbint
ret
lock_ipl:
.long ipl$_synch
end_lock:
assume <end_lock-begin_lock> le 512
nonproc:
movl #ss$_nonexpr,r0
ret
;
; This *PIC* code executes in the context of the target.
;
code:
movl g^ctl$gl_phd,r1
movl spec_limit(r5),phd$l_cpulim(r1)
setipl #ipl$_astdel
movl r5,r0
jmp @#exe$deanonpaged
codelen = .-code
.end
*setcpulim-ker*