Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM-86/MPM-86 2.0 SOURCES/02/DSPTCH.RTM
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

384 lines
8.8 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;*****************************************************
;*
;* Dispatch Routines
;*
;*****************************************************
;=====
fdisp:
;=====
; This entry point used by interrupt routines in XIOS
cli
push ds ! mov ds,sysdat
cmp indisp,true ! jne do_dispatch
pop ds ! iret
do_dispatch:
mov es_sav,es
mov bx_sav,bx
mov bx,rlr
mov es,p_uda[bx]
mov u_in_int,true
pop u_ds_sav
push bx
mov bl,p_stat[bx]
mov u_stat_sav,bl
pop bx
mov p_stat[bx],ps_run
mov bx,es_sav
mov u_es_sav,bx
mov bx,bx_sav
jmp dsptch
;dispatcher will jump to here if
; u_in_int = true.
int_disp_exit:
mov u_in_int,false
mov bx_sav,bx
mov es_sav,ax
mov bx,rlr
mov al,u_stat_sav
mov p_stat[bx],al
mov ax,es_sav
mov bx,bx_sav
mov indisp,false
mov ds,u_ds_sav
mov es,u_es_sav
iret
;========
farpdisp:
;========
; Intermodule pdisp (non-interrupt)
call pdisp ! ret
;=====
pdisp:
;=====
; Call dispatcher with no special action
push bx ! mov bx,rlr
mov p_stat[bx],ps_run ! pop bx
;jmp dsptch
;======
dsptch:
;======
; The dispatch function looks like a noop to the
; caller. All flags and registers are maintained.
; No levels of user stack is used.
; (jmp dispatch = ret)
; Interrupt routines enter through fdisp.
;
; Dispatch has two (2) arguments:
; 1. the p_stat field of the process descriptor
; determines the type of action to perform
; for this process.
; 2. the dparam field of the uda is an argument
; to the action.
; The main part of the dispatch routine takes the
; currently running process off the Ready list
; and jmps to a routine which will put it on some
; other list depending on the p_stat argument.
; The subsequent routine will then jump to the
; scheduler which will do polling of devices and
; move processes off the dispatch ready list onto
; the Ready list. The Ready List is maintained
; in priority order with round-robin scheduling
; of processes with equivalent priorities. The
; first process on the ready list will then be
; switched in.
; set indisp flag
pushf ! cld ! cli
cmp indisp,true ! jne dispin
popf ! ret
dispin: mov indisp,true
pop u_flag_sav
; store and switch stack
mov u_ss,ss ! mov u_sp,sp
mov ss,sysdat ! mov sp,offset dsptchtos
sti
; save registers
; NOTE: We will use DS instead of ES
; No segment overrides...
push es ! pop ds
mov ds:u_ax,ax
mov ds:u_bx,bx
mov ds:u_cx,cx
mov ds:u_dx,dx
mov ds:u_di,di
mov ds:u_si,si
mov ds:u_bp,bp
; save interrupt vectors
; block move first 5
mov bx,0 ! mov ds,bx
mov si,bx ! mov di,offset u_ivectors
mov cx,10 ! rep movs ax,ax
; block move mpmint,debugint
mov si,offset i_mpm_ip ! mov di,offset u_mpm_ip
mov cx,4 ! rep movs ax,ax
; take current process off RLR.
mov ds,sysdat
cli
mov si,rlr
mov ax,p_link[si] ! mov rlr,ax
mov p_link[si],0
; We are now in NO-MAN's land
; From now until the end of the
; switch routine, There is no
; process in context.
; SI -> PD just taken out of context.
; jump to routine for given status
mov bh,0 ! mov bl,p_stat[si] ! shl bx,1
jmp cs:dsp_table[bx]
dsp_table dw disp_act ;00 - run
dw poll_act ;01 - poll device
dw delay_act ;02 - delay
dw swap_act ;03 - swap
dw term_act ;04 - terminate
dw sleep_act ;05 - sleep
dw disp_act ;06 - (nop)-dq
dw disp_act ;07 - (nop)-nq
dw flag_act ;08 - flag wait
;09 - (nop)-ciowait
sleep_act:
;---------
; insert running process into list specified by
; u_dparam and set p_stat from p_scratch
mov bx,u_dparam
push si ! call insert_process
pop si ! or p_flag[si],pf_resource
mov al,p_scratch[si] ! mov p_stat[si],al
jmp schedule
poll_act:
;--------
; set p_wait field of process = device number.
; put running process on poll list and wait
; for the device specified by u_dparam
; input: SI=pd address
mov dx,u_dparam
mov p_wait[si],dx
mov ax,plr ! mov p_link[si],ax
mov plr,si ! jmp schedule
delay_act:
;---------
; Put the running process on the Delay List. The
; delay list is built such that any process's
; remaining delay time is the additive of the delay
; times of all processes ahead of it plus the # of
; ticks in it's own p_wait field. At each clock tick
; the p_wait field of the top process in the list
; is decremented. If it reaches zero (0), all
; processes with a zero in the p_wait field are
; placed on the dispatch ready list.
; input: SI=pd address
push si ! mov al,io_strtclk
call xiosif ! pop si
mov bx,(offset dlr)-p_link
mov cx,u_dparam ! inc cx
cmp cx,0 ! jne del_lp
dec cx
del_lp: mov di,p_link[bx]
cmp di,0 ! je del_o
mov ax,p_wait[di]
cmp ax,cx ! ja del_o
sub cx,ax ! mov bx,di ! jmps del_lp
del_o: mov p_link[si],di ! mov p_link[bx],si
mov p_wait[si],cx
cmp di,0 ! je del_e
sub p_wait[di],cx
del_e: jmp schedule
swap_act:
;--------
; put running process on swap list
; input: SI=pd address
mov bx,(offset slr)-p_link
call insert_process ! jmp schedule
flag_act:
;--------
; place running process in flag table to wait
; for next flag. Note, flag may have been set...
; input: SI=pd address
; BX=address of Flag entry
mov bx,u_dparam
cmp flg_pd[bx],flag_on ! je gflagon
mov flg_pd[bx],si ! mov p_link[si],0
jmp schedule
gflagon: ; Flag set since wait check
mov flg_pd[bx],flag_off
jmps disp_act
term_act:
;--------
; terminate the running process
; free memory,free pd
; input: SI=pd address
mov ax,rlr
mov p_link[si],ax
mov rlr,si
mov ch,0 ! mov cl,ncondev
nxtcon: jcxz delst
dec cx ! mov p_cns[si],cl
push cx ! push si
mov cx,f_condetach ! call mpmif
pop si ! pop cx ! jmps nxtcon
delst: mov cl,nlstdev
nxtlst: jcxz free_nxt
dec cx ! mov dx,cx
add dl,ncondev
mov p_lst[si],dl
push cx ! push si
mov cx,f_lstdetach ! call mpmif
pop si ! pop cx ! jmps nxtlst
free_nxt:
push si
mov si,p_mem[si]
test si,si ! jz end_free
push ds ! sub cx,cx ! push cx
push ms_start[si]
mov ax,ss ! mov ds,ax ! mov dx,sp
mov cx,f_memfree ! call mpmif
pop bx ! pop cx ! pop ds ! pop si
jmps free_nxt
end_free:
mov mxmemowner,0
mov dx,offset mxmemqpb ! mov cx,f_qwrite
call mpmif
pop si
mov ax,p_link[si]
mov rlr,ax
mov p_link[si],0
call freepd ! jmp schedule
disp_act:
;--------
; place process on RLR
; input: SI=pd address
mov p_stat[si],ps_run
mov bx,(offset rlr)-p_link
call insert_process ! jmp schedule
;==============
insert_process:
;==============
;
; put PD# in list ordered by priority
;
; input: BX = list root
; SI = pd number
mov cx,pflag[si] ! and cx,pf_resource
ins_npd: mov di,p_link[bx]
cmp di,0 ! jz ins_out
mov al,p_prior[di]
cmp al,p_prior[si]
ja ins_out
jb ins_nxt
cmp cx,0 ! jz ins_nxt
jmps ins_out
ins_nxt: mov bx,di ! jmp ins_npd
ins_out: cmp cx,0 ! jz ins_exit
mov cx,pf_resource
not cx ! and p_flag[si],cx
ins_exit:
mov p_link[si],di ! mov p_link[bx],si ! ret
;=========
schedule:
;=========
; poll all required devices and place any ready
; processes on the Ready List
;we can enable interrupts now.
;there MUST be a process on the RLR
;at this point, ie. IDLE...
sti
;go through the Poll List
mov di,(offset plr)-p_link
;get the next PD on list.
;DI is the last one which
;has already been checked.
polld_another:
mov si,p_link[di]
;SI is the next PD to check
cmp si,0 ! jz drltorlr
;SI is valid PD, poll it.
push di ! mov cx,p_wait[si]
mov al,io_polldev ! call xiosif
pop di ! mov si,p_link[di]
;if AL=0, device not ready.
cmp al,0 ! je polld_next
;device ready,
;move SI from PLR to RLR
mov ax,p_link[si] ! mov p_link[di],ax
push di ! mov bx,(offset rlr)-p_link
mov p_stat[si],ps_run
call insert_process ! pop si
;p_link[SI]=next PD to check
polld_next: ;SI has been checked
mov di,si ! jmps polld_another
drltorlr:
;--------
; Pull all processes on the dispatch ready list and
; place them on the Ready List.
;We must disable interrupts while
;playing with DRL since interrupts
;doing a Flag_set may also.
cli ! mov si,drl
cmp si,0 ! jz switch
mov ax,p_link[si] ! mov drl,ax
mov p_stat[si],ps_run
mov bx,(offset rlr)-p_link
call insert_process
sti ! jmps drltorlr
switch:
;------
; switch to the first process on the Ready List
mov bx,rlr
mov dx,p_uda[bx] ! mov ds,dx
push dx ;UDA on stack
; restore interrupt vectors
mov ax,0 ! mov es,ax
mov si,offset u_ivectors ! mov di,ax
mov cx,10 ! rep movs ax,ax
mov si,offset u_mpm_ip
mov di,offset i_mpm_ip
mov cx,4 ! rep movs ax,ax
; restore registers
mov ax,ds:u_ax
mov bx,ds:u_bx
mov cx,ds:u_cx
mov dx,ds:u_dx
mov si,ds:u_si
mov di,ds:u_di
mov bp,ds:u_bp
; restore DS and ES and stack
pop es
mov ss,u_ss
mov sp,u_sp
mov ds,sysdat
cmp u_in_int,true ! jne dret
jmp int_disp_exit
dret: push u_flag_sav ! popf
mov indisp,false
ret