.title lib_default_dir - obtain default directory of a process ;++ ; FACILITY: JCF SYSTEM PROGRAMS ; ; ABSTRACT: This routine obtains the default directory of a given ; process specified by process ID. It uses a special kernel ; mode AST to get the translation of SYS$DISK and the directory ; string in PIO$GT_DDSTRING of the processes virtual address ; space. ; ; ENVIRONMENT: Native, User and Kernel mode, privileged code ; Not reentrant -- do not call from AST level. ; ; AUTHOR: Michael R. Gretzinger ; DATE: 26-OCT-1982 ; ; Copyright (C) 1982 MIT Joint Computer Facility ; ; MODIFIED BY: Ned Freed (MATHLIB) converted program to routine. ; Extensive rewrite for VMS 4.0. ; ; Ned Freed (MATHLIB) converted to use LNM$SEARCH_ONE; ; LNM$SEARCHLOG isn't available in VMS 5.0. ; ; Call: ; ret-status.wlc.v = LIB_DEFAULT_DIR (pid.rl.r, dirstring.wt.ds) ;-- .library "SYS$LIBRARY:LIB" $STATEDEF $PCBDEF $PHDDEF $ACBDEF $IPLDEF $PRIDEF $PSLDEF $LNMDEF $LNMSTRDEF lnm_size = LNM$C_NAMLENGTH + LNMX$T_XLATION dd_size = 256 .psect $LOCAL, PIC,USR,CON,REL,LCL,NOSHR,NOEXE,RD,WRT,NOVEC,LONG pid: .long 0 device: .blkb lnm_size ddstring:.blkb dd_size .psect $CODE, PIC,USR,CON,REL,LCL,SHR,EXE,RD,NOWRT,NOVEC,LONG .entry lib_default_dir,^m clrb device+lnmx$t_xlation ;default to zero length strings clrb ddstring movl @4(ap),r0 ;prepare the pid jsb G^exe$epid_to_ipid ;convert to internal form movl r0,pid bneq 5$ ;check for pushl #ss$_nonexpr ;non-existent process brb 10$ ;blank strings and return 5$: $cmkrnl_s routin=get_defdir ;get into kernel mode for the ;real work pushl r0 ;save return status 10$: movl 8(ap),r6 ;get address of destination descr movw (r6),r7 ;grab length of destination string cvtbw device+lnmx$t_xlation,r8 ;grab length of device string movab @4(r6),r6 ;get address of destination string movc5 r8,device+lnmx$t_xlation+1,#^A/ /,- r7,(r6) ;install device string tstl r0 ;see if any room left bneq 20$ subw2 r8,r7 ;compute the remaining length bleq 20$ ;if none left just punt addw2 r8,r6 ;compute new address cvtbw ddstring,r8 ;get length of dd string movc5 r8,ddstring+1,#^A/ /,- r7,(r6) ;install dd string 20$: movl (sp)+,r0 ;retrieve status ret acb_l_origpid = acb$l_ast ;pid of requestor acb_l_imgcnt = acb$l_astprm ;image count in PHD acb_l_retloc = acb$l_kast+4 ;address to return data acb_s_retloc = 4 ;size of that address ;adjacency of next two items required acb_t_device = acb_l_retloc+acb_s_retloc ;SYS$DISK translation acb_s_device = lnm_size ;maximum size of it acb_t_ddstring = acb_t_device+acb_s_device ;default directory string acb_s_ddstring = dd_size ;directory string size acb_k_size = acb_t_ddstring+acb_s_ddstring ;total size of acb ;ast code follows data ; Routine to return device and directory data from the other process ; Note that code to execute in other process' context follows data ; in ast control block. .enable lsb .entry get_defdir,^m movl #,r1 ;size of non-paged buffer jsb G^exe$allocbuf ;allocate buffer for code and data blbs r0,1$ ;skip if no error ret ;return 1$: movl r2,r5 ;save address of packet movl pid,acb$l_pid(r5) ;set target pid movb #<1@acb$v_kast>,acb$b_rmod(r5) ;set special kernel ast movab acb_k_size(r5),acb$l_kast(r5) ;set address for ast movab device,acb_l_retloc(r5) ;set address of return location movl G^ctl$gl_pcb,r4 ;get address of current pcb movl pcb$l_pid(r4),acb_l_origpid(r5) ;set pid for return movl pcb$l_phd(r4),r4 ;get PHD address movl phd$l_imgcnt(r4),acb_l_imgcnt(r5) ;sequence number of image pushr #^m ;save regs for movc3 movc3 #codelen,code,@acb$l_kast(r5) ;copy code segment popr #^m ;restore registers ; The AST is queued to the destination process unless it has delete or ; suspend pending set, or is currently suspended. movl pid,r2 ;get target pid before synching begin_lock: setipl lock_ipl ;raise IPL to synch, lock code movl r2,r0 ;Call system routine for PCB jsb G^exe$ipid_to_pcb ;Since its not related to the PID movl r0,r4 movl #ss$_nonexpr,r0 ;assume non-existent process tstl r4 ;see if we had an error bneq 7$ ;skip if not brw 10$ ;exit if so 7$: cmpl pcb$l_pid(r4),r2 ;is pid same? bneq 10$ ;br if not tstl pcb$l_jib(r4) ;see if it has a jib beql 10$ ;if not, don't try to queue the AST bbs #pcb$v_delpen,pcb$l_sts(r4),10$ ;br if delete pending movl #ss$_suspended,r0 ;assume suspended process bbs #pcb$v_suspen,pcb$l_sts(r4),10$ ;br if suspend pending cmpw #sch$c_susp,pcb$w_state(r4) beql 10$ ;or if process suspended cmpw #sch$c_suspo,pcb$w_state(r4) beql 10$ ;or process suspended out of memory cmpw #sch$c_mwait,pcb$w_state(r4) beql 10$ ;or in MWAIT movzbl #pri$_ticom,r2 ;set priority increment class jsb G^sch$qast ;queue ast for target ; If process is in compute state and at a lower priority than the requesting ; process, boost its current priority to the requesting process's current ; priority. (Required because event reporting won't normallly boost a COM ; state process's priority). cmpw #sch$c_com,pcb$w_state(r4) ;process in compute state? beql 8$ cmpw #sch$c_como,pcb$w_state(r4) ;or compute out of memory? bneq 9$ 8$: movl G^ctl$gl_pcb,r3 ;get requestor's PCB address movb pcb$b_pri(r3),r0 ;get requestor's current priority cmpb r0,pcb$b_pri(r4) ;other process have a higher priority? bgequ 9$ ;if GEQU yes, don't boost priority cmpb #16,r0 ;will boost be into realtime priority? bgtru 9$ ;if GEQU yes, don't boost priority jsb G^sch$chsep ;boost other process's priority 9$: brw out_and_wait ;successful AST queued, go wait ; We were unable to deal with the specified process. Deallocate the system ; buffer and return. 10$: pushl r0 ;push error code movl r5,r0 ;get addr of AST packet jsb G^exe$deanonpaged ;deallocate the block setipl #0 ;restore IPL popl r0 ;restore status ret ;and return ; The AST is queued and the other process can handle it now. Lower ; IPL and wait for the response. out_and_wait: setipl #0 ;lower our IPL $HIBER_S ;SKAST will wake us up ret ;we're finished, return lock_ipl: .long ipl$_synch ;locate here to insure lock end_lock: assume le 512 ; Code placed in non-paged buffer executed in ; destination process context. .enable lsb code: pushr #^m ;we need these registers movl r5,r7 ;save ACB in non-volatile register ; We now translate SYS$DISK in the destination process context. This ; is done with calls to the internal LNM$ system routines. ; Translate SYS$DISK movzbl #8,r0 ;set logical name length movq #^A/SYS$DISK/,-(sp) ;push logical name onto stack moval (sp),r1 ;set logical name addr movzbl process_table,r2 ;length of table name moval process_table+1,r3 ;process name table name movl #psl$c_user,r5 ;access mode = user moval acb_t_device(r7),r6 ;point at lmnx buffer we have jsb G^lnm$search_one ;search for the logical name addl #8,sp ;clean stack blbs r0,44$ ;Exit on any error clrb acb_t_device(r7) ;Error - return zero length string ; Now get the default directory string 44$: movab acb_t_ddstring(r7),r2 ;get addr to put default directory movab G^pio$gt_ddstring,r1 ;get addr of def dir movb (r1),(r2)+ ;copy length movzbl (r1)+,r0 ;convert to longword movc3 r0,(r1),(r2) ;copy string movl r7,r5 ;restore ACB address popr #^m ;restore r6, r7 movl acb_l_origpid(r5),acb$l_pid(r5) ;turn the block around movab b^20$,acb$l_kast(r5) ;new AST routine movb #<1@acb$v_kast>,acb$b_rmod(r5) ;set kast again 6$: setipl #ipl$_synch ;raise IPL to synch, lock code movl acb_l_origpid(r5),r0 ;Get caller PID jsb G^exe$ipid_to_pcb ;Convert to PCB movl r0,r1 cmpl pcb$l_pid(r1),acb$l_pid(r5) ;same PID in both places bneq 8$ ;br if not bbs #pcb$v_delpen,pcb$l_sts(r1),8$ ;error if delete pending clrl r2 ;null priority increment jsb G^sch$qast ;queue the AST setipl #ipl$_astdel ;drop back to AST delivery level rsb ; If the process did not exist, or was marked for delete, deallocate the ; blocks and return. 8$: setipl #ipl$_astdel ;drop back to AST delivery level movl r5,r0 ;get buffer address jmp @#exe$deanonpaged ;deallocate it and exit process_table: .ascic /LOG$PROCESS/ ; This is the special kernel mode AST code for the requesting process ; that copies the data from the system buffer to the requestor's address ; space. It first checks to see if the process is running the same image ; that started all this. If not, it punts, deallocating the buffer and ; exiting. 20$: movl G^ctl$gl_phd,r3 ;get process header address cmpl phd$l_imgcnt(r3),acb_l_imgcnt(r5) ;see if the same beql 21$ ;br if okay movl r5,r0 ;set buffer address jmp G^exe$deanonpaged ;release the buffer and return 21$: movab acb_t_device(r5),r0 ;get addr of data movl acb_l_retloc(r5),r1 ;get addr to move data to pushr #^m ;save ACB address movc3 #,(r0),(r1) ;copy info popr #^m ;restore ACB 25$: movl acb$l_pid(r5),r1 ;get pid for wake movl G^ctl$gl_pcb,r4 ;get pid setipl #ipl$_synch ;raise to synch jsb G^sch$wake ;wake process setipl #ipl$_astdel ;lower ipl movl r5,r0 ;set address for release jmp G^exe$deanonpaged ;free block and exit codelen = .-code ;size of code segment .end