frenzy/job.asm

262 lines
4.9 KiB
NASM

B>type job.asm
.title "Job Scheduling"
.sbttl "FRENZY"
.ident JOBS
;~~~~~~~~~~~~~~~~~~~~
; multi-job System
;____________________
.insert EQUS
.extern Zap
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Job System Initialization
;____________________________
JobInit::
xra a ;reset man alternator
sta Man.Alt
lxi h,J.Used
lxi b,(MaxJob*JobLength)+2
jmp Zap
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Pass Control to next job
;____________________________
Next.J::
push y ;pc is on stack
push x ;save all registers
push h
push d
push b
push psw ;->job store area
call JobPtr ;returns in de
lxi h,0
dad sp ;hl->top of stack(the register set)
lxi b,JobLength ;move stack to store
LDIR
lxi h,J.Used ;move to next job
mov b,m ;# in use
inx h ;->J.Index
..loop: mov a,m
inr m ;++J.Index
cmp b ;see if we're last job
jrnz ..ok
mvi m,0
..ok: mov a,m ;is it man job
cpi 1 ;if so skip it
jrz ..loop
lxi h,Man.Alt ;check if time for man job
mov a,m
ora a
jrnz OK1
mvi m,1b ;reset alternator
lda J.Used ;check number of jobs used
ora a
jrz OK1 ;no man job yet so skip
call MJPtr ;->man job
jmpr GOJ
OK1: call JobPtr
GOJ: lxi h,SPos-JobLength
sphl ;->stack area
xchg
lxi b,JobLength ;move store to stack
LDIR
pop psw ;get this job's registers
pop b
pop d
pop h
pop x
pop y
ret ;and pc register too
;~~~~~~~~~~~~~~~~~~~~~~
; Return from man job
;______________________
Man.Next::
push y ;pc is on stack
push x ;save all registers
push h
push d
push b
push psw ;->job store area
call MJPtr ;returns -> man job in de
lxi h,0
dad sp ;hl->top of stack(the register set)
lxi b,JobLength ;move stack to store
LDIR
jmp OK1 ;go do next job
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Split off new job
;____________________________
J.FORK::
push b ;bc=starting PC for new job
push y ;also get set of input
push x ;registers for parms
push h
push d
push b
push psw
; check if possible to start a new job
lxi h,J.Used ;-># of jobs in use (0 is 1)
mov a,m
cpi MaxJob-1
jrc ..ok
lxi h,7*2 ;sorry no room
dad sp ;get rid of registers
sphl
stc ;aborto
ret
;ok to add a job
..ok: inr m ;++J.Used
call JLPtr ;get pointer to last job in de
lxi h,0
dad sp ;top ot stack frame
lxi b,JobLength
LDIR
pop psw ;restore mother registers
pop b
pop d
pop h
pop x
pop y
pop b ;was copy of bc=daughter pc
ora a ;nc means no problem
ret ;return to mother
;~~~~~~~~~~~~~~~~~~~~
; Delete Current Job
;____________________
JobDel::
lxi h,J.Used
mov a,m ;save
dcr m ;one less job active
inx h ;->J.Index
sub m ;J.Used-J.Index
jrnz ..move ;if = then this is last job
mvi m,0 ;reset J.Index
..go: call JobPtr ;de->frame
jmpr GOJ
..move: ;move jobs up j.index stays same
call JobPtr ;de->frame
lxi h,JobLength
dad d ;hl->next frame
xchg
push h
lxi h,Jobs+(MaxJob*JobLength) ;->end of job area
ora a
dsbc d ;hl=#of bytes to end of job area
mov b,h
mov c,l
pop h
xchg
LDIR
jmpr ..go
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Point to Job[J.Index] Storage Area
;_____________________________________
MJPtr: mvi c,1
.byte (3eh) ;mvi a,(mov c,m)
JLPtr: mov c,m
lxi h,Jobs
jmpr JP2
JobPtr: lxi h,J.Index
mov c,m ;current index
inx h ;->Jobs
JP2: mvi b,0
xchg
lxi h,0 ;hl=14*bc (J.Index*JobLength)
MULT JobLength
dad d ;Jobs[Jindex*JobLength]
xchg ;return de->job area
ret
;~~~~~~~~~~~~~~~~~~~~~~~
; Initialize the Timers
;_______________________
TimerInit::
lxi h,Talloc ;timer allocation area
lxi b,MaxTimer+(Maxtimer/8)
jmp Zap
;~~~~~~~~~~~~~~~~~~
; Allocate a Timer
;__________________
; returns hl->a timer byte
GetTimer::
push d
push b
push psw
lxi h,Talloc
lxi b,(MaxTimer/8)<8 ;#of timers:timer0
..alp: mov a,m ;get alloc bits
cpi -1 ;if not all 1's
jrnz ..get ;then find a zero bit
mvi a,8 ;move index up 8
add c
mov c,a
inx h ;->talloc group
djnz ..alp
..bad: pop psw
stc ;no timer available
jmpr ..ret
..get: mvi b,1 ;bit 0 mask
..blp: mov d,a ;save Talloc
ana b ;check bit
mov a,d ;restore Talloc
jrz ..ok
inr c ;up the index
rlcr b ;move bit left
jmpr ..blp
..ok: ora b ;set alloc bit
mov m,a ;set Talloc
mvi b,0 ;bc=timer #
lxi h,Timer0
dad b ;hl->special timer
pop psw
ora a
..ret: pop b
pop d
ret
;~~~~~~~~~~~~~~~
; Free a Timer
;_______________
; input hl->timer byte
FreeTimer::
push b
push psw
mvi m,0
lxi b,Timer0 ;find the offset
ora a
dsbc b ;hl=timer number
mov a,l
cpi 24
jrnc ..ret
lxi h,Talloc ;->talloc[0..7]
..idx: cpi 8 ;check index 0..7
jrc ..ok
inx h ;->talloc[+8]
sui 8 ;index-=8
jmpr ..idx
..ok: mvi b,#1 ;FEh bit 0 negitive mask
ora a ;index=0?
jrz ..fr
..blp: rlcr b ;move bit mask up
dcr a ;dec index
jrnz ..blp
..fr: mov a,b
ana m
mov m,a
..ret: pop psw
pop b
ret
;~~~~~~~~~~~~~~~~~~
; Put job to sleep
;__________________
; input A=number of 60ths to wait
J.WAIT::
pop y
call GetTimer
mov m,a
..lp: call NEXT.J
mov a,m
ora a
jrnz ..lp
call FreeTimer
pciy
.end