home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
ctask.zip
/
TSKASM.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-03-01
|
7KB
|
389 lines
;
; CTask - Scheduler and miscellaneous utilities
;
; Public Domain Software written by
; Thomas Wagner
; Patschkauer Weg 31
; D-1000 Berlin 33
; West Germany
;
IFDEF at
.186
ENDIF
name tskasm
.model large
;
public scheduler
public _schedule
public _c_schedule
public _sched_int
;
public _tsk_dis_int
public _tsk_ena_int
public _tsk_cli
public _tsk_sti
public _tsk_dseg
public _tsk_flags
public _tsk_outp
public _tsk_inp
public _tsk_nop
;
;
include tsk.mac
;
INT_FLAG = 2h ; Int enable flag in upper byte of flag reg
r_flags = 24 ; Offset of flag register on task stack
;
.data?
;
extrn _tsk_current: dword
extrn _tsk_eligible: dword
extrn _tsk_preempt: byte
extrn _idle_tcb: word
extrn _tsk_pretick: byte
extrn _tsk_var_prior: byte
;
.code
;
_dgroup dw seg dgroup
;
;------------------------------------------------------------------------
;
; enq Enqueue tcb in queue. For local use only.
; entry: es:di = tcb to enqueue
; exit: -
; uses: ax, cx, dx, bp, di
;
enq proc near
;
lds bx,es:queue[di] ; queue head pointer
mov ax,ds
or ax,bx
jz enq_end ; nothing left to do if queue null
mov dx,es:prior[di] ; load priority of task
mov word ptr es:queue[di],bx ; init queue head pointer
mov word ptr es:queue+2[di],ds
enq_l:
mov cx,bx ; save last ptr
mov bp,ds
lds bx,next[bx] ; load next
mov ax,ds
or ax,bx ; end of chain?
jz enq_found ; then insert
cmp dx,prior[bx] ; compare priority
jbe enq_l ; loop if tasks prior less or equal
;
enq_found:
mov word ptr es:next[di],bx ; set tasks next pointer
mov word ptr es:next+2[di],ds
mov bx,cx ; last pointer
mov ds,bp
mov word ptr next[bx],di ; last->next = task
mov word ptr next+2[bx],es
enq_end:
ret
;
enq endp
;
;
; upd_prior: Update priority of tasks in eligible queue.
; Only activated if tsk_var_prior is nonzero.
;
upd_prior proc near
;
cmp _tsk_var_prior,0
je updp_end
;
les di,_tsk_eligible
pinc_loop:
mov ax,es
or ax,di ; end of chain?
jz updp_end
inc es:prior[di]
jnz pinc_nxt
dec es:prior[di]
pinc_nxt:
les di,es:next[di]
jmp pinc_loop
;
updp_end:
ret
;
upd_prior endp
;
;
; The scheduler. Note tat this routine is entered with the stack
; set up as for an interrupt handler.
;
scheduler proc far
;
cli
IFNDEF at
push ax
push cx
push dx
push bx
push sp
push bp
push si
push di
ELSE
pusha
ENDIF
push ds
push es
;
mov ds,_dgroup ; establish addressing of our vars
;
call upd_prior ; update priority
;
les di,_tsk_current ; get current tcb
mov word ptr es:stack[di],sp ; store stack pointer & seg
mov word ptr es:stack+2[di],ss
;
mov _tsk_pretick,0 ; No preemption tick
and _tsk_preempt,1 ; Turn off temp preempt flag
;
call enq ; Enqueue current task
;
mov ds,_dgroup
les di,_tsk_eligible
;
; If eligible queue empty, activate idle task.
;
mov ax,es
or ax,di ; is the eligible queue empty?
jnz not_empty ; jump if not
mov di,offset _idle_tcb ; else use idle tcb
mov es,_dgroup
jmp short sched_go
;
; Eligible queue not empty, activate first eligible task.
;
not_empty:
mov ax,word ptr es:next[di] ; load next pointer
mov word ptr _tsk_eligible,ax ; remove from queue
mov ax,word ptr es:next+2[di]
mov word ptr _tsk_eligible+2,ax
;
sched_go:
mov word ptr _tsk_current,di ; set tcb into current
mov word ptr _tsk_current+2,es
mov ax,es:iniprior[di] ; reset current tasks priority
mov es:prior[di],ax
;
lds si,es:stack[di] ; load stack
or byte ptr r_flags+1[si],INT_FLAG ; enable interrupts
mov es:state[di],ST_RUNNING ; set task state
mov cx,ds ; switch stack
mov ss,cx
mov sp,si
pop es ; restore all registers
pop ds
IFNDEF at
pop di
pop si
pop bp
pop bx ; don't pop SP
pop bx
pop dx
pop cx
pop ax
ELSE
popa
ENDIF
iret
;
scheduler endp
;
;
;--------------------------------------------------------------------------
;
;
; _sched_int
;
; Is the scheduler entry for interrupt handlers.
; It checks if preemption is allowed, returning if not.
; The stack is assumed to be set up as on interrupt entry.
;
_sched_int proc far
;
push ds
push bx
mov ds,_dgroup
cmp _tsk_preempt,0 ; preempt flags 0?
jne no_sched ; no scheduling if set
lds bx,_tsk_current ; current running task
test flags[bx],F_CRIT ; preemption allowed for this task?
jnz no_sched ; no scheduling if flag set
pop bx ; else go schedule
pop ds
jmp scheduler
;
no_sched:
mov ds,_dgroup
mov _tsk_pretick,1 ; Mark preemption pending
pop bx
pop ds
iret
;
_sched_int endp
;
;
; void far schedule (void)
;
; Entry for calling the scheduler. Rearranges the stack to
; contain flags.
; NOTE: Uses ax,bx.
;
_schedule proc far
;
pop ax
pop bx
pushf
push bx
push ax
cli
jmp scheduler
;
_schedule endp
;
;
; void far c_schedule (void)
;
; Entry for conditionally calling the scheduler. Rearranges
; the stack to contain flags, then jumps to _sched_int.
; NOTE: Uses ax,bx.
;
_c_schedule proc far
;
pop ax
pop bx
pushf
push bx
push ax
cli
jmp _sched_int
;
_c_schedule endp
;
;--------------------------------------------------------------------------
;
; word tsk_dseg (void)
;
; Returns current contents of DS register.
;
_tsk_dseg proc far
mov ax,ds
ret
_tsk_dseg endp
;
;
; word tsk_flags (void)
;
; Returns current contents of Flag register.
;
_tsk_flags proc far
pushf
pop ax
ret
_tsk_flags endp
;
;
; int tsk_dis_int (void)
;
; Returns current state of the interrupt flag (1 if ints were
; enabled), then disables interrupts.
;
_tsk_dis_int proc far
;
pushf
pop ax
mov cl,9
shr ax,cl
and ax,1
cli
ret
;
_tsk_dis_int endp
;
;
; void far tsk_ena_int (int state)
;
; Enables interrupts if 'state' is nonzero.
;
_tsk_ena_int proc far
;
push bp
mov bp,sp
mov ax,6[bp]
pop bp
or ax,ax
jz teiend
sti
teiend:
ret
;
_tsk_ena_int endp
;
;
; tsk_cli/tsk_sti: disable/enable int
;
_tsk_cli proc far
cli
ret
_tsk_cli endp
;
;
_tsk_sti proc far
sti
ret
_tsk_sti endp
;
;
; tsk_inp/tsk_outp: input/output from/to port
;
_tsk_inp proc far
;
push bp
mov bp,sp
mov dx,6[bp]
in al,dx
xor ah,ah
pop bp
ret
;
_tsk_inp endp
;
;
_tsk_outp proc far
;
push bp
mov bp,sp
mov dx,6[bp]
mov al,8[bp]
out dx,al
pop bp
ret
;
_tsk_outp endp
;
;
; void tsk_nop (void)
;
; Do nothing. Used for very short delays.
;
_tsk_nop proc far
;
jmp short tnop1
tnop1:
jmp short tnop2
tnop2:
ret
;
_tsk_nop endp
;
end