
		;   long var[2] = { 0, 0 };
		;
		;   These routines provide fast exclusive
		;   locks.
		;
		;   LockAddr(&var[0]:A0)
		;   UnlockAddr(&var[0]:A0)
		;   TryLockAddr(&var[0]:A0)

		section __MERGED,DATA

		xref	_SysBase

		section text,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"

		xref	_LVOWait
		xref	_LVOForbid
		xref	_LVOPermit
		xref	_LVOSignal

		xdef	_LockAddr
		xdef	_UnlockAddr
		xdef	_TryLockAddr

_TryLockAddr:
		move.l	4(sp),A0
		moveq.l #0,D0

		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

_LockAddr:					; bit: 0     lock: A0
		move.l	4(sp),A0
		moveq.l #0,D0

		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

_UnlockAddr:	move.l	4(sp),A0
		moveq.l #0,D0

		bclr.b	D0,4(A0)                ; clear lock bit
		move.l	(A0),D1                 ; anybody waiting?
		beq	.ulrts			; no, rts

		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


		END
