mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 17:34:06 +00:00
522 lines
13 KiB
Plaintext
522 lines
13 KiB
Plaintext
;*************************************************************
|
|
;*
|
|
;* Terminate and Abort Specify Process Entry Points
|
|
;*
|
|
;*************************************************************
|
|
|
|
;============== ==============
|
|
sysreset_entry: ; System Reset
|
|
;============== ==============
|
|
xor dx,dx
|
|
mov cx,f_terminate
|
|
jmp osif
|
|
|
|
;=============== ===============================
|
|
terminate_entry: ; Terminate - DX=terminate code
|
|
;=============== ===============================
|
|
; This entry point is used for a process to terminate itself. The
|
|
; code from the label 'TERMINATE:' on, is also used by a process to be
|
|
; terminated when it comes back into context, as set up by
|
|
; abort specified process.
|
|
|
|
mov bx,rlr
|
|
call abt_chk
|
|
jcxz terminate
|
|
jmp term_err
|
|
|
|
terminate: ;process terminated by abort
|
|
mov bx,rlr ;spec resumes execution here
|
|
cli ;interrupts off during stack switch
|
|
mov ss,p_uda[bx] ;reset the stack to top of UDA
|
|
mov sp,ulen
|
|
sti
|
|
|
|
mov p_prior[bx],abt_prior ;finish termination quickly
|
|
;abort spec can't force us
|
|
;to reenter terminate when
|
|
;we have best priority
|
|
|
|
mov bx,offset thrd_spb ;get ownership of thread
|
|
call sync_entry ;list before searching
|
|
|
|
xor dx,dx
|
|
mov bx,(offset thrdrt)-p_thread
|
|
mov ax,rlr
|
|
nxtchld:
|
|
mov bx,p_thread[bx] ;set all child process's p_parent
|
|
test bx,bx ! jz nochld ;field to 0
|
|
cmp p_parent[bx],ax
|
|
jne nxtchld
|
|
mov p_parent[bx],dx ;found a child, 0 its parent field
|
|
jmps nxtchld
|
|
nochld:
|
|
mov bx,offset thrd_spb
|
|
call unsync_entry
|
|
;set parent's child abort flag
|
|
mov bx,rlr ;if terminating process's
|
|
|
|
test p_flag[bx],pf_ctlc ;CTL_C flag is on, ie, we are
|
|
jz term_r1 ;terminating from an abort spec
|
|
and p_flag[bx],not pf_ctlc ;or control C
|
|
mov bx,p_parent[bx]
|
|
test bx,bx ! jz term_r1
|
|
or p_flag[bx],pf_childabort
|
|
term_r1:
|
|
mov u_error_mode,0feh ;call BDOS termination
|
|
mov cx,f_bdosterm
|
|
call osif
|
|
|
|
mov bx,offset q_spb
|
|
call sync_entry
|
|
call rlsmx ;release all MXqueues
|
|
mov bx,offset q_spb
|
|
call unsync_entry
|
|
|
|
mov bx,offset mem_spb ;get ownership of MEM
|
|
call sync_entry
|
|
mov mem_cnt,1 ;keep MEM from freeing
|
|
;the MEM_SPB
|
|
|
|
mov bx,offset thrd_spb ;get the MEM sync BEFORE
|
|
call sync_entry ;the THRD sync to avoid
|
|
;deadlock
|
|
|
|
mov cx,f_freeall ;free all memory except
|
|
call osif ;load stack and UDA
|
|
mov bx,rlr ;dispatcher does rest of
|
|
mov p_stat[bx],ps_term ;termination
|
|
jmp dsptch
|
|
|
|
term_err:
|
|
;--------
|
|
; entry: CX=1 then can't terminate because KEEP or SYS flag
|
|
; CX=0ffffh TEMPKEEP on, CTLC turned on
|
|
|
|
; called from TERMINATE_ENTRY and ABORT_SPEC_ENTRY
|
|
; after call to ABT_CHK:
|
|
|
|
dec cx ! jz term_err1
|
|
;TEMPKEEP and CTLC flag on
|
|
xor bx,bx ! mov cx,bx ;and process will terminate
|
|
ret ;itself, or needs CTLC information
|
|
|
|
term_err1:
|
|
mov cx,e_pd_noterm ;couldn't term because of
|
|
mov bx,0ffffh ! ret ;SYS or KEEP flags,
|
|
;CTLC is off
|
|
|
|
;================
|
|
abort_spec_entry: ;Abort the specified process
|
|
;================
|
|
; entry: DX = address of APB in the caller's U_WRKSEG
|
|
; exit: BX = 0 if success, 0FFFFH if failure
|
|
; CX = 0 " " , error code if failure
|
|
|
|
; Set up the specified PD for termination when it is next in context.
|
|
; If the running PD is the same as the PD to abort, we can just use
|
|
; the terminate entry point. Otherwise we use the Abort Parameter Block
|
|
; to find it. If it cannot be found, name and console must both match,
|
|
; the abort fails. If the TEMPKEEP flag is on, set the CTLC flag
|
|
; and return. If the KEEP flag is on and not the TEMPKEEP flag,
|
|
; then fail.
|
|
; If the terminate code in DL on entry, is not 0ffh
|
|
; and the SYS flag is on in the PD to be aborted, then fail.
|
|
; The PD is taken off the list it is attached to via its link field.
|
|
; The terminating PD's priority is set to ABT_PRIOR,
|
|
; and the address of TERMINATE: is put on top of its UDA stack.
|
|
; This forces the terminating process to run next (it has the
|
|
; best priority in the system) and for it to resume execution
|
|
; at TERMINATE: on returning from the dispatcher.
|
|
|
|
push dx
|
|
mov bx,offset thrd_spb ; get ownership of thread
|
|
call sync_entry ; while searching
|
|
pop si ; U_WRKSEG:SI->APB
|
|
|
|
push ds ! mov ds,u_wrkseg
|
|
mov bx,apb_pd[si] ; get PD adr to abort
|
|
mov cx,apb_term[si] ; get termination/memfree code
|
|
mov ah,apb_cns[si] ; console from APB
|
|
pop ds
|
|
push cx ; save termination code
|
|
test bx,bx ! jz abt_findit ; got a PD ID, but not verified
|
|
call find_pdthrd ; find it on thread
|
|
push cx ; save return code
|
|
jmps abt_unsync
|
|
|
|
abt_findit:
|
|
add dx,offset apb_pdname ; get adr of named PD
|
|
mov bx,offset thrdrt - p_thread ; find it on thread
|
|
call findpdnc ; look for PD name and console match
|
|
push cx ; save return code
|
|
abt_unsync:
|
|
push bx ; BX=PD if found
|
|
mov bx,offset thrd_spb
|
|
call unsync_entry
|
|
pop bx
|
|
pop cx ; CX=0 if no PD found
|
|
jcxz abt_err1
|
|
; successfully found PD
|
|
pop dx ; DX = terminate code
|
|
mov ax,rlr ; we are aborting ourselves
|
|
cmp ax,bx ; jump to TERMINATE_ENTRY
|
|
jne abt_notus
|
|
jmp terminate_entry
|
|
|
|
abt_notus:
|
|
mov indisp,true ; stop dispatching
|
|
;pushf ! cli ; do not let process or another
|
|
; process (NO_ABORT_SPEC) change the
|
|
or p_flag[bx],pf_ctlc ; flags while testing and acting on them.
|
|
call abt_chk ; ok to abort this PD ?
|
|
jcxz abt_ok
|
|
;popf ; can't abort it - return
|
|
call ok_disp
|
|
jmps term_err
|
|
|
|
; The interrupt window above may be lessened if the TERMINATE_ENTRY
|
|
; code is moved to the dispatcher and the status is set to PS_TERM.
|
|
; Turning interrupts back on, the aborting process could come
|
|
; back into context. Before turning on TEMPKEEP it would check
|
|
; its status, if it is PS_TERM, then it goes to the dispatcher
|
|
; to terminate.
|
|
|
|
abt_ok: ; this process will be aborted
|
|
mov dl,p_stat[bx] ; call abort function based on status
|
|
mov dh,0 ! mov di,dx
|
|
|
|
add di,di
|
|
call cs:abort_tab[di] ; find via p_link and take PD off its list
|
|
;popf
|
|
call ok_disp ; process can't come back into context
|
|
; so interrupts are ok
|
|
jcxz abt_err2 ; couldn't find PD on list by indicated
|
|
mov indisp,false ; by P_STAT
|
|
mov p_prior[bx],abt_prior
|
|
; set to low priority
|
|
push es ; save calling process' UDA
|
|
mov es,p_uda[bx] ; UDA of PD being aborted
|
|
mov si,(ulen-2) ; reset stack to top of UDA
|
|
mov u_sp,si
|
|
mov u_ss,es
|
|
mov es:[si],offset terminate
|
|
; TERMINATE: will be executed when
|
|
; terminating process comes back into
|
|
; context
|
|
xor ax,ax ; on exit from dispatcher interrupts
|
|
mov u_flag_sav,ax ; will be off
|
|
mov u_inint,false ; return into context with a RET and
|
|
; not an IRET
|
|
pop es ; ES=calling PD's UDA
|
|
call abt_putdrl
|
|
xor bx,bx ; indicate sucess
|
|
jmp pdisp ; force abort to happen before we return
|
|
; since terminating process has better
|
|
; priority
|
|
|
|
abt_err1:
|
|
pop dx ; throw out termination code
|
|
abt_err2:
|
|
mov cx,e_no_pdname ; set TERM_ERR for other returns
|
|
mov bx,0ffffh
|
|
ret
|
|
|
|
; The folowing are the abort handlers for a specific PD status.
|
|
; These labels are entered in the abort_tab(le) in the RTM data area.
|
|
; Interrupts assumed off.
|
|
; For all of the following:
|
|
; entry: BX = PD addr to be aborted
|
|
; AH = cons
|
|
; exit: CX=0 if error
|
|
; BX preserved
|
|
;
|
|
; abort_specified process jump table
|
|
;
|
|
; Status
|
|
abort_tab dw abtrun ; 0 = ready list root
|
|
dw abtslp ; 1 = poll
|
|
dw abtdly ; 2 = delay
|
|
dw abtslp ; 3 = swap
|
|
dw abttrm ; 4 = term
|
|
dw abtrun ; 5 = sleep
|
|
dw abtslp ; 6 = dq
|
|
dw abtslp ; 7 = nq
|
|
dw abtflg ; 8 = flagwait
|
|
dw abtslp ; 9 = ciowait
|
|
dw abtslp ; 10 = sync
|
|
abt_tablen equ offset $ - offset abort_tab
|
|
|
|
abtrun:
|
|
;-------
|
|
; On ready list root or dispatcher ready list
|
|
|
|
mov di,(offset rlr) - p_link
|
|
call find_pd
|
|
jcxz abtr_drl
|
|
jmps snip_it
|
|
abtr_drl: ; wasn't on rlr, try drl
|
|
mov di,(offset drl) - plink
|
|
jmps abt_common
|
|
|
|
abtslp:
|
|
;------
|
|
; On list indicated by u_dparam
|
|
; Note: a PD in the SY_NEXT field will not be found
|
|
; and cannot be terminated. Usually the PD has TEMPKEEP on
|
|
; so it never gets this far.
|
|
|
|
push es ! mov es,p_uda[bx]
|
|
mov di,u_dparam
|
|
pop es ! jmps abt_common
|
|
|
|
abtdly:
|
|
;------
|
|
mov di,offset dlr - p_link
|
|
call find_pd
|
|
jcxz abt_tab_err
|
|
mov si,p_link[si] ; Fix wait field in next PD on dlr
|
|
test si,si
|
|
jz ad_nofix ; Are there more PDs after the one
|
|
mov dx,p_wait[si] ; being aborted on the DLR ?
|
|
add dx,p_wait[bx] ; Add wait of aborting PD
|
|
mov p_wait[si],dx ; New value in next PD on dlr
|
|
ad_nofix:
|
|
jmps snip_it
|
|
|
|
abttrm:
|
|
;------
|
|
mov indisp,false
|
|
call pdisp ; we are terminating already
|
|
xor cx,cx ; make sure termination completes
|
|
jmps abt_tab_err ; before returning error
|
|
|
|
abtflg:
|
|
;------
|
|
xor cx,cx
|
|
mov di,u_dparam ; flag PD field asleep on
|
|
cmp bx,[di] ; if interrupts are allowed
|
|
jne aflg_err ; in this code, check DRL
|
|
inc flg_ignore[di] ; and RLR if not in flags
|
|
mov flg_pd[di],flag_off
|
|
inc cx
|
|
aflg_err:
|
|
ret
|
|
|
|
abt_common:
|
|
;----------
|
|
call find_pd ! jcxz abt_tab_err
|
|
;jmps snip_it
|
|
|
|
snip_it:
|
|
;-------
|
|
; Take PD out of linked list of PDs
|
|
; entry: BX = PD being sniped out
|
|
; DI = offset of previous PD or offset of root - p_link.
|
|
|
|
mov dx,p_link[bx] ; DX = next link
|
|
mov p_link[di],dx
|
|
ret ; CX<>0
|
|
|
|
abt_tab_err:
|
|
;-----------
|
|
ret ; CX = 0
|
|
|
|
;
|
|
; End of abort_tab(le) functions
|
|
;
|
|
|
|
|
|
abt_putdrl:
|
|
;-------
|
|
; Puts PD on DRL
|
|
; entry: BX = PD to insert
|
|
; exit: BX preserved
|
|
|
|
pushf ! cli
|
|
mov dx,drl
|
|
mov p_link[bx],dx
|
|
mov drl,bx
|
|
popf ! ret
|
|
|
|
; Utility routines for abort entry point
|
|
|
|
findpdnc:
|
|
;--------
|
|
; Find PD by name and console, via thread list.
|
|
; entry: BX = offset of thread list root - p_thread
|
|
; DX = adr of name in u_wrkseg
|
|
; AH = console number
|
|
; ownership of thread sync
|
|
; exit: BX = PD
|
|
; CX = 0 failure
|
|
|
|
xor cx,cx
|
|
nxt_pdname:
|
|
push ax ; save console number
|
|
call findpdname_entry
|
|
pop ax
|
|
jcxz fnc_found_one ; CX = 0 is success from findpdname
|
|
xor cx,cx
|
|
ret ; CX = 0 is failure from this routine
|
|
fnc_found_one: ; found PD w/ same name
|
|
cmp p_cns[bx],ah ; chk for same console #
|
|
jnz nxt_pdname
|
|
inc cx ! ret ; success
|
|
|
|
find_pdthrd:
|
|
;-----------
|
|
; Find PD on thread list
|
|
; entry: BX = PD address we want
|
|
; ownership of thread sync
|
|
; exit: CX = 0 if not found
|
|
; BX prserved
|
|
|
|
xor cx,cx
|
|
mov di,offset thrdrt - p_thread
|
|
fp_next:
|
|
mov di,p_thread[di]
|
|
test di,di
|
|
jz fp_err
|
|
cmp bx,di
|
|
jne fp_next
|
|
inc cx
|
|
fp_err:
|
|
ret
|
|
|
|
|
|
find_pd:
|
|
;-------
|
|
; Find PD through link field, interrupts assumed off
|
|
; entry: BX = PD address
|
|
; DI = offset of list root - p_link
|
|
; exit: BX = SI = PD address
|
|
; DI = Previous PD
|
|
; CX = 0 if failure
|
|
|
|
mov si,p_link[di]
|
|
xor cx,cx
|
|
fpd_nxt_pd:
|
|
test si,si ; SI could be zero to start
|
|
jz fpd_not_found
|
|
cmp si,bx ; Are addresses the same ?
|
|
jz fpd_found
|
|
fpd_nxt_lnk:
|
|
mov di,si ; Save previous link
|
|
mov si,p_link[si]
|
|
jmps fpd_nxt_pd
|
|
fpd_found:
|
|
inc cx
|
|
fpd_not_found:
|
|
ret
|
|
|
|
fflgpd:
|
|
;-----
|
|
; Find offset into flag table of flag waiting PD
|
|
; entry: BX = PD
|
|
; exit: DI = offset in RTM data of flag
|
|
; CX = 0 if failure
|
|
; BX preserved
|
|
|
|
mov cl,nflags
|
|
xor ch,ch
|
|
mov di,flags
|
|
ffp_nxt_flg:
|
|
cmp bx,flg_pd[di] ; assume legal flag
|
|
jz ffp_pdfound
|
|
add di,flglen
|
|
loop ffp_nxt_flg
|
|
ffp_pdfound:
|
|
ret ; CX is 0 at end of loop instr
|
|
; CX <> 0 if found
|
|
|
|
|
|
ok_disp:
|
|
;-------
|
|
mov indisp,false
|
|
cmp drl,0
|
|
jz od_ret
|
|
call pdisp
|
|
od_ret:
|
|
ret
|
|
|
|
|
|
|
|
abt_chk:
|
|
;-------
|
|
; Check different PD flags for terminate or abort
|
|
; CTLC flag is on if called from ABORT_SPEC
|
|
; entry: BX = PD to possibly abort
|
|
; DL = termination code
|
|
; interrupts off if called from ABORT_SPEC
|
|
; exit: CX = 00000H if ok to abort
|
|
; 00001H IF NOT OK TO ABORT
|
|
; 0FFFFH IF TEMPKEEP
|
|
; BX = PD as on entry
|
|
; interrupts unchanged
|
|
|
|
xor cx,cx
|
|
mov ax,p_flag[bx] ;AX = PD flags
|
|
|
|
;test TEMPKEEP first
|
|
;for signaling KEEP process
|
|
;to terminate i.e., the TMP
|
|
;while in the CLI
|
|
test ax,pf_tempkeep ! jz ac_keep
|
|
or ax,pf_ctlc ;signal control C
|
|
dec cx ;temp keep return
|
|
jmps ac_ret
|
|
ac_keep:
|
|
test ax,pf_keep ! jnz ac_no
|
|
;not KEEP, test SYS
|
|
inc dl ! jz ac_ok ;if DL = 0ffh -> ok to terminate
|
|
test ax,pf_sys ! jz ac_ok ;DL<>0ffh & not sys-> ok to terminate
|
|
ac_no:
|
|
and ax,not pf_ctlc ;turn off ctlc
|
|
inc cx ;CX=1, can't terminate
|
|
|
|
ac_ret:
|
|
mov p_flag[bx],ax ;new flags if no termination
|
|
ac_ok:
|
|
ret
|
|
|
|
rlsmx:
|
|
;-----
|
|
; Release all MX queues owned by the terminating process
|
|
; called only from TERMINATE_ENTRY
|
|
; entry: we own the Queue SYNC
|
|
; exit: none
|
|
|
|
; To guard against queue deletes, and to make interrupt
|
|
; windows are smaller, we start over from the beginning of
|
|
; QLR after we write to an MXqueue that we own.
|
|
|
|
mov bx,rlr ;BX=running process
|
|
; pushf ! cli
|
|
mov si,(offset qlr)-q_link
|
|
rm_nxt:
|
|
mov si,q_link[si] ;SI=QD currently checking
|
|
test si,si ;end of list ?
|
|
jz rm_done
|
|
test q_flags[si],qf_mx ;is it an MX queue ?
|
|
jz rm_nxt
|
|
cmp bx,q_buf[si] ;do we own it ?
|
|
jne rm_nxt
|
|
; popf ;allow interrupts
|
|
push si ;put 2-word QPB on stack
|
|
xor ax,ax
|
|
push ax
|
|
mov dx,sp
|
|
mov cx,f_qwrite
|
|
push ds ;save DS
|
|
push ss ! pop ds ;DS=SS
|
|
call osif
|
|
pop ds ;restore DS
|
|
pop ax ! pop ax ;throw out 2-word QPB
|
|
jmps rlsmx ;start over from
|
|
;top of queue list
|
|
;a queue could have been
|
|
;deleted while we were writing
|
|
rm_done:
|
|
; popf
|
|
ret
|