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*