.title VPWSUBPRC - VPW subprocess control routines .ident 'V01-01' ;++ ; FACILITY: VPW Subroutine library ; ; ABSTRACT: This module contains the routines to create, ; delete and communicate with DCL subprocesses. ; ; ENVIRONMENT: Native/user-mode, non-privileged code ; ; AUTHOR: Neal Lippman/Douglass Wilson (MIT JCF) ; CREATION DATE: 9-MAR-1982 ; ; MODIFIED BY: J. Downward ; ;-- .page .sbttl Data declarations ; ; system include files: ; .library 'sys$library:starlet' $dibdef .library 'sys$library:lib' $logdef ; ; definition of a subprocess task block ; $defini stb $def stb_q_queue .blkq 1 ;queue pointer $def stb_l_pid .blkl 1 ;process identification $def stb_t_name .blkb 15 ;process name $def stb_w_cmdchan .blkw 1 ;command mbox channel $def stb_l_cmdefn .blkl 1 ;command mbox efn $def stb_b_flags .blkb 1 ;flags $def stb_b_prio .blkb 1 ;priority $def stb_k_length ;block length $defend stb ; ; read only data ; .psect vpwsubprc_read,rd,nowrt,noexe mbox_format: ;fao string for building device names .ascid '_!AC!UW:' num_bytes: ;number of bytes for silly library routine .long stb_k_length sysoutput: ;sys$output logical name .ascid 'SYS$OUTPUT' subprc_flag: ;flag for sub process create .long 1 ; ; read/write data ; .psect vpwsubprc_rw,rd,wrt,noexe stb_listhead: ;stb list header .long stb_listhead .long stb_listhead exit_block: ;exit handler block .blkl 5 exit_code: ;image exit status code .blkl 1 cmdmbxnam: ;buffer to build command mbox name .blkb log$c_namlength cmdmbxdesc: ;descriptor for above .long 0,cmdmbxnam initial_flag: ;flag for first call .byte 1 ;cleared on first call mem_addr: ;memory address buffer .blkl 1 iosb: ;io status block .blkw 1 io_size: .blkw 3 read_buffer: ;buffer for read qio .blkb 256 .psect vpwsubprc_code,rd,nowrt,exe .page .sbttl Subprocess create ;++ ; VPW_SUBCRE ; ; FUNCTIONAL DESCRIPTION: This routine starts a new subprocess running ; DCL. ; ; Istatus = VPW_SUBCRE(Ipntr,Process_name,Exit_Ast) ; ; Where Ipntr = Address to receive the STB pointer ; Process_name = Address of descriptor for process name ; Exit_Ast = Address of Exit AST routine ; Istatus = System service and library return code ; ; The STP pointer is returned to enable the subroutines to communicate ; with multiple subprocesses. If the process name is no-opped, the system ; will create a unique process name. ; ; ; SIDE EFFECTS: ; STB block is allocated and initialized. ; Process is created. ; Exit handler is declared on first call. ; ;-- .ENTRY VPW_SUBCRE,^M cmpb #3,(ap) ;validate number of arguments beql 5$ ;br if right number of aguments movzwl #ss$_insfarg,r0 ;set return code ret 5$: tstb initial_flag ;is this the first call beql subcre_notfirst ;no - branch around initialization code ; ; perform once only initialization ; moval exit_block,r0 ;get exit block address movaw exit_handler,4(r0) ;set exit handler address movzbl #2,8(r0) ;set arg count moval exit_code,12(r0) ;set exit status address $dclexh_s (r0) ;set the exit handler blbs r0,10$ ;okay to continue ret ;else, abort processing 10$: clrb initial_flag ;once only init done ; ; continue common processing ; SUBCRE_NOTFIRST: pushal mem_addr ;buffer for memory pushal num_bytes ;size of memory calls #2,g^lib$get_vm ;get memory blbs r0,20$ ;br if okay ret ;else abort 20$: movl mem_addr,r3 ;get memory address clrl stb_l_pid(r3) ;clear pid (mark block invalid) insque (r3),@ ;insert entry in queue ; ; now create a mailbox for the process sys$input ; $crembx_s - ;create mailbox chan=stb_w_cmdchan(r3) blbs r0,50$ ;br if okay brw subcre_cleanup ;abort processing 50$: subl #,sp ;build buffer on stack pushl sp ;build descriptor movzwl #,-(sp) ;... movl sp,r2 ;get descr addr $getchn_s - ;find out about mbox chan=stb_w_cmdchan(r3),- pribuf=(r2) addl #8,r2 ;point at dib buffer movl #log$c_namlength,cmdmbxdesc ;set size of output buffer movzwl dib$w_devnamoff(r2),r0 ;grab device name offset addl r2,r0 ;and compute device name addr movzwl dib$w_unit(r2),r1 ;get device unit $fao_s - ;format the mailbox name ctrstr=mbox_format,- outlen=cmdmbxdesc,- outbuf=cmdmbxdesc,- p1=r0,- ;device name p2=r1 ;device unit addl #,sp ;remove buffer from stack ; ; get event flag numbers ; pushal stb_l_cmdefn(r3) ;command efn calls #1,g^lib$get_ef ;get efn blbs r0,60$ ;failure? brw subcre_cleanup ;else abort ; ; create the process!!! ; 60$: clrq -(sp) ;clear completion routine addr and param tstl 12(ap) ;is there a complete routine specified? beql 80$ ;br if not movl r3,8(sp) ;set completion parameter movl 12(ap),4(sp) ;set completion routine address 80$: clrq -(sp) ;clear efn and completion status pushal stb_l_pid(r3) ;process id pushl 8(ap) ;process name desc addr pushal subprc_flag ;process nowait flag clrl -(sp) ;default sys$output pushaq cmdmbxdesc ;sys$input descr clrl -(sp) ;no command to execute calls #10,g^lib$spawn ;make the process blbc r0,subcre_cleanup ;handle error movl r3,@4(ap) ;return stb pointer movzwl #ss$_normal,r0 ;okay ret ; ; cleanup handler on error ; SUBCRE_CLEANUP: pushl r0 ;save exit status code remque (r3),r1 ;remove the entry from the que movl r1,mem_addr ;save address of block pushal mem_addr ;pushl block addr pushal num_bytes ;pushl size of block calls #2,g^lib$free_vm ;free the memory popl r0 ;get exit status code ret ;and return with status .page .SBTTL Subprocess Delete Routines ;++ ; FUNCTIONAL DESCRIPTION: This routine stops a subprocess ; ; CALLING SEQUENCE: ; CALLS/G ; Istatus = VPW_Stop(%VAL(Ipntr)) ; ; Where Ipntr = address of STB block (index) ; Istatus = Return status from system services ; ; ; SIDE EFFECTS: ; Process is stopped and stb block deallocated ; ;-- .ENTRY VPW_SUBSTOP,^M movl 4(ap),r1 ;get stb block address remque (r1),r3 ;attempt to remove the block bsbw free_block ;free the block movzwl #ss$_normal,r0 ;set success ret ;all done ;++ ; FUNCTIONAL DESCRIPTION: This routine performs a purge on all blocks ; ; Istatus = VPW_PURGE() ; ; Where Istatus = SS$_NORMAL if all goes ok ; ; SIDE EFFECTS: ; processes stopped and stb blocks released ; ;-- .ENTRY VPW_SUBPURGE,^M<> 10$: remque @,r3 ;get next block bvs 20$ ;br if done bsbw free_block ;free the block brb 10$ ;get next one 20$: movzwl #ss$_normal,r0 ;set success ret ; ; local subroutine to free up a stb block ; free_block: tstl stb_l_pid(r3) ;check block bneq 10$ ;br if valid rsb ;otherwise, don't process 10$: $delprc_s - ;stop process pidadr=stb_l_pid(r3) $dassgn_s - ;kill command mailbox chan=stb_w_cmdchan(r3) pushal stb_l_cmdefn(r3) ;push efn calls #1,g^lib$free_ef ;free it movl r3,mem_addr ;set into mem_addr pushal mem_addr ;push addr of block pushal num_bytes ;push block size calls #2,g^lib$free_vm ;free block movzwl #ss$_normal,r0 ;set success rsb .page .SBTTL EXIT HANDLER ;++ ; FUNCTIONAL DESCRIPTION: Exit handler ; ; CALLING SEQUENCE: ; CALLS/G from exit dispatcher ; ; INPUT PARAMETERS: ; None ; ; IMPLICIT INPUTS: ; Exit_code - ignored ; ; OUTPUT PARAMETERS: ; None ; ; IMPLICIT OUTPUTS: ; None ; ; COMPLETION CODES: ; None ; ; SIDE EFFECTS: ; ;-- .entry exit_handler,^m<> calls #0,vpw_subpurge ;delete all processes ret ;and return .page .SBTTL SEND A LINE TO A PROCESS ;++ ; FUNCTIONAL DESCRIPTION: This routine sends a message to the ; specified subprocess. ; ; CALLING SEQUENCE: ; CALLS/G ; ; Istatus = VPW_SUBSEND(%VAL(Ipntr),Cmdline) ; ; Where Ipntr = Address of STB block ; Cmdlin = Address of command line descriptor ; Istatus = System service return codes ; ; ; SIDE EFFECTS: ; None ; ;-- .ENTRY VPW_SUBSEND,^M movl 4(ap),r3 ;get stb block address movl 8(ap),r2 ;get command descr address movzwl (r2),r1 ;get string length $qiow_s - ;send the line efn=stb_l_cmdefn(r3),- ;event flag chan=stb_w_cmdchan(r3),- ;channel func=#io$_writevblk,- ;write virtual function p1=@4(r2),- ;address of buffer p2=r1 ;size of buffer blbs r0,10$ ;br if okay ret ;return with error 10$: bsbw set_rast ;set read attn ast bsbw set_wast ;set write attn ast $hiber_s ;sleep for a while bsbw clear_wast ;clear write attn ast movzwl #ss$_normal,r0 ;set success ret .page .sbttl ast set and clear routines ;++ ; FUNCTIONAL DESCRIPTION: Read and write ast clear and set ; routines ; ; CALLING SEQUENCE: ; BSBW/B ; ; INPUT PARAMETERS: ; None ; ; IMPLICIT INPUTS: ; None ; ; OUTPUT PARAMETERS: ; None ; ; IMPLICIT OUTPUTS: ; None ; ; COMPLETION CODES: ; None ; ; SIDE EFFECTS: ; AST routines execute (maybe) ; ;-- set_wast: movl #,r0 ;set function code movaw wast_handler,r1 ;set ast routine brw ast_common ;jump to common code clear_wast: movl #,r0 ;set function code clrl r1 ;no ast routine brw ast_common ;jump to common code set_rast: movl #,r0 ;set function code movaw rast_handler,r1 ;set ast routine brw ast_common ;jump to common code clear_rast: movl #,r0 ;set function code clrl r1 ;no ast routine ;fall through to common code ast_common: $qiow_s - ;set/clear ast chan=stb_w_cmdchan(r3),- ;channel func=r0,- ;function p1=(r1),- ;ast routine address p2=r3 ;stb block address rsb ;done .page .sbttl AST handlers ;++ ; FUNCTIONAL DESCRIPTION: Read attention AST handler ; ; CALLING SEQUENCE: ; CALLS/G from AST dispatch ; ; INPUT PARAMETERS: ; None ; ; IMPLICIT INPUTS: ; None ; ; OUTPUT PARAMETERS: ; None ; ; IMPLICIT OUTPUTS: ; None ; ; COMPLETION CODES: ; None ; ; SIDE EFFECTS: ; Process is woken up ; ;-- .entry rast_handler,^m<> $wake_s ;wake us up ret ;++ ; FUNCTIONAL DESCRIPTION: Write attn ast handler - read mbox and ; echo it to sys$output. ; ; CALLING SEQUENCE: ; CALLS/G from AST dispatch ; ; INPUT PARAMETERS: ; None ; ; IMPLICIT INPUTS: ; None ; ; OUTPUT PARAMETERS: ; None ; ; IMPLICIT OUTPUTS: ; Write to sys$output ; ; COMPLETION CODES: ; None ; ; SIDE EFFECTS: ; None ; ;-- .entry wast_handler,^m<> movl 4(ap),r3 ;set STB address $suspnd_s - ;suspend subprocess pidadr=stb_l_pid(r3) bsbw clear_rast ;clear read attn ast $qiow_s - ;read the write chan=stb_w_cmdchan(r3),- ;channel iosb=iosb,- ;iosb func=#io$_readvblk,- ;read virtual p1=read_buffer,- ;read it here p2=#256 ;and this many of em pushab read_buffer ;build output descr movzwl io_size,-(sp) ;... pushl sp ;push descr addr calls #1,g^lib$put_output ;play it, sam bsbw set_rast ;set read ast bsbw set_wast ;set write ast $resume_s - ;resume subproc pidadr=stb_l_pid(r3) ret ;another triumph for mankind .end