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

SIGNAL.ASM

Signals


; =============================================================================
;
;                                Litos - Signals
;
; =============================================================================
; TODO: Verify destination task. Verify access rights (user).
; TODO: Signal handler

		CODE_SECTION	32

		GET eax,1234h,5678h	; only test, delete it later

; -----------------------------------------------------------------------------
;                       Set signal context in user stack
; -----------------------------------------------------------------------------
; INPUT:
; -----------------------------------------------------------------------------

SignalSetCont:	; !!!!!!! TODO
		ret


; -----------------------------------------------------------------------------
;                              Service signal
; -----------------------------------------------------------------------------
; OUTPUT:	CY = task killed
; -----------------------------------------------------------------------------

; TODO: Wake-up sleeping tasks is any signal is pending.

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

DoSignal:	pusha			; push all registers
		mov	ebp,esp		; EBP <- push stack pointer

; ------------- Prepare local SIGINFO buffer for signal (-> ECX)

		sub	esp,byte SIGINFO_size ; create SIGINFO buffer
		mov	ecx,esp		; ECX <- SIGINFO buffer

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

		CURRENT	ebx		; EBX <- get current task

; ------------- Get next signal (into ECX buffer)

DoSignal2:	call	SignalNext	; get next signal
		jc	near DoSignal8	; no next signal

; ------------- Get and lock signal action table (-> EDX)

		mov	edx,[ebx+TASK_SigAction] ; EDX <- signal action table
%ifdef	SMP
		call	SpinLockEDX	; lock signal action table
%endif
; ------------- Get signal action (-> ESI) and handler (-> EDI)

		movzx	eax,byte [ecx+SI_Signal] ; EAX <- signal number
		shl	eax,1		; EAX <- signal number * 2
		lea	esi,[edx+eax*(SIGACT_size/2)] ; ESI <- action table
		mov	edi,[esi+SA_Handler] ; EDI <- handler

; ------------- Use parent's signal

           	cmp	edi,byte SA_PAR	; use parent's signal?
		jne	DoSignal28

		push	ebx		; push EBX
		push	edx		; push EDX

DoSignal22:	add	edi,byte SA_IGN-SA_PAR ; EDI <- ignore signal
		mov	ebx,[ebx+TASK_Link+TREE_Parent] ; EBX <- parent
		or	ebx,ebx		; valid parent?
		jz	DoSignal24	; parent is not valid

		mov	edx,[ebx+TASK_SigAction] ; EDX <- signal action table
		lea	edx,[edx+eax*(SIGACT_size/2)] ; EDX <- action table
		mov	edi,[edx+SA_Handler] ; EDI <- handler
		cmp	edi,byte SA_PAR	; use parent's signal?
		je	DoSignal22	; use parent's signal

DoSignal24:	pop	edx		; pop EDX
		pop	ebx		; pop EBX

; ------------- 0: SA_DEF, Default action

DoSignal28:	or	edi,edi		; default action?
		jnz	DoSignal3	; no default action
		or	edi,byte SA_TERM ; EDI <- terminate
		cmp	al,32		; real-time signal?
		jae	DoSignal3	; real-time signal
		movzx	edi,byte [SignalDefAct+eax] ; EDI <- default action

; ------------- 1: SA_IGN, Ignore signal

DoSignal3:	dec	edi		; signal action - 1
		jnz	DoSignal32	; don't ignore signal
DoSignal31:
%ifdef	SMP
		LOCK_Unlock edx		; unlock signal action table
%endif
		jmp	short DoSignal2	; get next signal

; ------------- 2: SA_TERM, Terminate the process

DoSignal32:	dec	edi		; terminate the process?
		jnz	DoSignal34	; don't terminate the process
DoSignal33:
%ifdef	SMP
		LOCK_Unlock edx		; unlock signal action table
%endif
		call	TaskKill	; kill the task
		stc			; error flag - task killed
		jmp	short DoSignal9

; ------------- 3: SA_DUMP, Terminate and dump

DoSignal34:	dec	edi		; terminate and dump?
		jnz	DoSignal36	; don't terminate and dump

		; !!!!!!! TODO

		jmp	short DoSignal33

; ------------- 4: SA_STOP, Stop the task 

DoSignal36:	dec	edi		; stop the task
		jnz	DoSignal4	; dont stop the task
%ifdef	SMP
		LOCK_Unlock edx		; unlock signal action table
%endif
		call	TaskStop	; stop task
		jmp	DoSignal2	; get next signal

; ------------- User handler

DoSignal4:	add	edi,byte 4	; EDI <- handler

		; !!!!!!! TODO

%ifdef	SMP
		LOCK_Unlock edx		; unlock signal action table
%endif
		jmp	DoSignal2	; get next signal

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

DoSignal8:	clc
DoSignal9:	mov	esp,ebp		; ESP <- pop stack pointer
		popa			; pop all registers
		ret

; -----------------------------------------------------------------------------
;                            Test if ignore signal
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number
;		EDX = destination task
; OUTPUT:	CY = ignore signal
; NOTES:	Blocked or traced signals are not ignored.
; -----------------------------------------------------------------------------

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

SignalTestIgn:	push	eax		; push EAX
		push	ebx		; push EBX

; ------------- Check signal number

		cmp	al,SIGNULL	; unused signal
		je	SignalTestIgn7	; signal is always ignored
		cmp	al,63		; maximal signal number
		ja	SignalTestIgn7	; ignore invalid signal number

; ------------- Check if task is traced (signal cannot be ignored)

		test	byte [edx+TASK_Trace],PTRACED ; is task traced?
		jnz	SignalTestIgn8	; signal cannot be ignored if traced

; ------------- Blocked signals are not ignored (signal handler may change)

		movzx	eax,al		; EAX <- signal number
		bt	[edx+TASK_SigMask],eax ; test signal mask (CY=enabled)
		jnc	SignalTestIgn8	; signal is blocked, don't ignore it

; ------------- Pointer to signal action (-> EBX)

		shl	eax,1		; EAX <- signal number * 2
		mov	ebx,[edx+TASK_SigAction] ; EBX <- action table
		lea	ebx,[ebx+eax*(SIGACT_size/2)] ; EBX <- action table

; ------------- Ignore signal (= 1, SIG_IGN)

		mov	ebx,[ebx+SA_Handler] ; get signal handler
		dec	ebx		; ignore signal (=1) ?
		jz	SignalTestIgn7	; ignore signal

; ------------- Default handler (= 0, SIG_DFL)

		inc	ebx		; default handler?
		clc			; flag "don't ignore"
		jnz	SignalTestIgn8	; no default handler, not ignored

; ------------- Check if default ignore signal

		cmp	al,SIGCHLD*2	; child notify?
		je	SignalTestIgn7	; ignore child notify
		cmp	al,SIGWINCH*2	; change windows size?
		je	SignalTestIgn7	; ignore change window size
		cmp	al,SIGURG*2	; urgent condition on socket?
		clc			; preset flag - don't ignore
		jne	SignalTestIgn8	; another signal, don't ignore it
SignalTestIgn7:	stc			; CY <- set flag "ignore signal"

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

SignalTestIgn8:	pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;               Flush STOP pending signals for destination task
; -----------------------------------------------------------------------------
; INPUT:	EDX = destination task
; NOTES:	Signal queue must be locked and interrupts disabled.
;		Stop signals are: SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU.
; -----------------------------------------------------------------------------

%define STOP_MASK ( (1<<SIGSTOP) | (1<<SIGTSTP) | (1<<SIGTTIN) | (1<<SIGTTOU) )

; ------------- Check if any STOP is pending

SigFlushStop:	test	dword [edx+TASK_Signal],STOP_MASK
		jz	SigFlushStop9	; no pending signal

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

		push	eax		; push EAX
		push	ebx		; push EBX
		push	ecx		; push ECX

; ------------- Find STOP signals

		lea	ebx,[edx+TASK_SigQueue] ; EBX <- head
		mov	ecx,ebx		; ECX <- queue head
SigFlushStop2:	mov	ebx,[ebx+LIST_Next] ; EBX <- next item
SigFlushStop4:	cmp	ebx,ecx		; end of queue?
		je	SigFlushStop8	; end of queue

; ------------- Check signal

		movzx	eax,byte [ebx+SIGNAL_Info+SI_Signal] ; signal number
		cmp	al,SIGSTOP	; SIGSTOP signal?
		je	SigFlushStop6	; yes, SIGSTOP
		cmp	al,SIGTSTP	; SIGTSTP signal?
		je	SigFlushStop6	; yes, SIGTSTP
		cmp	al,SIGTTIN	; SIGTTIN signal?
		je	SigFlushStop6	; yes, SIGTTIN
		cmp	al,SIGTTOU	; SIGTTOU signal?
		jne	SigFlushStop2	; no

; ------------- Decrease number of signals and reset signal flag

SigFlushStop6:	dec	dword [ecx+TASK_SigNum-TASK_SigQueue]; decrease signals
		btr	[ecx+TASK_Signal-TASK_SigQueue],eax ; reset flag

; ------------- Free old entry from the queue

		xchg	eax,ebx		; EAX <- signal item
		mov	ebx,[eax+LIST_Next] ; EBX <- next item
		call	ListDel		; free signal list entry
		call	SysMemFree	; free memory block
		jmp	short SigFlushStop4

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

SigFlushStop8:	pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
SigFlushStop9:	ret

; -----------------------------------------------------------------------------
;                       Send signal info to a task
; -----------------------------------------------------------------------------
; INPUT:	ECX = filled SIGINFO structure (its content will be copied)
;		EDX = destination task (must be valid)
; OUTPUT:	CY = error, signal cannot be sent (queue full or memory error)
; LOCKS:	TASK_SigLock, SysMemLock
; NOTES:	Regular signals (0 to 31) are not limited to queue size.
;		Sender entry will be filled with current running task.
; -----------------------------------------------------------------------------

; TODO: Wake-up sleeping tasks is any signal is pending.


; ------------- Ignore signal (-> EAX = signal number)

SignalSendInfo:	push	eax		; push EAX
		movzx	eax,byte [ecx+SI_Signal] ; EAX <- signal number
		call	SignalTestIgn	; test if ignore signal
		jnc	SignalSendInfo1	; signal not ignored
		pop	eax		; pop EAX
		clc			; clear error flag
		ret

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

SignalSendInfo1:push	ebx		; push EBX
		push	edx		; push EDX
		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock signal queue (-> EDX = signal queue lock)

		add	edx,TASK_SigLock ; EDX <- signal queue lock
%ifdef	SMP
		LOCK_Lock edx 		; lock signal queue
%endif
; ------------- For SIGCONT flush pending STOP signals

		cmp	al,SIGCONT	; SIGCONT signal?
		jne	SignalSendInf14	; no
		sub	edx,TASK_SigLock ; EDX <- task
		call	SigFlushStop	; flush STOP signals

; ------------- Unlock signal queue list

		mov	ebx,edx		; EBX <- task
		add	edx,TASK_SigLock ; EDX <- signal queue lock
%ifdef	SMP
		LOCK_Unlock edx		; unlock queue
%endif
; ------------- Service SIGCONT signal

		call	TaskContinue	; continue the task
		jmp	SignalSendInf74

; ------------- Check if it is regular signal

SignalSendInf14:cmp	al,32		; is it regular signal?
		jae	SignalSendInfo3	; no, it is real-time signal

; ------------- Check if signal is already in the queue list

		bt	[edx+TASK_Signal-TASK_SigLock],eax ; signal in queue?
		jnc	SignalSendInfo5	; signal is not in the queue

; ------------- Find this signal in the signal queue list

		lea	ebx,[edx+TASK_SigQueue-TASK_SigLock] ; EBX<-queue list
SignalSendInfo2:mov	ebx,[ebx+LIST_Next] ; EBX <- next item
		cmp	[ebx+SIGNAL_Info+SI_Signal],al ; signal found?
		jne	SignalSendInfo2	; no, try next item

; ------------- Free signal list entry from the queue

		call	ListDelEBX	; free signal list entry
		dec	dword [edx+TASK_SigNum-TASK_SigLock]; decrease entries
		jmp	short SignalSendInfo6 ; fill list entry

; ------------- Check number of signals (only for real-time signals)

SignalSendInfo3:cmp	byte [edx+TASK_SigRTNum-TASK_SigLock+eax-32],255; full?
		je	SignalSendInfo4	; signal queue is full
		mov	ebx,[edx+TASK_SigNum-TASK_SigLock] ; EBX <- signals
		cmp	ebx,[edx+TASK_SigMax-TASK_SigLock] ; max. signals?
		jb	SignalSendInfo5	; signal queue is not full

; ------------- Unlock signal queue list on ERROR (-> CY)

SignalSendInfo4:
%ifdef	SMP
		LOCK_Unlock edx		; unlock signal queue
%endif

; ------------- Set error flag

		popf			; pop flags
		stc			; set CF = error
		jmp	short SignalSendInfo9

; ------------- Create new signal queue item (-> EBX)

SignalSendInfo5:mov	ebx,eax		; EBX <- push EAX (signal number)
		mov	al,SIGNAL_size	; EAX <- size of signal queue item
		call	SysMemAlloc	; get signal queue item
		xchg	eax,ebx		; pop EAX, EBX <- signal queue item
		jnc	SignalSendInfo6	; item created OK

; ------------- For SIGKILL take reserved item (-> EBX)

		cmp	al,SIGKILL	; is it SIGKILL?
		jne	SignalSendInfo4	; error
		xor 	ebx,ebx		; EBX <- 0
		xchg	ebx,[edx+TASK_SigRes-TASK_SigLock] ; reserved item
		or	ebx,ebx		; is item valid?
		jz	SignalSendInfo4	; error

; ------------- Copy signal info (into entry in EBX)

SignalSendInfo6:push	eax		; push EAX (signal number)
		mov	eax,[ecx+SI_Signal] 		; byte parameters
		mov	[ebx+SIGNAL_Info+SI_Signal],eax
		CURRENT	eax		; EAX <- get current task
		mov	[ebx+SIGNAL_Info+SI_Sender],eax
		mov	eax,[ecx+SI_Param1] 		; parameter 1
	        mov	[ebx+SIGNAL_Info+SI_Param1],eax
		mov	eax,[ecx+SI_Param2] 		; parameter 2
	        mov	[ebx+SIGNAL_Info+SI_Param2],eax
		mov	eax,[ecx+SI_Param3] 		; parameter 3
	        mov	[ebx+SIGNAL_Info+SI_Param3],eax
		mov	eax,[ecx+SI_Param4] 		; parameter 4
	        mov	[ebx+SIGNAL_Info+SI_Param4],eax

; ------------- Add new entry into signal queue list

		xchg	eax,ebx		; EAX <- signal queue item
		lea	ebx,[edx+TASK_SigQueue-TASK_SigLock]; signal queue list
		call	ListLast	; add item at end of list
		pop	eax		; pop EAX (signal number)

; ------------- Set signal flag and count signal number

		bts	[edx+TASK_Signal-TASK_SigLock],eax ; set signal flag
		inc	dword [edx+TASK_SigNum-TASK_SigLock] ; increase entries
		cmp	al,32		; is it regular signal?
		jb	SignalSendInfo7	; it is regular signal
		inc	byte [edx+TASK_SigRTNum-TASK_SigLock+eax-32]

; ------------- Unlock signal queue list on OK (-> NC)

SignalSendInfo7:
%ifdef	SMP
		LOCK_Unlock edx		; unlock queue
%endif
; ------------- Reschedule task if signal is not blocked

		bt	[edx+TASK_SigMask-TASK_SigLock],eax ; signal blocked?
		jnc	SignalSendInfo8	; signal is blocked
SignalSendInf74:mov	ebx,[edx+TASK_RunQueue-TASK_SigLock] ; run-queue
		RESCHEDULE ebx		; reschedule request

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

SignalSendInfo8:popf			; pop flags
		clc			; clear CF = operation OK
SignalSendInfo9:pop	edx		; pop EDX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                        Send signal to a task
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
;		EDX = destination task (must be valid)
; OUTPUT:	CY = error, signal cannot be sent (queue full or memory error)
; -----------------------------------------------------------------------------

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

SignalSend:	push	eax		; push EAX
		push	ecx		; push ECX
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- push stack pointer

; ------------- Create signal info structure

		sub	esp,byte SIGINFO_size; create buffer (must be aligned!)
		mov	ecx,esp		; ECX <- info structure

; ------------- Fill up signal info structure

		movzx	eax,al		; EAX <- signal number
		mov	[ecx+SI_SignalDW],eax ; byte parameters
		xor	eax,eax		; EAX <- 0
		mov	[ecx+SI_Param1],eax ; parameter 1
		mov	[ecx+SI_Param2],eax ; parameter 2
		mov	[ecx+SI_Param3],eax ; parameter 3
		mov	[ecx+SI_Param4],eax ; parameter 4

; ------------- Send signal info

		call	SignalSendInfo	; send signal info

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

		mov	esp,ebp		; ESP <- pop stack pointer
		pop	ebp		; pop EBP
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;          Check if signal is pending in the signal queue (from user)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63, except SIGKILL, SIGCONT, SIGSTOP)
; OUTPUT:	CY = required signal is not pending
; NOTES:	Signal may be pending even if it is blocked.
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalCheckU:	cmp	al,SIGKILL	; SIGKILL signal?
		je	SignalCheck2	; forbidden signal
		cmp	al,SIGCONT	; SIGCONT signal?
		je	SignalCheck2	; forbidden signal
		cmp	al,SIGSTOP	; SIGSTOP signal?
		je	SignalCheck2	; forbidden signal

; SignalCheck must follow

; -----------------------------------------------------------------------------
;          Check if signal is pending in the signal queue (from kernel)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
; OUTPUT:	CY = required signal is not pending
; NOTES:	Signal may be pending even if it is blocked.
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalCheck:	cmp	al,64		; check signal number
SignalCheck2:	cmc
		jc	SignalCheck9	; invalid signal

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

		push	eax		; push EAX
		push	ebx		; push EBX

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

		CURRENT	ebx		; EBX <- get current task

; ------------- Check if signal is pending

		movzx	eax,al		; EAX <- signal number
		bt	[ebx+TASK_Signal],eax ; is signal pending?
		cmc			; CY = signal is not pending

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

		pop	ebx		; pop EBX
		pop	eax		; pop EAX
SignalCheck9:	ret

; -----------------------------------------------------------------------------
;              Get signal info from the signal queue (from user)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63, except SIGKILL, SIGCONT, SIGSTOP)
; 		ECX = SIGINFO structure (it will be filled out with new data)
; OUTPUT:	CY = required signal is not pending, structure will not change
;		NC = signal removed from the signal queue and structure filled
; NOTES:	Signal may be taken even if it is blocked.
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalGetInfoU:	cmp	al,SIGKILL	; SIGKILL signal?
		je	SignalGetInfo1	; forbidden signal
		cmp	al,SIGCONT	; SIGCONT signal?
		je	SignalGetInfo1	; forbidden signal
		cmp	al,SIGSTOP	; SIGSTOP signal?
		je	SignalGetInfo1	; forbidden signal

; SignalGetInfo must follow

; -----------------------------------------------------------------------------
;              Get signal info from the signal queue (from kernel)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
; 		ECX = SIGINFO structure (it will be filled with new data)
; OUTPUT:	CY = required signal is not pending, structure will not change
;		NC = signal removed from the signal queue and structure filled
; NOTES:	Signal may be taken even if it is blocked.
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalGetInfo:	cmp	al,64		; check signal number
SignalGetInfo1:	cmc			; complement error flag
		jc	near SignalGetInfo9 ; invalid signal

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

		push	eax		; push EAX
		push	ebx		; push EBX

; ------------- Get current task (-> EBX signal lock)

		CURRENT	ebx		; EBX <- get current task
		add	ebx,TASK_SigLock ; EBX <- signal queue lock

; ------------- Lock signal queue

		pushf			; push flags
		cli			; disable interrupts
%ifdef	SMP
		LOCK_Lock ebx		; lock signal queue
%endif
; ------------- Check if signal is pending

		movzx	eax,al		; EAX <- signal number
		bt	[ebx+TASK_Signal-TASK_SigLock],eax ; is signal pending?
		jc	SignalGetInfo2	; signal is pending

; ------------- Unlock signal queue on ERROR
%ifdef	SMP
		LOCK_Unlock ebx		; unlock signal queue
%endif
		popf			; pop flags
		stc			; set error flag
		jmp	short SignalGetInfo8

; ------------- Decrease number of signals and reset signal flag

SignalGetInfo2:	dec	dword [ebx+TASK_SigNum-TASK_SigLock] ; decrease signals
		cmp	al,32		; is it regular signal?
		jb	SignalGetInfo3	; reset flag for regular signal
		dec	byte [ebx+TASK_SigRTNum-TASK_SigLock+eax-32]
		jnz	SignalGetInfo4	; there are another real-time signals
SignalGetInfo3:	btr	[ebx+TASK_Signal-TASK_SigLock],eax ; reset flag

; ------------- Find the signal

SignalGetInfo4:
%ifdef	SMP
		push	ebx		; push EBX (signal lock)
%endif
		add	ebx,byte TASK_SigQueue-TASK_SigLock ; EBX <- list head
SignalGetInfo5:	mov	ebx,[ebx+LIST_Next] ; EBX <- next item
		cmp	[ebx+SIGNAL_Info+SI_Signal],al ; signal found?
		jne	SignalGetInfo5	; no, try next item

; ------------- Get signal parameters

		mov	eax,[ebx+SIGNAL_Info+SI_SignalDW] ; byte parameters
		mov	[ecx+SI_SignalDW],eax
		mov	eax,[ebx+SIGNAL_Info+SI_Sender] ; sender
		mov	[ecx+SI_Sender],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param1] ; parameter 1
		mov	[ecx+SI_Param1],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param2] ; parameter 2
		mov	[ecx+SI_Param2],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param3] ; parameter 3
		mov	[ecx+SI_Param3],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param4] ; parameter 4
		mov	[ecx+SI_Param4],eax

; ------------- Free old entry from the queue

		xchg	eax,ebx		; EAX <- signal entry
		call	ListDel		; free signal list entry
		call	SysMemFree	; free memory block

; ------------- Unlock signal queue on OK
%ifdef	SMP
		pop	ebx		; pop EBX (signal lock)
		LOCK_Unlock ebx		; unlock signal queue
%endif
		popf			; pop flags
		clc			; clear error flag, operation OK

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

SignalGetInfo8:	pop	ebx		; pop EBX
		pop	eax		; pop EAX
SignalGetInfo9:	ret

; -----------------------------------------------------------------------------
;             Get specific signal from the signal queue (from user)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63, except SIGKILL, SIGCONT, SIGSTOP)
; OUTPUT:	CY = required signal is not pending
;		NC = signal found and removed from the signal queue
; NOTES:	Signal may be taken even if it is blocked.
; -----------------------------------------------------------------------------

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

SignalGetU:	push	ecx		; push ECX
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- push stack pointer

; ------------- Create signal info structure

		sub	esp,byte SIGINFO_size; create buffer (must be aligned!)
		mov	ecx,esp		; ECX <- info structure

; ------------- Get signal info

		call	SignalGetInfoU	; get signal info

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

		mov	esp,ebp		; ESP <- pop stack pointer
		pop	ebp		; pop EBP
		pop	ecx		; pop ECX
		ret

; -----------------------------------------------------------------------------
;             Get specific signal from the signal queue (from kernel)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
; OUTPUT:	CY = required signal is not pending
;		NC = signal found and removed from the signal queue
; NOTES:	Signal may be taken even if it is blocked.
; -----------------------------------------------------------------------------

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

SignalGet:	push	ecx		; push ECX
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- push stack pointer

; ------------- Create signal info structure

		sub	esp,byte SIGINFO_size; create buffer (must be aligned!)
		mov	ecx,esp		; ECX <- info structure

; ------------- Get signal info

		call	SignalGetInfo	; get signal info

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

		mov	esp,ebp		; ESP <- pop stack pointer
		pop	ebp		; pop EBP
		pop	ecx		; pop ECX
		ret

; -----------------------------------------------------------------------------
;               Get next unblocked signal from the signal queue
; -----------------------------------------------------------------------------
; INPUT:	ECX = SIGINFO structure (it will be filled with new data)
; OUTPUT:	CY = no unblocked signal is pending, structure will not change
;		NC = signal removed from the queue and structure filled out
; -----------------------------------------------------------------------------

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

SignalNext:	push	eax		; push EAX
		push	ebx		; push EBX
		push	edx		; push EDX

; ------------- Get current task (-> EBX signal lock)

		CURRENT	ebx		; EBX <- get current task
		add	ebx,TASK_SigLock ; EBX <- signal queue lock

; ------------- Lock signal queue

		pushf			; push flags
		cli			; disable interrupts
%ifdef	SMP
		LOCK_Lock ebx		; lock signal queue
%endif
; ------------- Check if any signal is pending

		mov	eax,[ebx+TASK_SigMask-TASK_SigLock] ; EAX <- mask LOW
		test	eax,[ebx+TASK_Signal-TASK_SigLock] ; pending signal?
		jnz	SignalNext3	; pending signal found
		mov	edx,[ebx+TASK_SigMask-TASK_SigLock+4]; EDX <- mask HIGH
		test	edx,[ebx+TASK_Signal-TASK_SigLock+4] ; pending signal?
		jnz	SignalNext3	; pending signal found

; ------------- Unlock signal queue on ERROR
%ifdef	SMP
		LOCK_Unlock ebx		; unlock signal queue
%endif
		popf			; pop flags
		stc			; set error flag
		jmp	short SignalNext9

; ------------- Find signal (here is EDX:EAX=signal mask, EBX=queue lock)

SignalNext3:	push	ebx		; push EBX (signal lock)
		push	ecx		; push ECX (SIGINFO structure)
		add	ebx,byte TASK_SigQueue-TASK_SigLock ; EBX <- head
SignalNext4:	mov	ebx,[ebx+LIST_Next] ; EBX <- next item
		movzx	ecx,byte [ebx+SIGNAL_Info+SI_Signal] ; signal number

; ------------- Check signal LOW

		cmp	cl,32		; is it signal LOW?
		jae	SignalNext5	; it is signal HIGH
		bt	eax,ecx		; test if signal is blocked
		jc	SignalNext6	; signal is not blocked
		jmp	short SignalNext4 ; try next signal

; ------------- Check signal HIGH

SignalNext5:	sub	cl,32		; CL <- signal offset
		bt	edx,ecx		; test if signal is blocked
		jnc	SignalNext4	; signal is blocked, try next one

; ------------- Get signal parameters

SignalNext6:	pop	ecx		; pop ECX (SIGINFO structure)
		mov	eax,[ebx+SIGNAL_Info+SI_Sender] ; sender
		mov	[ecx+SI_Sender],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param1] ; parameter 1
		mov	[ecx+SI_Param1],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param2] ; parameter 2
		mov	[ecx+SI_Param2],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param3] ; parameter 3
		mov	[ecx+SI_Param3],eax
	        mov	eax,[ebx+SIGNAL_Info+SI_Param4] ; parameter 4
		mov	[ecx+SI_Param4],eax
		mov	eax,[ebx+SIGNAL_Info+SI_SignalDW] ; byte parameters
		mov	[ecx+SI_SignalDW],eax
		movzx	eax,al		; EAX <- signal number

; ------------- Free old entry from the queue

		xchg	eax,ebx		; EAX <- entry, EBX <- signal number
		call	ListDel		; free signal list entry
		call	SysMemFree	; free memory block
		xchg	eax,ebx		; EAX <- signal number
		pop	ebx		; pop EBX (signal queue lock)

; ------------- Decrease number of signals and reset signal flag

		dec	dword [ebx+TASK_SigNum-TASK_SigLock] ; decrease signals
		cmp	al,32		; is it regular signal?
		jb	SignalNext7	; reset flag for regular signal
		dec	byte [ebx+TASK_SigRTNum-TASK_SigLock+eax-32]
		jnz	SignalNext8	; there are another real-time signals
SignalNext7:	btr	[ebx+TASK_Signal-TASK_SigLock],eax ; reset flag

; ------------- Unlock signal queue on OK

SignalNext8:
%ifdef	SMP
		LOCK_Unlock ebx		; unlock signal queue
%endif
		popf			; pop flags
		clc			; clear error flag, operation OK

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

SignalNext9:	pop	edx		; pop EDX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                      Flush pending signals (from user)
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = signal mask (1=flush signal)
; NOTES:	Cannot flush signals SIGKILL, SIGCONT, SIGSTOP.
;		Blocked signals are flushed too.
; -----------------------------------------------------------------------------

SignalFlushU:	push	eax		; push EAX
		and	eax,~((1<<SIGKILL)+(1<<SIGCONT)+(1<<SIGSTOP))
		call	SignalFlush	; flush pending signals
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                      Flush pending signals (from kernel)
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = signal mask (1=flush signal)
; NOTES:	Blocked signals are flushed too.
; -----------------------------------------------------------------------------

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

SignalFlush:	push	eax		; push EAX
		push	ebx		; push EBX
		push	ecx		; push ECX
		push	esi		; push ESI
		push	edi		; push EDI
		pushf			; push flags
		cli			; disable interrupts

; ------------- Get current task (-> EBX signal lock)

		CURRENT	ebx		; EBX <- get current task
		add	ebx,TASK_SigLock ; EBX <- signal queue lock

; ------------- Check if any signal is pending

		test	eax,[ebx+TASK_Signal-TASK_SigLock]; signal pending LOW?
		jnz	SignalFlush1	; any signal pending LOW
		test	edx,[ebx+TASK_Signal+4-TASK_SigLock] ; pending HIGH?
		jz	SignalFlushA	; no pending signal

; ------------- Lock signal queue

SignalFlush1:
%ifdef	SMP
		LOCK_Lock ebx		; lock signal queue
%endif
; ------------- Find signal

SignalFlush2:	lea	esi,[ebx+TASK_SigQueue-TASK_SigLock] ; ESI <- head
		mov	edi,esi		; EDI <- queue head
SignalFlush3:	mov	esi,[esi+LIST_Next] ; ESI <- next item
SignalFlush4:	cmp	esi,edi		; end of queue?
		je	SignalFlush9	; end of queue
		movzx	ecx,byte [esi+SIGNAL_Info+SI_Signal] ; signal number

; ------------- Check signal LOW

		cmp	cl,32		; is it signal LOW?
		jae	SignalFlush5	; it is signal HIGH
		bt	eax,ecx		; test if it is required signal
		jc	SignalFlush6	; it is required signal
		jmp	short SignalFlush3 ; try next signal

; ------------- Check signal HIGH

SignalFlush5:	sub	cl,32		; CL <- signal offset
		bt	edx,ecx		; test if it is required signal
		jnc	SignalFlush3	; try next signal
		add	cl,32		; ECX <- signal number

; ------------- Decrease number of signals and reset signal flag

SignalFlush6:	dec	dword [ebx+TASK_SigNum-TASK_SigLock] ; decrease signals
		cmp	cl,32		; is it regular signal?
		jb	SignalFlush7	; reset flag for regular signal
		dec	byte [ebx+TASK_SigRTNum-TASK_SigLock+ecx-32]
		jnz	SignalFlush8	; there are another real-time signals
SignalFlush7:	btr	[ebx+TASK_Signal-TASK_SigLock],ecx ; reset flag

; ------------- Free old entry from the queue

SignalFlush8:	push	eax		; push EAX
		xchg	eax,esi		; EAX <- signal item
		mov	esi,[eax+LIST_Next] ; ESI <- next item
		call	ListDel		; free signal list entry
		call	SysMemFree	; free memory block
		pop	eax		; pop EAX
		jmp	short SignalFlush4

; ------------- Unlock signal queue

SignalFlush9:
%ifdef	SMP
		LOCK_Unlock ebx		; unlock signal queue
%endif
; ------------- Pop registers

SignalFlushA:	popf			; pop flags
		pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                    Flush all pending signals (from user)
; -----------------------------------------------------------------------------
; NOTES:	Cannot flush signals SIGKILL, SIGCONT, SIGSTOP.
;		Blocked signals are flushed too.
; -----------------------------------------------------------------------------

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

SignalFlushAllU:push	eax		; push EAX
		push	edx		; push EDX

; ------------- Flush signals

		xor	eax,eax		; EAX <- 0
		dec	eax		; EAX <- -1
		mov	edx,eax		; EDX <- -1
		call	SignalFlushU	; flush signals from user

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

		pop	edx		; pop EDX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                    Flush all pending signals (from kernel)
; -----------------------------------------------------------------------------
; NOTES:	Blocked signals are flushed too.
; -----------------------------------------------------------------------------

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

SignalFlushAll:	push	eax		; push EAX
		push	edx		; push EDX

; ------------- Flush signals

		xor	eax,eax		; EAX <- 0
		dec	eax		; EAX <- -1
		mov	edx,eax		; EDX <- -1
		call	SignalFlush	; flush signals

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

		pop	edx		; pop EDX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                             Get signal action
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
; OUTPUT:	ECX = signal action flags
;		EDX = signal handler
;		EDI:ESI = signal action mask (1=signal is enabled)
; -----------------------------------------------------------------------------

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

SignalGetAction:push	eax		; push EAX
		push	ebx		; push EBX
		pushf			; push flags
		cli			; disable interrupts

; ------------- Prepare default handler

		mov	ecx,SA_RESET	; default flags
		xor	edx,edx		; EDX <- 0, default handler
		xor	esi,esi		; ESI <- 0
		dec	esi		; ESI <- -1, signals enabled
		mov	edi,esi		; EDI <- -1, signals enabled

; ------------- Check if signal number is valid

		cmp	al,63		; maximal signal number
		ja	SignalGetAct8	; invalid signal number
		cmp	al,SIGNULL	; signal SIGNULL?
		je	SignalGetAct8	; signal SIGNULL is always ignored

; ------------- Prepare pointer to signal action table (-> EBX)

		CURRENT	ebx		; EBX <- get current task
		mov	ebx,[ebx+TASK_SigAction] ; EBX <- action table

; ------------- Lock signal action table
%ifdef	SMP
		LOCK_Lock ebx		; lock signal action table
%endif
; ------------- Prepare pointer to signal action (-> EAX)

		movzx	eax,al		; EAX <- signal number
		shl	eax,4		; EAX <- offset in signal action table
		add	eax,ebx		; EAX <- pointer into table

; ------------- Get signal action

		mov	edx,[eax+SA_Handler] ; get signal handler
		mov	ecx,[eax+SA_Flags] ; get flags
		mov	esi,[eax+SA_Mask] ; get signal mask LOW
		mov	edi,[eax+SA_Mask+4] ; get signal mask HIGH

; ------------- Unlock signal action table
%ifdef	SMP
		LOCK_Unlock ebx		; unlock signal action table
%endif
; ------------- Pop registers

SignalGetAct8:	popf			; pop flags
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;        Make signal action table private (duplicate it if it is shared)
; -----------------------------------------------------------------------------
; OUTPUT:	CY = error (not enough memory to create new table)
; LOCKS:	SysMemLock
; NOTES:	Action table must be in locked state with interrupts disabled.
; -----------------------------------------------------------------------------

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

SignalUnshare:	pusha			; push all registers

; ------------- Get current task (-> EDX)

		CURRENT	edx		; EDX <- get current task

; ------------- Get signal actiom table (-> EBX)

		mov	ebx,[edx+TASK_SigAction] ; EBX <- action table

; ------------- Check if table requires copy-on-write

		cmp	dword [ebx+ST_Ref],byte 1 ; is this table private?
		je	SignalUnshare8	; table is already private

; ------------- Create new signal action table

		mov	eax,SIGTAB_size	; EAX <- size of signal action table
		call	SysMemAlloc	; get new signal action table
		jc	SignalUnshare8	; memory error

; ------------- Copy signal action table contents

		mov	esi,ebx		; ESI <- old table
		mov	edi,eax		; EDI <- new table
		mov	ecx,SIGTAB_size/4 ; ECX <- signal table size / 4
		rep	movsd		; copy signal action table

; ------------- Set new reference counter

		inc	ecx		; ECX <- 1
		mov	[eax+ST_Ref],ecx ; initialize reference counter (=1)

; ------------- Release old reference counter

		dec	dword [ebx+ST_Ref] ; decrease old reference counter

; ------------- Store pointer to new signal action table

		mov	[edx+TASK_SigAction],eax ; store new action table

; ------------- Unlock old signal action table
%ifdef	SMP
		LOCK_Unlock ebx		; unlock old signal action table
%endif
		clc			; clear error flag

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

SignalUnshare8:	popa			; pop all registers
SignalUnshare9:	ret

; -----------------------------------------------------------------------------
;                               Set signal action
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
;		ECX = new signal action flags
;		EDX = new signal handler (or SA_DEF, SA_IGN, ...)
;		EDI:ESI = new signal action mask (1=signal is enabled)
; OUTPUT:	CY = error (not enough memory to copy-on-write action table)
;		ECX = old signal action flags
;		EDX = old signal handler
;		EDI:ESI = old signal action mask (1=signal is enabled)
; LOCKS:	TASK_SigLock
; NOTES:	SIGNULL, SIGKILL, SIGCONT, SIGSTOP have always default action.
;		SIGKILL, SIGCONT and SIGSTOP are always enabled.
; -----------------------------------------------------------------------------

; ------------- Check if signal number is valid (return NC)

SignalSetAction:cmp	al,63		; maximal signal number
		ja	short SignalUnshare9 ; invalid signal number

; ------------- Signals with default handler (returns NC)

		cmp	al,SIGNULL	; signal SIGNULL?
		je	short SignalUnshare9 ; ignore signal SIGNULL
		cmp	al,SIGKILL	; signal SIGKILL?
		je	short SignalUnshare9 ; signal has default handler
		cmp	al,SIGCONT	; signal SIGCONT?
		je	short SignalUnshare9 ; signal has default handler
		cmp	al,SIGSTOP	; signal SIGSTOP?
		je	short SignalUnshare9 ; signal has default handler

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

		push	eax		; push EAX
		push	ebx		; push EBX
		pushf			; push flags
		cli			; disable interrupts

; ------------- Enable signals SIGKILL, SIGCONT, SIGSTOP

		or	esi,(1<<SIGKILL)+(1<<SIGCONT)+(1<<SIGSTOP)

; ------------- Prepare pointer to signal action table (-> EBX)

		CURRENT	ebx		; EBX <- get current task
		mov	ebx,[ebx+TASK_SigAction] ; EBX <- action table

; ------------- Lock signal action table
%ifdef	SMP
		LOCK_Lock ebx		; lock signal action table
%endif
; ------------- Prepare pointer to signal action (-> EAX)

		movzx	eax,al		; EAX <- signal number
		shl	eax,4		; EAX <- offset in signal action table
		add	eax,ebx		; EAX <- pointer into table

; ------------- Check if table is private

		cmp	dword [ebx+ST_Ref],byte 1 ; is this table private?
		je	SignalSetAct6	; talbe is already private

; ------------- Check if change signal action entries

		cmp	edx,[eax+SA_Handler] ; set/get new signal handler
		jne	SignalSetAct2	; change
		cmp	ecx,[eax+SA_Flags] ; set/get new flags
		jne	SignalSetAct2	; change
		cmp	esi,[eax+SA_Mask] ; set/get signal mask LOW
		jne	SignalSetAct2	; change
		cmp	edi,[eax+SA_Mask+4] ; set/get signal mask HIGH
		je	SignalSetAct8	; no change

; ------------- Duplicate signal action table if it is shares

SignalSetAct2:	sub	eax,ebx		; EAX <- offset in action table
		call	SignalUnshare	; unshare signal action table
		jnc	SignalSetAct4	; memory is OK

; ------------- Memory error
%ifdef	SMP
		LOCK_Unlock ebx		; unlock signal action table
%endif
		popf			; pop flags
		stc			; set error flag
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; ------------- Get new signal action (after unsharing)

SignalSetAct4:	CURRENT	ebx		; EBX <- get current task
		mov	ebx,[ebx+TASK_SigAction] ; EBX <- action table
		add	eax,ebx		; EAX <- new signal action

; ------------- Set new signal action

SignalSetAct6:	xchg	edx,[eax+SA_Handler] ; set/get new signal handler
		xchg	ecx,[eax+SA_Flags] ; set/get new flags
		xchg	esi,[eax+SA_Mask] ; set/get signal mask LOW
		xchg	edi,[eax+SA_Mask+4] ; set/get signal mask HIGH

; ------------- Unlock signal action table

SignalSetAct8:
%ifdef	SMP
		LOCK_Unlock ebx		; unlock signal action table
%endif
; ------------- Pop registers

SignalSetAct9:	popf			; pop flags
		clc			; clear error flag
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                            Get signal mask
; -----------------------------------------------------------------------------
; OUTPUT:	EDX:EAX = signal mask (1=signal is enabled)
; -----------------------------------------------------------------------------

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

SignalGetMask:	push	ebx		; push EBX

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

		CURRENT	ebx		; EBX <- get current task

; ------------- Get signal mask

		mov	eax,[ebx+TASK_SigMask] ; get signal mask LOW
		mov	edx,[ebx+TASK_SigMask+4] ; get signal mask HIGH

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

		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;       Set signal mask (from user, cannot disable SIGKILL, SIGCONT, SIGSTOP)
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = new signal mask (1=signal is enabled)
; OUTPUT:	EDX:EAX = old signal mask (1=signal is enabled)
; -----------------------------------------------------------------------------

; ------------- Enable signals SIGKILL, SIGCONT, SIGSTOP

SignalSetMaskU:	or	eax,(1<<SIGKILL)+(1<<SIGCONT)+(1<<SIGSTOP)

; SignalSetMask must follow!

; -----------------------------------------------------------------------------
;                      Set signal mask (from kernel)
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = new signal mask (1=signal is enabled)
; OUTPUT:	EDX:EAX = old signal mask (1=signal is enabled)
; -----------------------------------------------------------------------------

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

SignalSetMask:	push	ebx		; push EBX

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

		CURRENT	ebx		; EBX <- get current task

; ------------- Set/get new signal mask

		xchg	eax,[ebx+TASK_SigMask] ; set/get signal mask LOW
		xchg	edx,[ebx+TASK_SigMask+4] ; set/get signal mask HIGH

; ------------- Reschedule task

		mov	ebx,[ebx+TASK_RunQueue] ; EBX <- current run-queue
		RESCHEDULE ebx		; reschedule request

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

		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;                             Enable one signal
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalEnable:	cmp	al,63		; maximal signal number
		ja	SignalEnable8	; invalid signal number

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

		push	eax		; push EAX
		push	ebx		; push EBX

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

		CURRENT	ebx		; EBX <- get current task

; ------------- Set signal mask

		movzx	eax,al		; EAX <- signal number
%ifdef	SMP
		lock			; CPU instruction lock
%endif
		bts	[ebx+TASK_SigMask],eax ; set signal mask
		jc	SignalEnable4	; signal was already enabled

; ------------- Reschedule task

		mov	ebx,[ebx+TASK_RunQueue] ; EBX <- current run-queue
		RESCHEDULE ebx		; reschedule request

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

SignalEnable4:	pop	ebx		; pop EBX
		pop	eax		; pop EAX
SignalEnable8:	ret

; -----------------------------------------------------------------------------
;   Disable one signal (from user, cannot disable SIGKILL, SIGCONT, SIGSTOP)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63, except SIGKILL, SIGCONT, SIGSTOP)
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalDisableU:	cmp	al,SIGKILL	; is it KILL signal?
		je	SignalDisable8	; cannot be disabled
		cmp	al,SIGCONT	; is it CONTINUE signal?
		je	SignalDisable8	; cannot be disabled
		cmp	al,SIGSTOP	; is it STOP signal?
		je	SignalDisable8	; cannot be disabled

; SignalDisable must follow!

; -----------------------------------------------------------------------------
;                       Disable one signal (from kernel)
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalDisable:	cmp	al,63		; maximal signal number
		ja	SignalDisable8	; invalid signal number

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

		push	eax		; push EAX
		push	ebx		; push EBX

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

		CURRENT	ebx		; EBX <- get current task

; ------------- Clear signal mask

		movzx	eax,al		; EAX <- signal number
%ifdef	SMP
		lock			; CPU instruction lock
%endif
		btr	[ebx+TASK_SigMask],eax ; clear signal mask

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

		pop	ebx		; pop EBX
		pop	eax		; pop EAX
SignalDisable8:	ret

; -----------------------------------------------------------------------------
;                      Check if signal is enabled
; -----------------------------------------------------------------------------
; INPUT:	AL = signal number (0 to 63)
; OUTPUT:	CY = signal is disabled
; -----------------------------------------------------------------------------

; ------------- Check signal number

SignalEnabled:	cmp	al,63		; maximal signal number
		ja	SignalEnabled8	; invalid signal number (=NC)

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

		push	eax		; push EAX
		push	ebx		; push EBX

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

		CURRENT	ebx		; EBX <- get current task

; ------------- Test signal mask

		movzx	eax,al		; EAX <- signal number
		bt	[ebx+TASK_SigMask],eax ; test signal mask (CY=enabled)

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

		pop	ebx		; pop EBX
		pop	eax		; pop EAX
SignalEnabled8: cmc			; invert flag
		ret

; -----------------------------------------------------------------------------
;                                   Data
; -----------------------------------------------------------------------------

		DATA_SECTION

		align	4, db 0

; ------------- Signal default actions

SignalDefAct:	db	SA_IGN		; 0: SIGNULL, unused signal
		db	SA_TERM		; 1: SIGHUP, hang up terminal
		db	SA_TERM		; 2: SIGINT, interrupt from keyboard
		db	SA_DUMP		; 3: SIGQUIT, quit from keyboard
		db	SA_DUMP		; 4: SIGILL, illegal instruction
		db	SA_DUMP		; 5: SIGTRAP, trace/breakpoint trap
		db	SA_DUMP		; 6: SIGABRT, abort
		db	SA_DUMP		; 7: SIGBUS, bus error
		db	SA_DUMP		; 8: SIGFPE, floating-point exception
		db	SA_TERM		; 9: SIGKILL, kill, termination
		db	SA_TERM		; 10: SIGUSR1, user defined signal 1
		db	SA_DUMP		; 11: SIGSEGV, invalid memory reference
		db	SA_TERM		; 12: SIGUSR2, user defined signal 2
		db	SA_TERM		; 13: SIGPIPE, write without readers
		db	SA_TERM		; 14: SIGALRM, real timer expired
		db	SA_TERM		; 15: SIGTERM, process termination
		db	SA_TERM		; 16: SIGSTKFLT, FPU stack error
		db	SA_IGN		; 17: SIGCHLD, child state changed
		db	SA_IGN		; 18: SIGCONT, resume execution
		db	SA_STOP		; 19: SIGSTOP, pause process execution
		db	SA_STOP		; 20: SIGTSTP, suspend request from tty
		db	SA_STOP		; 21: SIGTTIN, tty input for background
		db	SA_STOP		; 22: SIGTTOU, tty output for background
		db	SA_IGN		; 23: SIGURG, urgent condition on socket
		db	SA_DUMP		; 24: SIGXCPU, CPU time limit exceeded
		db	SA_DUMP		; 25: SIGXFSZ, file size limit exceeded
		db	SA_TERM		; 26: SIGVTALRM, virtual timer expired
		db	SA_TERM		; 27: SIGPROF, profiling timer expired
		db	SA_IGN		; 28: SIGWINCH, window resizing
		db	SA_TERM		; 29: SIGIO, input/output now possible
		db	SA_TERM		; 30: SIGPWR, power supply failure
		db	SA_DUMP		; 31: SIGSYS, bad system call

Back to source browser