;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;	Program:	WSblaster
;	Author:		Bruce Ellis
;	Date Written:	9/28/87
;	Synopsis:	This program takes a Process Id
;			as input and adjusts the associated
;			process working set down to 200 pages.
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

	.library	/sys$library:lib.mlb/
	.link		/sys$system:sys.stb/

;^^^^^^^^^^^^^^^^^^^^
;Include definitions
;^^^^^^^^^^^^^^^^^^^^
	$pcbdef		;Process Control Block
	$dyndef		;Dynamic memory types
	$ipldef		;Interrupt Priority Level 
	$acbdef		;AST Control Block
	$pridef		;Priority Class 

	.macro	check	?l
	blbs	r0,l
	$exit_s	r0
l:
	.endm	check

pid_a:	.long	8		;Ascii representation of pid
	.address	10$
10$:	.blkb	10
pid:	.blkl	1		;Binary representation of pid
pmt:	.ascid	/pid> /
pid_arg:			;Argument list for exe$nampid
	.long	1
	.address	pid	;Pointer to pid
	.long	0
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;	User mode code
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	.entry	blaster,^m<>
	pushal	pid_a		;Read in pid
	pushal	pmt		; with prompt
	pushal	pid_a
	calls	#3,g^lib$get_input
	check
	pushal	pid		;Convert pid from Hex Ascii
	pushal	pid_a		; to a longword binary value
	calls	#2,g^ots$cvt_tz_l
	check
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;	Get into kernel mode and blast him
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	$cmkrnl_s	routin=negate_him,arglst=pid_arg
	ret

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;	Kernel mode code
;		1)	Checks the pid and converts to pcb address
;		2)	Allocates pool for an ACB including the
;			code for the special kernel AST
;		3)	Queues a Special Kernel AST to the process
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	.entry	negate_him,^m<r2,r3,r4,r5>
	setipl	#ipl$_astdel		;Don't delete me
	movl	#blaster_ast_size,r1	;Allocate the pool for
	jsb	g^exe$alononpaged	; the ACB+code
	blbc	r0,scram		;no pool then leave
	pushr	#^m<r0,r1,r2,r3,r4,r5>	;Copy the code into pool
	movc3	#blaster_ast_size,blaster_ast,(r2)
	popr	#^m<r0,r1,r2,r3,r4,r5>
	movw	r1,acb$w_size(r2)	;Fill in the size for later deletion
	movb	#dyn$c_acb,acb$b_type(r2)	;Set as an ACB
					;Setup address of the KAST code
	moval	<blaster_ast_code-blaster_ast>(r2),acb$l_kast(r2)
	movb	#0,acb$b_rmod(r2)	;
	bisb	#acb$m_kast,acb$b_rmod(r2)	;Send a Special KAST
	pushl	r2			;NAMPID hoses R2, thanks alot guys
	jsb	g^exe$nampid		;Find the guy
	popl	r2			;restore R2
	blbc	r0,cleanup
	movl	pcb$l_pid(r4),acb$l_pid(r2)	;Fill in his internal pid
	BEQL	err_out			;
	movl	r2,r5			;Setup ACB address in R5 for SCH$QAST
	movl	#pri$_ticom,r2		;Give him a big boost
	jsb	g^sch$qast		;Queue the AST
	movl	#ss$_normal,r0
scram:	setipl	#0
	
	ret				;All done
err_out:	
	movl	#ss$_nonexpr,r0		;Nobody home
cleanup:
	pushl	r0			;Save the error status
	movl	r2,r0			;Deallocate the pool
	jsb	g^exe$deanonpaged
	popl	r0
	brb	scram


;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;	ACB with the codde following
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
blaster_ast:
acb:	.blkb	acb$k_length		;Allocate space for a baseline ACB
old_ws:	.blkl	1			;saved working set size
blaster_ast_code:
	$adjwsl_s	wsetlm=old_ws	;get current wworking set size
	blbc	r0,escape		;if error get out
	pushl	r3			;Save r3
	subl3	#200,old_ws,r3		;compute the difference between
					;the current working set size and
					;the new size of 200 pages 
	blss	escape			;if he is already under then get out
	mnegl	r3,r3			;negate the difference
	$adjwsl_s	pagcnt=r3	;Adjust down to 200 pages
escape:	movl	r5,r0			;set up for deallocation
	popl	r3			;restore r3
	jmp	g^exe$deanonpaged	;get out of here
	blaster_ast_size=.-blaster_ast	;size of ACB plus code
	.end	blaster
