home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_progs
/
prog_c
/
suplib.lzh
/
SUPLIB
/
SRC
/
MISC2.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-08-16
|
10KB
|
449 lines
section DATA,DATA
xref _SysBase
section CODE
include "exec/types.i"
include "exec/ports.i"
include "exec/tasks.i"
include "exec/execbase.i"
include "exec/ables.i"
include "exec/memory.i"
; NOTE: LockAddr/UnLockAddr referenced elsewhere in
; this library
; MISC2.ASM
xref _LVOPutMsg
xdef _DoSyncMsg
xdef _WaitMsg
_DoSyncMsg: movem.l 4(sp),A0/A1
movem.l A2/A3/A6,-(sp) ; A0=port, A1=msg
move.l _SysBase,A6 ; A6=execbase
sub.w #MP_SIZE,sp ; initialize reply port
move.b #NT_MSGPORT,LN_TYPE(sp)
move.b #PA_SIGNAL,MP_FLAGS(sp)
move.b #4,MP_SIGBIT(sp) ; EXEC semaphore signal
move.l ThisTask(A6),MP_SIGTASK(sp)
lea MP_MSGLIST(sp),A2
lea MP_MSGLIST+4(sp),A3
move.l A3,(A2) ; &tail -> head
move.l #0,(A3) ; NULL -> tail
move.l A2,8(A2) ; &head -> tailpred
move.l sp,MN_REPLYPORT(A1)
move.l A1,A2 ; save message
jsr _LVOPutMsg(A6) ; send the message
move.l A2,-(sp)
bsr _WaitMsg
addq.l #4,sp
add.w #MP_SIZE,sp
movem.l (sp)+,A2/A3/A6
rts
xdef _CheckMsg
_CheckMsg: move.l 4(sp),A0
moveq.l #0,D0
cmp.b #NT_MESSAGE,LN_TYPE(A0) ;NT_MESSAGE == not replied
beq .lcm1
move.l A0,D0
.lcm1 rts
xdef _CheckPort
_CheckPort: move.l 4(sp),A0
moveq.l #0,D0
move.l MP_MSGLIST+LH_HEAD(A0),A0
tst.l (A0) ;list empty?
beq .lcp1
move.l A0,D0 ;no, return first element
.lcp1 rts
xref _LVOWait
xref _LVORemove
xref _LVODisable
xref _LVOEnable
xdef _WaitMsg
_WaitMsg: move.l 4(sp),A0
movem.l A2/A3/A6,-(sp)
move.l A0,A2 ;A2 = message
move.l MN_REPLYPORT(A0),A3 ;A3 = replyport
move.l _SysBase,A6 ;A6 = execbase
.wmloop cmp.b #NT_MESSAGE,LN_TYPE(A2) ;while msg not replied
bne .wm1
move.b MP_SIGBIT(A3),D1 ;Wait on port signal
moveq.l #0,D0
bset.l D1,D0
jsr _LVOWait(A6)
bra .wmloop
.wm1 jsr _LVODisable(A6) ;remove from port
move.l A2,A1 ;A1 = message (A2)
jsr _LVORemove(A6)
jsr _LVOEnable(A6)
move.l A2,D0 ;return message
movem.l (sp)+,A2/A3/A6
rts
;WILDCMP(wild:D0, name:D1)
;
; Handles * and ?
;
;result: D0, 0 = no match, 1 = match
;
;auto:
; D2 bi
; A2 wildcard string
; A3 name string
; A4 back-array (of size MAXB * 2 * 4)
MAXB EQU 8
xdef _WildCmp
_WildCmp: movem.l 4(sp),D0/D1
movem.l D2/A2-A4,-(sp)
move.l D0,A2
move.l D1,A3
sub.l #MAXB*2*8,sp
move.l sp,A4
moveq.l #0,D2
.wcloop moveq.l #1,D0
move.b (A2),D1
bne .w1
tst.b (A3)
beq .wcdone
.w1 cmp.b #'*',D1
bne .w10
cmp.w #MAXB,D2
bne .w2
moveq.l #-1,D0 ; error
bra .wcdone
.w2 move.w D2,D0 ; back[bi][0] = w i.e. back+bi*8
asl.w #3,D0 ; back[bi][1] = n
move.l A2,0(A4,D0.w)
move.l A3,4(A4,D0.w)
addq.w #1,D2
addq.l #1,A2
bra .wcloop
.wgoback subq.w #1,D2
bmi .w5
move.w D2,D0
asl.w #3,D0
move.l 4(A4,D0.w),A0
tst.b (A0)
beq .wgoback
.w5 tst.w D2
bmi .wcret0
move.w D2,D0
asl.w #3,D0
move.l 0(A4,D0.w),A2
addq.l #1,A2
add.l #1,4(A4,D0.w)
move.l 4(A4,D0.w),A3
addq.l #1,D2
bra .wcloop
.w10 cmp.b #'?',D1
bne .w20
tst.b (A3)
bne .wcbreak
tst.w D2
bne .wgoback
bra .wcret0
.w20 move.b (A3),D0
cmp.b #'A',D0
bcs .w21
cmp.b #'Z',D0
bhi .w21
or.b #$20,D0
.w21 move.b (A2),D1
cmp.b #'A',D1
bcs .w22
cmp.b #'Z',D1
bhi .w22
or.b #$20,D1
.w22 cmp.b D0,D1
beq .wcbreak
tst.w D2
bne .wgoback
bra .wcret0
.wcbreak tst.b (A2)+
bne .wcb1
subq.l #1,A2
.wcb1 tst.b (A3)+
bne .wcb2
subq.l #1,A3
.wcb2 bra .wcloop
.wcret0 moveq.l #0,D0
.wcdone add.l #MAXB*2*8,sp
movem.l (sp)+,D2/A2-A4
rts
; LOCKS
;
; { LOCKADDR STRUCTURE
; ulong Link; dynamic linking of blocked requests
; ubyte LockByte; bset to here
; ubyte Reserved; reserved for future use (flags?)
; EXTENSIONS FOR TASKLOCK
; uword Refs; reference count same-task has-locked
; ulong Task; task address
; }
;
; long var[3] = { 0, 0, 0 };
;
; These routines work exactly like the lockaddr but maintain
; an additional reference count, allowing the same task to
; lock the same lock any number of times (the same number of
; unlocks are required to unlock the lock)
;
; Only one lock is available per structure
;
; TaskLock(&var[0]:A0)
; TaskUnlock(&var[0]:A0)
_lTaskLock:
move.l _SysBase,A1 ; task address used for ident
move.l ThisTask(A1),A1
bset.b #0,4(A0) ; try to get lock fast
beq .tl10 ; beq success
cmp.l 8(A0),A1 ; failure, but is it the same task?
beq .tl11 ; yes, success
movem.l A0/A1,-(sp) ; failure, different task, block.
moveq.l #0,D0 ; D0 = bit#, A0 = lock ptr
bsr LA0 ; get lock the hard way
movem.l (sp)+,A0/A1
.tl10 move.l A1,8(A0) ; success, store owner
.tl11 add.w #1,6(A0) ; success, bump ref count
rts
;;BREAKUP lockaddr.asm
; long var[2] = { 0, 0 };
;
; These routines provide fast exclusive
; locks. Up to 8 independant locks may be used for
; each 4 byte address.
;
; LockAddr(&var[0]:A0)
; LockAddrB(bit:D0, &var[0]:A0)
; UnlockAddr(&var[0]:A0)
; UnlockAddrB(bit:D0, &var[0]:A0)
; TryLockAddr(&var[0]:A0)
; TryLockAddrB(bit:D0, &var[0]:A0)
xref _LVOWait
xref _LVOForbid
xref _LVOPermit
xdef _LockAddr
xdef _LockAddrB
xdef _TryLockAddr
xdef _TryLockAddrB
IFD LATTICE
xdef @LockAddr
xdef @LockAddrB
xdef @TryLockAddr
xdef @TryLockAddrB
ENDC
_TryLockAddrB: movem.l 4(sp),D0/A0
bra TLA0
_TryLockAddr:
move.l 4(sp),A0
IFD LATTICE
@TryLockAddr:
ENDC
moveq.l #0,D0
IFD LATTICE
@TryLockAddrB:
ENDC
TLA0: bset.b D0,4(A0) ; attempt to gain lock
bne .tla10 ; failure
moveq.l #1,D0
rts ; success, return 1
.tla10 moveq.l #-1,D0 ; failure, return -1
rts
_LockAddrB: movem.l 4(sp),D0/A0 ; bit: D0 lock: A0
bra LA0
_LockAddr: ; bit: 0 lock: A0
move.l 4(sp),A0
; MAIN LOCK CODE
IFD LATTICE
@LockAddr:
ENDC
moveq.l #0,D0
IFD LATTICE
@LockAddrB:
ENDC
LA0: bset.b D0,4(A0) ; attempt to gain lock
bne .la10 ; failure
rts ; success, done, rts (FAST)
.la10 movem.l A2/A6,-(sp) ; failure (SLOW) (BLOCK)
move.l _SysBase,A6 ; A6 = SYSBase
FORBID
bset.b D0,4(A0) ; try again after FORBID
beq .la20 ; got it!
; Put linked list structure on stack
move.w D0,-(sp) ; bit# 12(sp)
move.l ThisTask(A6),-(sp) ; task# 8(sp)
move.l A0,-(sp) ; &var 4(sp)
move.l (A0),-(sp) ; Next (sp)
move.l sp,(A0) ; (put at head of list)
; Loop Wait/re-attempt lock
.la15 moveq.l #$10,D0 ; wait (semaphore signal)
jsr _LVOWait(A6)
move.w 12(sp),D0 ; try for lock
move.l 4(sp),A0
bset.b D0,4(A0)
bne .la15 ; loop until get it
.la16 cmp.l (A0),sp ; unlink, find our node!
beq .la18
move.l (A0),A0
bra .la16
.la18 move.l (sp),(A0)
add.w #14,sp
.la20
PERMIT
movem.l (sp)+,A2/A6
rts
;;BREAKUP unlockaddr.asm
; TaskUnlock() works on an expanded lock (see TaskLock() above)
; while UnlockAddr[B] works on a basic lock.
xdef _TaskUnlock
_TaskUnlock: move.l 4(sp),A0
sub.w #1,6(A0) ; decrement reference count
bne .tu10 ; non-zero, do not release lock yet
moveq.l #0,D0 ; D0 = 0 (needed for ULW)
move.l D0,8(A0) ; clear the owner field
; this repeats some of the unlock code
bclr.b #0,4(A0) ; clear the lock
move.l (A0),D1 ; Anybody waiting to get the lock?
bne ULW ; yes, branch to unlock code
.tu10 rts ; no, return immediately.
xref _LVOSignal
xref _LVOForbid
xref _LVOPermit
xdef _UnlockAddr
xdef _UnlockAddrB
IFD LATTICE
xdef @UnlockAddr
xdef @UnlockAddrB
ENDC
_UnlockAddrB: movem.l 4(sp),D0/A0
bra.s UL0
_UnlockAddr: move.l 4(sp),A0
IFD LATTICE
@UnlockAddr:
ENDC
moveq.l #0,D0
IFD LATTICE
@UnlockAddrB:
ENDC
UL0: bclr.b D0,4(A0) ; clear lock bit
move.l (A0),D1 ; anybody waiting?
beq .ulrts ; no, rts
ULW:
movem.l D2/A2/A6,-(sp) ; yes, wake 'm all up
move.b D0,D2 ; D2 = bit#
move.l _SysBase,A6 ; A6 = SYSBase
FORBID
move.l (A0),D1 ; get pointer again after FORBID
beq .ul20 ; no, rts (close a window)
.ul10 move.l D1,A2 ; A2 = node
cmp.b 13(A2),D2 ; waiting on our bit #?
bne .ul18 ; no
move.l 8(A2),A1 ; yes, signal the node
moveq.l #$10,D0
jsr _LVOSignal(A6) ; signal EVERYONE waiting
.ul18 move.l (A2),D1 ; next
bne .ul10
.ul20
PERMIT
movem.l (sp)+,D2/A2/A6
.ulrts rts
; FindName2(list:D0, name:A0)
;
; Search the node list as in FindName(), but also ignore
; NULL ln_name entries, which FindName() does not do. This
; routine will also return NULL if given an uninitialized
; list header (completely zero'd). Finally, it will not
; bother to do a string compare if the two pointers are
; the same.
xdef _FindName2
_FindName2: movem.l 4(sp),D0/A0
movem.l A2/A3,-(sp)
move.l D0,A1
tst.l (A1) ; uninitialized list header
beq .fn2fail
.fn2loop move.l (A1),A1 ; get first/next node
tst.l (A1) ; end of list?
beq .fn2fail
move.l LN_NAME(A1),D0 ; name
beq .fn2loop ; NULL, skip
cmp.l D0,A0 ; pointers are the same!
beq .fn2succ ; don't bother w/cmp.
move.l D0,A2
move.l A0,A3
.fn2l2 cmpm.b (A2)+,(A3)+
bne .fn2loop
tst.b -1(A2)
bne .fn2l2
.fn2succ move.l A1,D0
movem.l (sp)+,A2/A3
rts
.fn2fail moveq.l #0,D0
movem.l (sp)+,A2/A3
rts
END