Tvùrce webu je i pro tebe! Postav tøeba web. Bez grafika. Bez kodéra. Hned.
wz

TASKLOCK.ASM

Task Lock


; =============================================================================
;
;                             Litos - Task lock
;
; =============================================================================

		CODE_SECTION	32

; ------------- Macro - initialized task lock

%macro		TLOCK	0
		LISTHEAD		; list of locked tasks
		SPINLOCK		; lock of task list
%endmacro

; ------------- Macro - initialized task lock with lockable data
; %1 = pointer to lockable data

%macro		TLOCKD	1
		TLOCK			; initialized task lock
		dd	%1		; pointer to lockable data
%endmacro

; ------------- Macro - initialized task lock with integer variable
; %1 = pointer to lockable data, %2 = reference value LOW,
; %3 = reference value HIGH, %4 = value to set LOW, %5 = value to set HIGH

%macro		TLOCKV	5
		TLOCKD	%1		; initialized task lock with data
		dd	%2, %3 		; reference value
		dd	%4, %5		; value to set
%endmacro

; ------------- Macro - initialize task lock (%1 = pointer to TASKLOCK)

%macro		TLOCK_Init 1

		LISTINIT %1		; initialize task list head
%ifdef	SMP
		LOCK2_Init (%1+TLOCK_Lock) ; initialize lock of task list
%endif

%endmacro

; ------------- Macro - initialize task lock
; %1 = pointer to TASKLOCK, EAX = 0, destroys EAX

%macro		TLOCK0_Init 1

		LISTINIT %1		; initialize task list head
%ifdef	SMP
		LOCK0_Init (%1+TLOCK_Lock) ; initialize lock of task list
%endif

%endmacro

; ------------- Macro - initialize task lock
; %1 = pointer to TASKLOCK, EAX = 1

%macro		TLOCK1_Init 1

		LISTINIT %1		; initialize task list head
%ifdef	SMP
		LOCK1_Init (%1+TLOCK_Lock) ; initialize lock of task list
%endif

%endmacro

; -----------------------------------------------------------------------------
;             Macro - task lock callback function (integer variable)
; -----------------------------------------------------------------------------
; INPUT:
;  EBX = pointer to TASKLOCK
;  EDX = pointer to data
;  %1 = operand size: 0=byte, 1=word, 2=double word, 3=quadruple word
;  %2 = operand signification: 0=signed, 1=unsigned
;  %3 = operation: 0=nothing, 1=set value, 2=increment, 3=decrement
;  %4 = test: 0=false, 1=true, 2="=", 3="!=", 4="<", 5="<=", 6=">", 7=">="
; OUTPUT:
;  AL = 0: false, 1: true (condition accomplished)
; DESTROYS: rest of EAX
; -----------------------------------------------------------------------------

; Currently not used.

%ifdef _UNUSED_

%macro		TLV_FNC 4

		CODE_SECTION	32

TLV %+ %1 %+ %2 %+ %3 %+ %4:

; ------------- Push registers

%if	((%3!=0)||(%4>1))&&(%1==3)
		push	ecx		; push ECX
%endif

; ------------- Load data (-> ECX:EAX)

%if	(%3!=0)||(%4>1)
%if	(%3!=1)
  %if	(%1==0)
		mov	al,[edx]	; AL <- data byte
  %elif	(%1==1)
		mov	ax,[edx]	; AX <- data word
  %else
		mov	eax,[edx]	; EAX <- data double word
    %if	(%1==3)
		mov	ecx,[edx+4]	; ECX <- data quadruple word HIGH
    %endif
  %endif
%else
  %if	(%1==0)
		mov	al,[ebx+TLOCK_Set] ; AL <- data byte
  %elif	(%1==1)
		mov	ax,[ebx+TLOCK_Set] ; AX <- data word
  %else
		mov	eax,[ebx+TLOCK_Set] ; EAX <- data double word
    %if	(%1==3)
		mov	ecx,[ebx+TLOCK_Set+4] ; ECX <- data qword HIGH
    %endif
  %endif
%endif  

; ------------- Operation with data

%if	(%3==2)
		inc	eax		; increment data
  %if	(%1==3)
		jnz	%%TLV1
		inc	ecx		; increment data HIGH
    %%TLV1:
  %endif
%elif	(%3==3)
		dec	eax		; decrement data
  %if	(%1==3)
		jnz	%%TLV2
		dec	ecx		; decrement data HIGH
    %%TLV2:
  %endif
%endif

; ------------- Store new data

%if	(%3!=0)
  %if	(%1==0)
		mov	[edx],al	; store data byte
  %elif	(%1==1)
		mov	[edx],ax	; store data word
  %else
		mov	[edx],eax	; store data double word
    %if	(%1==3)
		mov	[edx+4],ecx	; store data quadruple word HIGH
    %endif
  %endif
%endif

; ------------- Compare data

%if	(%4>1)
  %if	(%1==0)
		cmp	al,[ebx+TLOCK_Ref] ; compare data byte
  %elif	(%1==1)
		cmp	ax,[ebx+TLOCK_Ref] ; compare data word
  %else
    %if	(%1==3)
		cmp	ecx,[ebx+TLOCK_Ref+4] ; compare data qword HIGH
		jne	%%TLV3
    %endif
		cmp	eax,[ebx+TLOCK_Ref] ; compare data double word
      %%TLV3:
  %endif
%endif
%endif

; ------------- Condition

%if     (%4==0)
		mov	al,0		; false
%elif   (%4==1)
		mov	al,1		; true
%elif   (%4==2)
		sete	al		; =
%elif   (%4==3)
		setne	al		; !=
%else
  %if (%2 == 0)
    %if   (%4==4)
		setl	al		; < signed
    %elif (%4==5)
		setle	al		; <= signed
    %elif (%4==6)
		setg	al		; > signed
    %else
		setge	al		; >= signed
    %endif
  %else
    %if   (%4==4)
		setb	al		; < unsigned
    %elif (%4==5)
		setbe	al		; <= unsigned
    %elif (%4==6)
		seta	al		; > unsigned
    %else
		setae	al		; >= unsigned
    %endif
  %endif
%endif

; ------------- Pop registers

%if	((%3!=0)||(%4>1))&&(%1==3)
		pop	ecx		; pop ECX
%endif
		ret

		CONST_SECTION

		dd	TLV %+ %1 %+ %2 %+ %3 %+ %4
%endmacro

; -----------------------------------------------------------------------------
;                Macro - task lock callback function (bit variable)
; -----------------------------------------------------------------------------
; INPUT:
;  EBX = popinter to TASKLOCK
;  EDX = pointer to data byte
;  %1 = bit number (0 to 7)
;  %2 = operation: 0=nothing, 1=set bit, 2=reset bit, 3=complement bit
;  %3 = test: 0=false, 1=true, 2=bit was set, 3=bit was reset
; OUTPUT:
;  AL = 0: false, 1: true (condition accomplished)
; NOTES: Test is accomplished before bit operation.
; -----------------------------------------------------------------------------

%macro		TLB_FNC 3

		CODE_SECTION	32

TLB %+ %1 %+ %2 %+ %3:

; ------------- Test

%if     (%3==0)
		mov	al,0		; false
%elif   (%3==1)
		mov	al,1		; true
%else
		test	byte [edx],1<<%1 ; test bit
  %if   (%3==2)
		setnz	al		; bit is set
  %else
		setz	al		; bit is reset
  %endif
%endif

; ------------- Operation

%if	(%2==1)
		or	byte [edx],1<<%1 ; set bit
%elif	(%2==2)
		and	byte [edx],~(1<<%1) ; reset bit
%elif	(%2==3)
		xor	byte [edx],1<<%1 ; complement bit
%endif
		ret

		CONST_SECTION

		dd	TLB %+ %1 %+ %2 %+ %3
%endmacro

; -----------------------------------------------------------------------------
;                   Standard task lock callback functions
; -----------------------------------------------------------------------------

		CONST_SECTION

[list -]

; ------------- Integer variable

		align	4, db 0
TLCallbackVar:

%assign TL_ARG4 0			; argument 4 - condition
%rep 8
  %assign TL_ARG3 0			; argument 3 - operation
  %rep 4
    %assign TL_ARG2 0			; argument 2 - signification
    %rep 2
      %assign TL_ARG1 0			; argument 1 - operand size
      %rep 4
		TLV_FNC TL_ARG1, TL_ARG2, TL_ARG3, TL_ARG4
        %assign TL_ARG1 TL_ARG1+1
      %endrep
      %assign TL_ARG2 TL_ARG2+1
    %endrep
    %assign TL_ARG3 TL_ARG3+1
  %endrep
  %assign TL_ARG4 TL_ARG4+1
%endrep

; ------------- Bit variable

		align	4, db 0
TLCallbackBit:

%assign TL_ARG3 0			; argument 3 - test
%rep 4
  %assign TL_ARG2 0			; argument 2 - operation
  %rep 4
    %assign TL_ARG1 0			; argument 1 - bit number
    %rep 8
		TLB_FNC TL_ARG1, TL_ARG2, TL_ARG3
      %assign TL_ARG1 TL_ARG1+1
    %endrep
    %assign TL_ARG2 TL_ARG2+1
  %endrep
  %assign TL_ARG3 TL_ARG3+1
%endrep

		CODE_SECTION	32
[list +]

%endif   ; _UNUSED_

; -----------------------------------------------------------------------------
;                                Initialize task lock
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock TASKLOCK
; -----------------------------------------------------------------------------

TaskLockInit:	TLOCK_Init ebx		; initialize task lock
		ret

; -----------------------------------------------------------------------------
;                   Initialize task lock with lockable data
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock TASKLOCKD
;		EDX = pointer to lockable data
; -----------------------------------------------------------------------------

TaskLockDInit:	call	TaskLockInit	; initialize task lock
		mov	[ebx+TLOCK_Data],edx ; store pointer to data
		ret

; -----------------------------------------------------------------------------
;     Initialize task lock with integer variable (byte, word or double word)
; -----------------------------------------------------------------------------
; INPUT:	EAX = reference value to compare
;		EBX = task lock TASKLOCKV
;		ECX = value to set
;		EDX = pointer to lockable data
; -----------------------------------------------------------------------------

TaskLockIntInit:call	TaskLockDInit	; initialize task lock with data
		mov	[ebx+TLOCK_Ref],eax ; store reference value
		and	dword [ebx+TLOCK_Ref+4],byte 0 ; ref. value HIGH
		mov	[ebx+TLOCK_Set],ecx ; store value to set
		and	dword [ebx+TLOCK_Set+4],byte 0 ; value to set HIGH
		ret

; -----------------------------------------------------------------------------
;         Initialize task lock with quadruple word integer variable
; -----------------------------------------------------------------------------
; INPUT:	ESI:EAX = reference value to compare
;		EBX = task lock TASKLOCKV
;		EDI:ECX = value to set
;		EDX = pointer to lockable data
; -----------------------------------------------------------------------------

TaskLockQWInit:	call	TaskLockDInit	; initialize task lock with data
		mov	[ebx+TLOCK_Ref],eax ; store reference value LOW
		mov	[ebx+TLOCK_Ref+4],esi ; clear ref. value HIGH
		mov	[ebx+TLOCK_Set],ecx ; store value to set
		mov	[ebx+TLOCK_Set+4],edi ; store value to set HIGH
		ret

; -----------------------------------------------------------------------------
;                                Task lock sleep
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock TASKLOCK
; NOTES:	It waits infinitely for an event. If event has not came after
;		returning, TaskSleep can be called again.
; -----------------------------------------------------------------------------

; ------------- Push registers

TaskSleep:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
%ifdef	SMP
		push	esi		; push ESI
%endif
; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		lea	esi,[ebx+TLOCK_Lock] ; EDX <- lock of task list
		call	SpinLockESI	; lock task list
%endif
; ------------- Prepare task list entry (-> ECX)

		CURRENT	ecx		; ECX <- current task
		add	ecx,TASK_TaskList ; ECX <- task list entry

; ------------- Add this task to task list

		mov	eax,ecx		; EAX <- task list entry
		mov	[ecx-TASK_TaskList+TASK_TaskLock],ebx ; store task lock
		call	ListLast	; add task to end of list

; ------------- Prepare to fall asleep task

		xor	edx,edx		; EDX <- 0
		dec	edx		; EDX <- -1 (infinitely sleep time)
		call	PrepSleepTask	; prepare to fall asleep task

; ------------- Unlock task list
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Call scheduler (and switch to another task)

		call	Schedule	; call scheduler

; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		call	SpinLockESI	; lock task list
%endif
; ------------- Remove task from task list

		xchg	eax,ecx		; EAX <- task list entry
		call	ListDel		; remove task from task list
		inc	edx		; EDX <- 0
		mov	[eax-TASK_TaskList+TASK_TaskLock],edx ; clear task lock

; ------------- Unlock task list
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                          Task lock sleep with time-out
; -----------------------------------------------------------------------------
; INPUT:	EAX = wait period (in [ms], negative=infinitely)
;		EBX = task lock TASKLOCK
; OUTPUT:	CY = time-out
; NOTES:	It waits for a given time for an event. If event has not came
;		after returning, TaskCont should be called.
; -----------------------------------------------------------------------------

; ------------- Push registers (it must be the same as in TaskContTime)

TaskSleepTime:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
%ifdef	SMP
		push	esi		; push ESI
%endif
; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		lea	esi,[ebx+TLOCK_Lock] ; EDX <- lock of task list
		call	SpinLockESI	; lock task list
%endif
; ------------- Prepare to fall asleep task

		xchg	eax,edx		; EDX <- wait time
		or	edx,edx		; negative time (infinitely)?
		js	TaskSleepTime2	; negative time (infinitely)
		mov	eax,TIME_1MS	; EAX <- time 1 ms
		mul	edx		; recalc time to 100-ns
TaskSleepTime2:	call	PrepSleepTask	; prepare to fall asleep task

; ------------- Prepare task list entry (-> ECX) (TaskCont jumps here)

TaskSleepTime4:	CURRENT	ecx		; ECX <- current task
		add	ecx,TASK_TaskList ; ECX <- task list entry

; ------------- Add this task to task list

		mov	eax,ecx		; EAX <- task list entry
		mov	[ecx-TASK_TaskList+TASK_TaskLock],ebx ; store task lock
		call	ListLast	; add task to end of list

; ------------- Unlock task list
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Call scheduler (and switch to another task)

		call	Schedule	; call scheduler

; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		call	SpinLockESI	; lock task list
%endif
; ------------- Remove task from task list

		xchg	eax,ecx		; EAX <- task list entry
		call	ListDel		; remove task from task list
		xor	edx,edx		; EDX <- 0
		mov	[eax-TASK_TaskList+TASK_TaskLock],edx ; clear task lock

; ------------- Check if time expired

		cmp	edx,[eax-TASK_TaskList+TASK_Alarm+ALARM_Expire] ; LOW
		jne	TaskSleepTime8	; time didn't expire
		cmp	edx,[eax-TASK_TaskList+TASK_Alarm+ALARM_Expire+4]; HIGH
		je	TaskSleepTime9	; sleep time expired

; ------------- OK: Unlock task list

TaskSleepTime8:
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		clc			; clear error flag
		ret

; ------------- ERROR: Unlock task list

TaskSleepTime9:
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		stc			; set error flag
		ret

; -----------------------------------------------------------------------------
;                   Continue task lock sleep with time-out
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock TASKLOCK
; OUTPUT:	CY = time-out
; NOTES:	It should be called after TaskSleepTime if event has not came.
; -----------------------------------------------------------------------------

; ------------- Push registers (it must be the same as in TaskSleepTime)

TaskCont:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
%ifdef	SMP
		push	esi		; push ESI
%endif
; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		lea	esi,[ebx+TLOCK_Lock] ; EDX <- lock of task list
		call	SpinLockESI	; lock task list
%endif
; ------------- Prepare to continue task sleep

		call	PrepSleepCont	; prepare to continue task sleep
		jmp	short TaskSleepTime4

; -----------------------------------------------------------------------------
;                      Task lock sleep with callback function
; -----------------------------------------------------------------------------
; INPUT:	EAX = wait period (in [ms], 0=no wait, negative=infinitely)
;		EBX = task lock TASKLOCK
;		ECX = callback function
;			INPUT:	EBX = task lock TASKLOCK
;				EDX = callback function data (pointer to data)
;			OUTPUT:	AL = 0: go sleep (and repeat test)
;				AL <> 0: continue, returns NC
;		EDX = callback function data (e.g. pointer to data)
; OUTPUT:	CY = time-out, NC = condition OK
; -----------------------------------------------------------------------------

; ------------- Push registers

TaskSleepFnc:	push	eax		; push EAX
%ifdef	SMP
		push	esi		; push ESI
%endif
		push	edi		; push EDI
		
; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		lea	esi,[ebx+TLOCK_Lock] ; EDX <- lock of task list
		call	SpinLockESI	; lock task list
%endif
; ------------- Test lock condition

		push	eax		; push EAX
		call	ecx		; callback function
		or	al,al		; continue?
		pop	eax		; pop EAX
		jnz	TaskSleepFnc8	; continue with condition OK

; ------------- Check if wait for lock condition

		or	eax,eax		; wait for lock condition?
		jz	TaskSleepFnc9	; don't wait for lock condition

; ------------- Prepare to fall asleep task

		push	edx		; push EDX
		xchg	eax,edx		; EDX <- wait time
		or	edx,edx		; negative time (infinitely)?
		js	TaskSleepFnc2	; negative time (infinitely)
		mov	eax,TIME_1MS	; EAX <- time 1 ms
		mul	edx		; recalc time to 100-ns
TaskSleepFnc2:	call	PrepSleepTask	; prepare to fall asleep task
		pop	edx		; pop EDX

; ------------- Prepare task list entry (-> EDI)

TaskSleepFnc4:	CURRENT	edi		; EDI <- current task
		add	edi,TASK_TaskList ; EDI <- task list entry

; ------------- Add this task to task list

		mov	eax,edi		; EAX <- task list entry
		mov	[eax-TASK_TaskList+TASK_TaskLock],ebx ; store task lock
		call	ListLast	; add task to end of list

; ------------- Unlock task list
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Call scheduler (and switch to another task)

		call	Schedule	; call scheduler

; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		call	SpinLockESI	; lock task list
%endif
; ------------- Remove task from task list

		xchg	eax,edi		; EAX <- task list entry
		call	ListDel		; remove task from task list
		xor	edi,edi		; EDI <- 0
		mov	[eax-TASK_TaskList+TASK_TaskLock],edi ; clear task lock

; ------------- Test lock condition

		push	eax		; push EAX
		call	ecx		; callback function
		or	al,al		; continue with condition OK?
		pop	eax		; pop EAX
		jnz	TaskSleepFnc8	; condition OK

; ------------- Check if time expired

		cmp	edi,[eax-TASK_TaskList+TASK_Alarm+ALARM_Expire] ; LOW
		jne	TaskSleepFnc6	; time didn't expire
		cmp	edi,[eax-TASK_TaskList+TASK_Alarm+ALARM_Expire+4]; HIGH
		je	TaskSleepFnc9	; sleep time expired

; ------------- Prepare to continue task sleep

TaskSleepFnc6:	call	PrepSleepCont	; prepare to continue task sleep
		jmp	short TaskSleepFnc4 ; continue sleep

; ------------- OK: Unlock task list

TaskSleepFnc8:
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers

		pop	edi		; pop EDI
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	eax		; pop EAX
		clc			; clear error flag
		ret

; ------------- ERROR: Unlock task list

TaskSleepFnc9:
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers

		pop	edi		; pop EDI
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	eax		; pop EAX
		stc			; set error flag
		ret

; -----------------------------------------------------------------------------
;                     Task lock sleep with integer variable
; -----------------------------------------------------------------------------
; INPUT:	EAX = wait period (in [ms], 0=no wait, negative=infinitely)
;		EBX = task lock with integer variable TASKLOCKV
;		CL = callback function flags for integer variable
;			(TLOCK_BYTE,... TLOCK_GE)
; OUTPUT:	CY = time-out, NC = condition OK
; -----------------------------------------------------------------------------

; Currently not used.

%ifdef _UNUSED_

; ------------- Push registers

TaskLockInt:	push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Call task lock sleep

		movzx	ecx,cl		; ECX <- flags
		mov	ecx,[TLCallbackVar+ecx*4] ; ECX <- callback function
		mov	edx,[ebx+TLOCK_Data] ; EDX <- pointer to data
		call	TaskSleepFnc	; call task lock sleep

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		ret

; -----------------------------------------------------------------------------
;                     Task lock sleep with bit variable
; -----------------------------------------------------------------------------
; INPUT:	EAX = wait period (in [ms], 0=no wait, negative=infinitely)
;		EBX = task lock with lockable data TASKLOCKD
;		CL = callback function flags for bit variable
;			(TLOCK_BIT0,... TLOCK_BITWASRES)
; OUTPUT:	CY = time-out, NC = condition OK
; -----------------------------------------------------------------------------

; ------------- Push registers

TaskLockBit:	push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Call task lock sleep

		and	ecx,7fh		; ECX <- flags
		mov	ecx,[TLCallbackBit+ecx*4] ; ECX <- callback function
		mov	edx,[ebx+TLOCK_Data] ; EDX <- pointer to data
		call	TaskSleepFnc	; call task lock sleep

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		ret


%endif   ; _UNUSED_

; -----------------------------------------------------------------------------
;                             Task lock wake-up
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock TASKLOCK
; -----------------------------------------------------------------------------

; ------------- Push registers

TaskWakeUp:	push	eax		; push EAX
		push	ebx		; push EBX
%ifdef	SMP
		push	esi		; push ESI
%endif
; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		lea	esi,[ebx+TLOCK_Lock] ; EDX <- lock of task list
		call	SpinLockESI	; lock task list
%endif
; ------------- Get next task (-> EBX)

		mov	eax,[ebx+LIST_Next] ; EAX <- next task
		cmp	eax,ebx		; is task list empty?
		je	TaskWakeUp8	; no other task in the list
		sub	eax,TASK_TaskList ; EAX <- task
		xchg	eax,ebx		; EBX <- task

; ------------- Clear fall asleep state

		cmp	byte [ebx+TASK_State],TASK_FALLASLEEP ; fall asleep?
		jne	TaskWakeUp4	; task is not going to fall asleep
		mov	byte [ebx+TASK_State],TASK_RUNNING ; mark as running
		jmp	short TaskWakeUp8

; ------------- Wake-up next task

TaskWakeUp4:	call	WakeUpTask	; wake-up task

; ------------- Unlock task list

TaskWakeUp8:
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                   Task lock wake-up with callback function
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock TASKLOCK
;		ECX = callback function
;			INPUT:	EBX = task lock TASKLOCK
;				EDX = callback function data (pointer to data)
;			OUTPUT:	AL = 0: returns CY
;				AL <> 0: wake-up next task, returns NC
;		EDX = callback function data (e.g. pointer to data)
; OUTPUT:	CY = condition not accomplished, NC = condition OK
; NOTES:	Next task waked-up if condition accomplished.
; -----------------------------------------------------------------------------

; ------------- Push registers

TaskWakeUpFnc:	push	eax		; push EAX
		push	ebx		; push EBX
%ifdef	SMP
		push	esi		; push ESI
%endif
; ------------- Disable interrupts

		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock task list
%ifdef	SMP
		lea	esi,[ebx+TLOCK_Lock] ; EDX <- lock of task list
		call	SpinLockESI	; lock task list
%endif
; ------------- Call callback function

		call	ecx		; callback function
		or	al,al		; continue?
		jz	TaskWakeUpFnc9	; condition not accomplished

; ------------- Get next task (-> EBX)

		mov	eax,[ebx+LIST_Next] ; EAX <- first task
		cmp	eax,ebx		; is task list empty?
		je	TaskWakeUpFnc8	; no task in the list
		sub	eax,TASK_TaskList ; EAX <- task
		xchg	eax,ebx		; EBX <- task

; ------------- Clear fall asleep state

		cmp	byte [ebx+TASK_State],TASK_FALLASLEEP ; fall asleep?
		jne	TaskWakeUpFnc6 ; task is not going to fall asleep
		mov	byte [ebx+TASK_State],TASK_RUNNING ; mark as running
		jmp	short TaskWakeUpFnc8

; ------------- Wake-up next task

TaskWakeUpFnc6:	call	WakeUpTask	; wake-up task

; ------------- OK: Unlock task list

TaskWakeUpFnc8:
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		clc			; clear error flag
		ret

; ------------- ERROR: Unlock task list

TaskWakeUpFnc9:
%ifdef	SMP
		LOCK_Unlock esi		; unlock task list
%endif
; ------------- Enable interrupts

		popf			; pop flags

; ------------- Pop registers
%ifdef	SMP
		pop	esi		; pop ESI
%endif
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		stc			; set error flag
		ret

; -----------------------------------------------------------------------------
;                    Task lock wake-up with integer variable
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock with integer variable TASKLOCKV
;		CL = callback function flags for integer variable
;			(TLOCK_BYTE,... TLOCK_GE)
; OUTPUT:	CY = condition not accomplished, NC = condition OK
; NOTES:	Next task waked-up if condition accomplished.
; -----------------------------------------------------------------------------

; Currently not used.

%ifdef _UNUSED_

; ------------- Push registers

TaskUnlockInt:	push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Call task lock sleep

		movzx	ecx,cl		; ECX <- flags
		mov	ecx,[TLCallbackVar+ecx*4] ; ECX <- callback function
		mov	edx,[ebx+TLOCK_Data] ; EDX <- pointer to data
		call	TaskWakeUpFnc	; call task lock wake-up

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		ret

; -----------------------------------------------------------------------------
;                    Task lock wake-up with bit variable
; -----------------------------------------------------------------------------
; INPUT:	EBX = task lock with lockable data TASKLOCKD
;		CL = callback function flags for bit variable
;			(TLOCK_BIT0,... TLOCK_BITWASRES)
; OUTPUT:	CY = condition not accomplished, NC = condition OK
; NOTES:	Next task waked-up if condition accomplished.
; -----------------------------------------------------------------------------

; ------------- Push registers

TaskUnlockBit:	push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Call task lock sleep

		and	ecx,7fh		; ECX <- flags
		mov	ecx,[TLCallbackBit+ecx*4] ; ECX <- callback function
		mov	edx,[ebx+TLOCK_Data] ; EDX <- pointer to data
		call	TaskWakeUpFnc	; call task lock wake-up

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		ret

%endif  ; _UNUSED_

Back to source browser