;******************************************************** ;* * ;* SYSTEM ENTRY FUNCTIONS * ;* * ;******************************************************** ;========== ========================= poll_entry: ; Poll device - DL=device ;========== ========================= mov ax,rlr mov bx,ax mov p_wait[bx],dx mov dx,offset plr mov bl,ps_poll jmp sleep_entry ;=========== =================== delay_entry: ;Delay - DX = ticks ;=========== =================== mov bx,rlr mov p_stat[bx],ps_delay mov u_dparam,dx xor bx,bx ;return success after coming back into jmp dsptch ;context from the dispatcher ;=============== ============== dispatch_entry: ;Call dispatch ;=============== ============== xor bx,bx ;return success ala DELAY_ENTRY: jmp pdisp ;=============== =========================== set_prior_entry: ;Set Priority - DX=priority ;=============== =========================== mov bx,rlr mov p_prior[bx],dl xor bx,bx ;return success ala DELAY_ENTRY: jmp pdisp ;======== ================== pd_entry: ;Return addr of PD ;======== ================== mov u_retseg,ds mov bx,rlr ret ;================ ============================ creat_proc_entry: ;Create Process - DX->new PD ;================ ============================ call proc_creat ! jmp pdisp ;=========== ============================== sleep_entry: ;Put Calling PD on System List ;=========== ============================== ; entry: DX = list root to sleep on ; BL = sleep status passed to the dispatcher in ; the PD.P_WAIT field and becomes the PD.STATUS ; when sleeping ; interrupts are typically off to ensure ; the PD sleeps on the specified list ; before another process runs. ; exit: BX = 0 to indicate success after return from dispatcher ; if entered with interrupts off the process will return ; from the dispatcher with them still off mov ax,rlr ! mov si,ax mov ax,dx ! mov u_dparam,ax mov p_scratch[si],bl mov p_stat[si],ps_sleep xor bx,bx jmp dsptch ;============ ============================== wakeup_entry: ;wakeup top PD in System List ;============ ============================== ; entry: DX = List Root Address ; exit: first PD on list is the last entry on the DRL ; Puting the process on the end of the DRL allows the ; process to run before equal priority processes waking up ; from flag sets, i.e., interrupts. ; To work, the dispatcher must disable interrupts ; from when the last process on the DRL is placed on the ; RLR to when the process is back in context and ; turns on the interrupt flag. pushf ! cli mov bx,dx ! mov si,[bx] ;SI=PD to wake test si,si ! jz wke_out ;check for a process to wake up mov ax,p_link[si] ;take PD off list mov [bx],ax ;set list root to next PD mov di,offset drl - p_link ;go to the end of DRL xor ax,ax ;AX=0 wu_drl: cmp p_link[di],ax je wu_drlend mov di,p_link[di] ! jmps wu_drl wu_drlend: mov p_link[di],si ;make waking PD last on DRL mov p_link[si],ax ;0 the end of the DRL mov p_stat[si],ps_run ;new status call pdisp wke_out: popf ! ret ;========== ======================== sync_entry: ;Obtain mutual exclusion ;========== ======================== ; entry: interrupts on or off ; BX = Sync Parameter Block ; exit: ownership of Sync Parameter Block, ; interrupt state unchanged ; Obtain ownership of mutually exclusive section of code ; without using MXqueues. A process only sleeps temporarily ; on a SYNC structure. A process that obtains the ; SYNC must call UNSYNC when finished with the ; protected data structure and before sleeping or ; calling SYNC with on a different SYNC structure. mov ax,rlr mov si,ax ;AX=SI calling process pushf ! cli xchg ax,sy_owner[bx] ;AX=owner test ax,ax ;0 nobody owns it jz s_got_it cmp ax,si ;do we already own it ? je s_got_it mov sy_owner[bx],ax ;restore owner lea dx,sy_wait[bx] ;list to sleep on mov bl,ps_sync ;sleep with sync status call sleep_entry ;awaken with sync ownership s_got_it: popf ! ret ;we own the SPB ;============ ========================== unsync_entry: ;release mutual exlclusion ;============ ========================== ; ; entry: BX = Sync Parameter Block ; exit: SYNC_OWNER changed to the PD in the SY_NEXT ; field if SY_NEXT is non 0. The PD in the SY_NEXT ; must have a 0 P_LINK. If SY_NEXT=0, the SY_OWNER ; field is changed to the first PD on the SY_WAIT ; list. If SY_WAIT is 0, SY_OWNER becomes 0. mov ax,rlr cmp ax,sy_owner[bx] ;do we own it ? jne us_ret xor ax,ax pushf ! cli ;no other process can change SYNC or DRL xchg ax,sy_next[bx] ;0 SY_NEXT field test ax,ax ;assigned next process ? jz us_wait mov si,ax jmps us_own us_wait: mov si,sy_wait[bx] ;give the sync to first waiting process test si,si ;no waiting PD ? jz us_zero mov ax,p_link[si] mov sy_wait[bx],ax mov p_link[si],0 us_own: mov p_stat[si],ps_run mov ax,drl mov p_link[si],ax ;put process on DRL mov drl,si us_zero: mov sy_owner[bx],si ;SI=0 or process to now own sync popf ;allow interrupts us_ret: ;wait for next dispatch ret ;================= ============================ assign_sync_entry: ;give away mutual exlclusion ;================= ============================ ; interrupts on ; entry: ; BX = Sync Parameter Block ; DX = address of list root, assign ; SPB to first PD on list ; exit: none ; mov ax,rlr cmp sy_owner[bx],ax ;check that we own the resource jne as_ret mov si,dx ;SI=list root pushf ! cli ;no other process can run mov di,[si] ;get first PD from list test di,di ;test for 0 list jz as_done mov ax,p_link[di] ;take PD off list mov [si],ax mov p_link[di],0 ;0 link of NEXT PD ;status is still PS_SLEEP. ;if TEMPKEEP is on ABORT_SPEC ;will just turn on CTLC flag. ;if no TEMPKEEP, ABORT_SPEC ;will not find PD on the U_DPARAM ;list and will fail. mov sy_next[bx],di ;see UN_SYNC_ENTRY ;for use of SYNC_NEXT field as_done: popf as_ret: ret ;============== no_abort_entry: ;============== ; Keep the calling process from being aborted by ; using the PF_TEMPKEEP flag. ; Turn on the PF_TEMPKEEP flag and ; increment the P_TKEEPCNT. ; entry: none ; exit: PD fields altered ; interrupt state unaltered ; This code must be exclusive of ABORT_SPEC's testing ; and acting on the PD flags. mov ax,rlr mov si,ax na_spec: cmp p_tkcnt[si],0 jne na_saved test p_flag[si],pf_tempkeep jz na_saved or p_tkcnt[si],80h ;save orignal TEMPKEEP in MSB na_saved: ;until rest of O.S. is fixed or p_flag[si],pf_tempkeep inc p_tkcnt[si] ret ;=================== no_abort_spec_entry: ;=================== ; Keep the specified process from being aborted by setting ; its TEMPKEEP flag. ; entry: DX=PD address, interrupts off ; exit: PD TEMPKEEP turned on, TKCNT incremented mov si,dx jmps na_spec ;============== ok_abort_entry: ;============== ; Allow the calling process to be aborted if ; the PF_TEMPKEEP flag is keeping it from being aborted. ; P_TKCNT is decremented in the PD, if P_TKCNT ; is = 0 then PF_TEMPKEEP is turned off and PF_CTLC ; flag is tested. ; Interrupts should be turned off if an NO_ABORT_SPEC ; can be performed on a process running this code. ; entry: none ; exit: PD fields altered mov ax,rlr mov si,ax mov al,p_tkcnt[si] and al,07FH ;high bit is original TEMPKEEP dec al jz oa_restore ;assume dec p_tkcnt[si] ;no borrow from MSB ret oa_restore: if netversion and p_tkcnt[si],80H ;was TEMPKEEP on originally ? endif if not netversion test p_tkcnt[si],80h endif jnz oa_ret ;if it was don't chk CTLC here ;turn off TEMPKEEP and p_flag[si],not pf_tempkeep test p_flag[si],pf_ctlc jz oa_ret mov dx,0ffffh ;if PF_CTLC is set ok to if netversion push si call terminate_entry ;terminate even if SYS PD, pop si endif ;see ABT_CHK in ABORT.RTM ;terminate may fail if ;KEEP was set while if not netversion call terminate_entry endif oa_ret: ;TEMPKEEP was also set. mov p_tkcnt[si],0 ret