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

TASK.ASM

Task


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

		CODE_SECTION	32

; ------------- Create task flags

TASKCREATE_ADMIN	EQU	B0	; allow admin reserve

; -----------------------------------------------------------------------------
;                            Clone current task
; -----------------------------------------------------------------------------
; OUTPUT:	EAX = 0 for child, new task ID for parent
;		CY = error, no child task created
; -----------------------------------------------------------------------------

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

TaskClone:	push	ebx		; push EBX
		push	ecx		; push ECX
		push	edx		; push EDX
		push	esi		; push ESI
		push	edi		; push EDI
		push	ebp		; push EBP
		push	ds		; push DS
		push	es		; push ES
		push	fs		; push FS
		push	gs		; push GS
		pushf			; push flags
		cli			; disable interrupts

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

		CURRENT edx		; get current task
		lea	ecx,[edx+TASK_Stack] ; ECX <- end of stack
		sub	ecx,esp		; ECX <- stack size
		neg	ecx		; ECX <- -stack size
		fnsave	[edx+TASK_FPU]	; save FPU state

; ------------- Create new task (-> EBX)

		xor	eax,eax		; EAX <- flags
		call	TaskCreate	; create new task
		jnc	TaskClone2	; task created OK
		popf			; pop flags
		stc			; set error flag		
		jmp	short TaskClone9 ; error

; ------------- Initialize task

TaskClone2:	mov	dword [byte ebx+TASK_EIP],ScheduleRet; scheduler
		lea	eax,[ebx+TASK_Stack-7*4+ecx] 	; EAX <- task stack
		mov	dword [eax],0			; flags
		mov	dword [byte eax+6*4],TaskCloneCont ; return address
		mov	dword [ebx+TASK_ESP],eax	; stack address

; ------------- Store new task into run-queue

		and	dword [ebx+TASK_Alarm+ALARM_Expire],byte 0
		and	dword [ebx+TASK_Alarm+ALARM_Expire+4],byte 0
		call	TaskGoWait	; store task into wait-queue
		call	WakeUpTask	; wake up task
		xchg	eax,ebx		; EAX <- new task
		jmp	short TaskClone8

; ------------- Child

TaskCloneCont:	xor	eax,eax		; EAX <- 0

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

TaskClone8:	popf			; pop flags
		clc			; operation OK
TaskClone9:	pop	gs		; pop GS
		pop	fs		; pop FS
		pop	es		; pop ES
		pop	ds		; pop DS
		pop	ebp		; pop EBP
		pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;                         Set TSS descriptor
; -----------------------------------------------------------------------------
; INPUT:	ECX = TSS descriptor
;		EBX = task
; -----------------------------------------------------------------------------

SetTSSDescr:	push	ebx		; push EBX
		add	ebx,byte TASK_TSS ; EBX <- address of TSS
		mov	word [ecx+GLDT_Limit],TASK_IOTerm-TASK_TSS+2 ; limit
		mov	[ecx+GLDT_Base3-3],ebx ; base address HIGH
		mov	[ecx+GLDT_Base],ebx ; base address LOW
		mov	word [ecx+GLDT_Access],B7+9 ; TSS type, present
		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;                         Set LDT descriptor
; -----------------------------------------------------------------------------
; INPUT:	ECX = LDT descriptor
;		EBX = task
; -----------------------------------------------------------------------------

SetLDTDescr:	push	ebx		; push EBX
		or	word [ecx+GLDT_Limit],byte -1 ; limit
		and	dword [ecx+GLDT_Base3-3],byte 0 ; base address HIGH
		and	dword [ecx+GLDT_Base],byte 0 ; base address LOW
		mov	word [ecx+GLDT_Access],B7+2 ; LDT type, present
		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;                              Create new task
; -----------------------------------------------------------------------------
; INPUT:	AL = flags
;			B0: 1=admin reserve allowed, 0=only user tasks
;		EDX = address of parent task
; OUTPUT:	CY = memory error (EBX = NULL)
;		EBX = address of new task (NULL=memory error)
; LOCKS:	SysMemLock
; -----------------------------------------------------------------------------

; ------------- Create task memory block (-> EDX)

TaskCreate:	xchg	eax,ebx		; EBX <- push EAX
		mov	eax,TASK_size	; EAX <- size of task
		call	SysMemAlloc	; get new task memory block
		xchg	eax,ebx		; EBX <- address of task memory block
		jnc	TaskCreate2	; task created OK
		ret

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

TaskCreate2:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
		push	esi		; push ESI	
		push	edi		; push EDI

; ------------- Copy parent task

		mov	esi,edx		; ESI <- source task
		mov	edi,ebx		; EDI <- destination task
		mov	ecx,TASK_size/4	; ECX <- size of task / 4
		rep	movsd		; copy parent task

; ------------- Get TSS index (-> EAX)

		call	GetTSS		; get TSS index
		jnc	TaskCreate3	; TSS index OK
		xchg	eax,ebx		; EAX <- task memory block
		call	SysMemFree	; free task memory block
		xchg	eax,ebx		; EBX <- 0
		stc			; set error flag
		jmp	TaskCreate9

; ------------- Prepare TSS selector

TaskCreate3:	lea	ecx,[TASK_FIRST_TSS+eax*8] ; EDX <- TSS selector
		mov	[ebx+TASK_TR],ecx ; TSS selector
		mov	[ebx+TASK_TSSIndex],eax ; save TSS index

; ------------- Initialize TSS descriptor

		add	ecx,TaskTSSTab-TASK_FIRST_TSS ; ECX <- TSS descriptor
		call	SetTSSDescr	; set TSS descriptor

; ------------- Prepare LDT selector

		sub	ecx,TaskTSSTab-TASK_FIRST_LDT ; ECX <- LDT selector
		mov	[ebx+TASK_LDT],ecx ; LDT selector

; ------------- Initialize LDT descriptor

		add	ecx,TaskLDTTab-TASK_FIRST_LDT ; ECX <- LDT descriptor
		call	SetLDTDescr	; set LDT descriptor

; ------------- Initialize object head

		mov	eax,OBJECT_TASK	; EAX <- object type, task
		call	ObjectInit	; initialize object head

; ------------- Split remaining time quantum (between task and its parent)

		shr	dword [ebx+TASK_Remaining],1; task remaining time/2
		inc	dword [edx+TASK_Remaining] ; parent remaining time+1
		shr	dword [edx+TASK_Remaining],1; parent remaining time/2

; ------------- Initialize some parameters

		lea	eax,[ebx+TASK_Stack] ; initialize stack address
		mov	[ebx+TASK_ESP0],eax
		mov	[ebx+TASK_ESP1],eax
		mov	[ebx+TASK_ESP2],eax
		mov	byte [ebx+TASK_AbsPrio],PRIORITY_NORMAL ; priority
		mov	byte [ebx+TASK_RelPrio],0
		mov	byte [ebx+TASK_AddPrio],6
		mov	byte [ebx+TASK_MaxPrio],PRIORITY_MAXUSR
		call	TaskCalcPrio	; recalc new priority
		mov	[ebx+TASK_Priority],al	; store new priority

; ------------- Initialize task link

		lea	eax,[ebx+TASK_Link] ; EAX <- task link
		TREEINIT eax		; initialize task link

; ------------- Initialize link to task queue

		lea	eax,[ebx+TASK_Queue] ; EAX <- link to task queue
		LISTINIT eax		; initialize link to task queue

; ------------- Initialize signals

		xor	eax,eax		; EAX <- 0
		mov	[ebx+TASK_Signal],eax ; reset signal flags LOW
		mov	[ebx+TASK_Signal+4],eax ; reset signal flags HIGH
		mov	[ebx+TASK_SigNum],eax ; reset number of signals
		mov	[ebx+TASK_TaskLock],eax ; no task lock
		lea	edi,[ebx+TASK_SigRTNum] ; EDI <- number of RT signals
		xor	ecx,ecx		; ECX <- 0
		mov	cl,32/4		; ECX <- number of RT signals in DW
		rep	stosw		; reset real-time counters
		mov	al,SIGNAL_size	; EAX <- size of signal queue item
		call	SysMemAlloc	; get signal queue item
		mov	[ebx+TASK_SigRes],eax ; reserve signal entry
%ifdef	SMP
		LOCK_Init (ebx+TASK_SigLock) ; initialize signal queue lock
%endif
		lea	eax,[ebx+TASK_SigQueue] ; EAX <- signal queue
		LISTINIT eax		; initialize signal queue
		mov	eax,[ebx+TASK_SigAction] ; EAX <- signal actions
%ifdef	SMP
		lock			; CPU instruction lock
%endif
		inc	dword [eax+ST_Ref] ; increase shared sounter

; ------------- Link with parent

;		mov	[ebx+TASK_Link+TREE_Parent],edx ; link to parent
;		mov	eax,[edx+TASK_Link+TREE_Child] ; EAX <- first child
;		or	eax,eax		; any child?
;		jz	TaskCreate4	; no child
;		lea	esi,[ebx+TASK_Link] ; ESI <- sibling list
;		LISTADD	eax,esi,ecx	; link to sibling list
;		jmp	short TaskCreate5
;
;TaskCreate4:	mov	[edx+TASK_Link+TREE_Child],ebx ; it is first child
		
; ------------- Start time

TaskCreate5:	call	GetSystemTime	; get system time
		mov	[ebx+TASK_StartTime],eax ; store start time LOW
		mov	[ebx+TASK_StartTime+4],edx ; store start time HIGH

; ------------- Clear running time

		xor	eax,eax		; EAX <- 0
		mov	[ebx+TASK_RunTime],eax ; clear running time LOW
		mov	[ebx+TASK_RunTime+4],eax ; clear running time HIGH

; ------------- Initialize alarm

		lea	eax,[ebx+TASK_Alarm] ; EAX <- alarm
		LISTINIT eax		; initialize list
		xor	eax,eax		; EAX <- 0
		mov	[ebx+TASK_Alarm+ALARM_Repeat],eax ; repeat time LOW
		mov	[ebx+TASK_Alarm+ALARM_Repeat+4],eax ; repeat time HIGH
		mov	dword [ebx+TASK_Alarm+ALARM_Func],SleepWakeUp; function
		mov	[ebx+TASK_Alarm+ALARM_Data],ebx ; user data

; ------------- Mask of consoles

		mov	eax,[ConActMask] ; EAX <- mask of active consoles
		mov	[ebx+TASK_ConOutMask],eax ; mask of output consoles
		mov	[ebx+TASK_ConInMask],eax ; mask of input consoles

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

		clc			; flag - operation OK
TaskCreate9:	pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                              Create idle task
; -----------------------------------------------------------------------------
; INPUT:	EDX = index of CPU
; OUTPUT:	EBX = idle task
; DESTROYS:	EAX, ECX, EDX, ESI, EDI
; LOCKS:	SysMemLock
; -----------------------------------------------------------------------------

; ------------- Create idle task structure (it cannot fail, memory is OK now)

IdleInit:	mov	eax,TASK_size	; EAX <- size of task
		call	SysMemAlloc	; get new task memory block
		xchg	eax,ebx		; EBX <- address of task memory block

; ------------- Prepare run-queue (-> ESI)

		mov	esi,[RunQueueAddr+edx*4] ; ESI <- run-queue

; ------------- Clear task structure

		mov	edi,ebx		; EDI <- task structure
		xor	eax,eax		; EAX <- 0
		mov	ecx,TASK_size/4	; ECX <- size of task structure
		rep	stosd		; clear task structure

; ------------- Initialize object head

		mov	eax,OBJECT_TASK	; EAX <- object type, task
;		call	ObjectInit	; initialize object head

; ------------- Initialize basic registers

		lea	eax,[ebx+TASK_Stack]	; EAX <- task stack
		mov	[ebx+TASK_ESP0],eax	; ESP for level 0
		mov	[ebx+TASK_SS0],ss	; SS for level 0
		mov	[ebx+TASK_ESP1],eax	; ESP for level 1
		mov	[ebx+TASK_SS1],ss	; SS for level 1
		mov	[ebx+TASK_ESP2],eax	; ESP for level 2
		mov	[ebx+TASK_SS2],ss	; SS for level 2
		mov	[ebx+TASK_ESP],eax	; ESP for task
		mov	eax,cr3			; EAX <- cr3
		mov	[ebx+TASK_CR3],eax 	; set CR3
		mov	dword [ebx+TASK_EIP],Idle; idle loop
		mov	[ebx+TASK_ES],es	; ES
		mov	[ebx+TASK_CS],cs	; CS
		mov	[ebx+TASK_SS],ss	; SS
		mov	[ebx+TASK_DS],ds	; DS
		mov	eax,USER_DS		; AX <- user data segment
		mov	[ebx+TASK_FS],eax	; FS
		mov	[ebx+TASK_GS],eax	; GS
		mov	word [ebx+TASK_IOBase],TASK_IOBitmap ; perm. bit map
		or	dword [ebx+TASK_IOTerm],byte -1 ; set I/O terminator
		pushf			; push flags
		pop	eax		; EAX <- flags
		and	eax,~(B12+B13)	; set I/O privilege level to 0
		mov	[ebx+TASK_Flags],eax ; flags
		push	eax		; push EAX
		popf			; pop flags

; ------------- Initialize FPU

		fninit			; initialize FPU
		fnsave	[ebx+TASK_FPU]	; save FPU state

; ------------- Prepare TSS selector

		mov	al,1		; admin reserve allowed
		call	GetTSS		; get TSS index
		lea	ecx,[TASK_FIRST_TSS+eax*8] ; EDX <- TSS selector
		mov	[ebx+TASK_TR],ecx ; TSS selector
		mov	[ebx+TASK_TSSIndex],eax ; save TSS index

; ------------- Initialize TSS descriptor

		add	ecx,TaskTSSTab-TASK_FIRST_TSS ; ECX <- TSS descriptor
		call	SetTSSDescr	; set TSS descriptor

; ------------- Prepare LDT selector

		sub	ecx,TaskTSSTab-TASK_FIRST_LDT ; ECX <- LDT selector
		mov	[ebx+TASK_LDT],ecx ; LDT selector

; ------------- Initialize LDT descriptor

		add	ecx,TaskLDTTab-TASK_FIRST_LDT ; ECX <- LDT descriptor
		call	SetLDTDescr	; set LDT descriptor

; ------------- Initialize task link

		lea	eax,[ebx+TASK_Link] ; EAX <- task link
		TREEINIT eax		; initialize task link

; ------------- Set some other variables

		mov	byte [ebx+TASK_State],TASK_RUNNING ; running state
		mov	byte [ebx+TASK_Type],TASK_IDLE ; idle task type
		mov	[ebx+TASK_CPU],dl ; current CPU
		mov	eax,[CPUMask]	; EAX <- CPU mask
		mov	[ebx+TASK_CPUMask],eax ; mask of allowed CPUs

; ------------- Initialize link to task queue

		lea	eax,[ebx+TASK_Queue] ; EAX <- link to task queue
		LISTINIT eax		; initialize link to task queue

; ------------- Initialize signals

		dec	dword [ebx+TASK_SigMask] ; enable all signals LOW
		dec	dword [ebx+TASK_SigMask+4] ; enable all signals HIGH
%ifdef	SMP
		LOCK_Init (ebx+TASK_SigLock) ; initialize signal queue lock
%endif
		lea	eax,[ebx+TASK_SigQueue] ; EAX <- signal queue
		LISTINIT eax		; initialize signal queue
		mov	dword [ebx+TASK_SigMax],200 ; maximal number of signals

; ------------- Create default table of signal actions

		mov	eax,SIGTAB	; size of table of signal actions
		call	SysMemAlloc	; get table of signal actions
		mov	[ebx+TASK_SigAction],eax ; table of signal actions
		xchg	eax,edi		; EDI <- start of table
		xor	eax,eax		; EAX <- 0
		inc	eax		; EAX <- 1
		stosd			; initialize table lock
		stosd			; initialize number of shared count
		dec	eax		; EAX <- 0
		mov	ecx,SIGTAB_size/4-2	; ECX <- size of table
		rep	stosd		; clear signal action table

; ------------- Create reserve signal entry for SIGKILL

		xor	eax,eax		; EAX <- 0
		mov	al,SIGNAL_size	; EAX <- size of signal queue item
		call	SysMemAlloc	; get signal queue item
		mov	[ebx+TASK_SigRes],eax ; reserve signal entry

; ------------- Store task into run-queue

		mov	[ebx+TASK_RunQueue],esi ; set run-queue
		mov	edx,[esi+RUNQ_Current] ; EDX <- current task queue
		xor	ecx,ecx		; ECX <- 0, level
		call	TaskEnqueue	; store task into run-queue
		inc	dword [esi+RUNQ_Total] ; increase number of tasks
		mov	[esi+RUNQ_Idle],ebx ; idle task of this run-queue

; ------------- Start time

		call	GetSystemTime	; get system time
		mov	[ebx+TASK_StartTime],eax ; store start time LOW
		mov	[ebx+TASK_StartTime+4],edx ; store start time HIGH

; ------------- Initialize alarm

		lea	eax,[ebx+TASK_Alarm] ; EAX <- alarm
		LISTINIT eax		; initialize list
		xor	eax,eax		; EAX <- 0
		mov	[ebx+TASK_Alarm+ALARM_Repeat],eax ; repeat time LOW
		mov	[ebx+TASK_Alarm+ALARM_Repeat+4],eax ; repeat time HIGH
		mov	dword [ebx+TASK_Alarm+ALARM_Func],SleepWakeUp; function
		mov	[ebx+TASK_Alarm+ALARM_Data],ebx ; user data

; ------------- Mask of consoles

		mov	eax,[ConActMask] ; EAX <- mask of active consoles
		mov	[ebx+TASK_ConOutMask],eax ; mask of output consoles
		mov	[ebx+TASK_ConInMask],eax ; mask of input consoles
		ret

; -----------------------------------------------------------------------------
;                            Destroy task
; -----------------------------------------------------------------------------
; INPUT:	EBX = task to destroy
; -----------------------------------------------------------------------------

TaskDestroy:
		; !!!!!!!! TODO

		ret

; -----------------------------------------------------------------------------
;                            Kill task
; -----------------------------------------------------------------------------
; INPUT:	EBX = task to kill
; -----------------------------------------------------------------------------

TaskKill:
		; !!!!!!!! TODO

		ret

; -----------------------------------------------------------------------------
;                         Initialize TSS list
; -----------------------------------------------------------------------------

InitTSS:	mov	eax,TaskTSSTab	; EDX <- task TSS table
		mov	ebx,TaskFreeList ; EDX <- list of free TSS
		mov	ecx,TASK_MAX	; ECX <- number of tasks
InitTSS2:	call	ListLast	; add entry into list
		add	eax,byte GLDT_size ; EAX <- next entry
		loop	InitTSS2	; next entry
		ret

; -----------------------------------------------------------------------------
;                           Get TSS index
; -----------------------------------------------------------------------------
; INPUT:	AL = flag, 0=only user tasks, 1=admin reserve allowed
; OUTPUT:	EAX = index of TSS
;		CY = error, no free TSS
; -----------------------------------------------------------------------------

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

GetTSS:		push	ebx		; push EBX

; ------------- Lock free TSS table

		pushf			; push flags
		cli			; disable interrupts
%ifdef SMP
		mov	ebx,TaskFreeLock ; EBX <- lock to free TSS table
		call	SpinLock	; lock free TSS table
%endif
; ------------- Check if any free TSS left

		cmp	dword [TaskFree],byte 0 ; any free TSS left?
		jg	GetTSS2		; any free TSS left
		cmp	al,0		; admin reserve allowed?
		je	GetTSS9		; no admin reserve
		cmp	dword [TaskFree],byte -TASK_ADMIN ; admin reserve?
		jle	GetTSS9		; no free tasks left

; ------------- Decrease number of free tasks

GetTSS2:	dec	dword [TaskFree] ; decrease number of free tasks
		inc	dword [TaskUsedNum] ; increase number of used tasks

; ------------- Get index of next free task

		mov	eax,[TaskFreeList+LIST_Next] ; EBX <- next free task
		call	ListDel		; remove task from the list
		sub	eax,TaskTSSTab	; EAX <- offset in TSS table
		shr	eax,3		; EAX <- relative index of task

; ------------- Set flag in bit map of used tasks

		push	eax		; push EAX
		push	ecx		; push ECX

		mov	ebx,eax		; EBX <- index of task
		shr	ebx,3		; EBX <- offset od BYTE
		and	al,7		; AL <- index of bit in BYTE
		xchg	eax,ecx		; CL <- index of bit in BYTE
		xor	eax,eax		; EAX <- 0
		inc	eax		; EAX <- 1
		shl	eax,cl		; EAX <- bit mask
		or	[TaskUsedMap+ebx],al ; set flag in bit map

		pop	ecx		; pop ECX
		pop	eax		; pop EAX

; ------------- OK, unlock free TSS table
%ifdef SMP
		LOCK_Unlock TaskFreeLock ; unlock free TSS table
%endif
		popf			; pop flags and enable interrupts
		clc			; clear error flag

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

		pop	ebx		; pop EBX
		ret

; ------------- Error, unlock free TSS table

GetTSS9:
%ifdef SMP
		LOCK_Unlock TaskFreeLock ; unlock free TSS table
%endif
		popf			; pop flags and enable interrupts
		stc			; set error flag

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

		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;                      Check if TSS index is valid
; -----------------------------------------------------------------------------
; INPUT:	EAX = TSS index
; OUTPUT:	CY = error, TSS index is not valid (task does not exist)
; NOTES:	It does not lock TSS table.
; -----------------------------------------------------------------------------

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

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

; ------------- Check maximal TSS value

		cmp	eax,TASK_MAX	; is TSS index valid?
		jae	CheckTSS6	; TSS index is not valid

; ------------- Check if task is valid

		mov	ebx,eax		; EBX <- index of task
		shr	ebx,3		; EBX <- offset od BYTE
		and	al,7		; AL <- index of bit in BYTE
		xchg	eax,ecx		; CL <- index of bit in BYTE
		xor	eax,eax		; EAX <- 0
		inc	eax		; EAX <- 1
		shl	eax,cl		; EAX <- bit mask
		test	[TaskUsedMap+ebx],al ; test flag in bit map
		jnz	CheckTSS8	; task is valid
CheckTSS6:	stc			; set error flag

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

CheckTSS8:	pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		pop	eax		; pop EAX
		ret

; -----------------------------------------------------------------------------
;                           Free TSS index
; -----------------------------------------------------------------------------
; INPUT:	EAX = index of TSS
; OUTPUT:	CY = error, TSS index is not valid (task does not exist)
; -----------------------------------------------------------------------------

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

FreeTSS:	push	ebx		; push EBX

; ------------- Lock free TSS table

		pushf			; push flags
		cli			; disable interrupts
%ifdef SMP
		mov	ebx,TaskFreeLock ; EBX <- lock to free TSS table
		call	SpinLock	; lock free TSS table
%endif
; ------------- Check if index of TSS is valid

		call	CheckTSS	; check if TSS index is valid
		jc	FreeTSS9	; error, TSS index is not valid

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

		push	eax		; push EAX
		push	ecx		; push ECX

; ------------- Increase number of free tasks

		inc	dword [TaskFree] ; increase number of free tasks
		dec	dword [TaskUsedNum] ; decrease number of used tasks

; ------------- Add task to the list of free tasks

		push	eax		; push EAX
		shl	eax,3		; EAX <- offset of task
		add	eax,TaskTSSTab	; EAX <- address of task
		mov	ebx,TaskFreeList ; EBX <- free task list
		call	ListLast	; add task into end of list
		pop	eax		; pop EAX

; ------------- Reset flag in bit map of used tasks

		mov	ebx,eax		; EBX <- index of task
		shr	ebx,3		; EBX <- offset od BYTE
		and	al,7		; AL <- index of bit in BYTE
		xchg	eax,ecx		; CL <- index of bit in BYTE
		xor	eax,eax		; EAX <- 0
		inc	eax		; EAX <- 1
		shl	eax,cl		; EAX <- bit mask
		xor	[TaskUsedMap+ebx],al ; reset flag in bit map

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

		pop	ecx		; pop ECX
		pop	eax		; pop EAX

; ------------- OK, unlock free TSS table
%ifdef SMP
		LOCK_Unlock TaskFreeLock ; unlock free TSS table
%endif
		popf			; pop flags and enable interrupts
		clc			; clear error flag

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

		pop	ebx		; pop EBX
		ret

; ------------- Error, unlock free TSS table

FreeTSS9:
%ifdef SMP
		LOCK_Unlock TaskFreeLock ; unlock free TSS table
%endif
		popf			; pop flags and enable interrupts
		stc			; set error flag

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

		pop	ebx		; pop EBX
		ret

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

		DATA_SECTION

; ------------- Free TSS table

		align	4, db 0

%ifdef SMP
TaskFreeLock:	SPINLOCK		; lock to free TSS table
%endif
		align	4, db 0
TaskUsedNum:	dd	0		; number of used tasks
TaskFree:	dd	TASK_MAX-TASK_ADMIN ; number of free tasks (-reserve)
TaskFreeList:	LISTHEAD		; list of free TSS

; -----------------------------------------------------------------------------
;                            Uninitialized data
; -----------------------------------------------------------------------------

		BSS_SECTION

; ------------- Bit map of used tasks (32 or 512 bytes)

		align	4, resb 1
TaskUsedMap:	resb	(TASK_MAX+7)/8

Back to source browser