Paste Description for Task Switcher
The Task Switcher of the ToasterOS written by Toaster.
- Task Switcher
- Sunday, July 23rd, 2006 at 1:46:14am MDT
- ; **********************************************************
- ; Name: Task Switcher
- ; Autor: Toaster Burger
- ; Version: 1.00
- ; Date: 26.11.2005
- ; last Update: 26.11.2005
- ; see document: ToasterOS.pdf
- ; **********************************************************
- [bits 32]
- CPU 386
- %define Type_System
- %include "interface.asm"
- %define Handle_Size 6
- org Task_Switcher
- jmp dword Enable_Scheduler
- jmp dword Create_Task
- jmp dword Delete_Task
- jmp dword Destroy_Task
- jmp dword Check_Task_Handle
- jmp dword Dispatcher
- jmp dword Finite
- jmp dword Create_Task_System
- jmp dword Switch_Task
- jmp dword Get_Current_Process
- Enable_Scheduler: ; enable (start) the Scheduler
- ; API Enable_Scheduler
- Enter_System_Environment
- ; command CPUID available (test bit 21 of eflags to set) ?
- pushfd
- or [esp],dword 1000000000000000000000b
- popfd
- pushfd
- pop eax
- test eax,1000000000000000000000b
- jz No_FPU_MMX_SSE2_support
- ; check if the FPU, MMX, SSE (re)store command is available
- mov eax,1
- CPU PentiumPro
- cpuid
- CPU 386
- test edx,1000000000000000000000000b
- jz No_FPU_MMX_SSE2_support
- jmp Write_Task_Table
- No_FPU_MMX_SSE2_support:
- ; if here the fxsave/fxrstor opcodes are not supported, so delete them
- mov [Store_FPU_MMX_SSE_state],dword 90909090h
- mov [Store_FPU_MMX_SSE_state+4],word 9090h
- mov [Store_FPU_MMX_SSE_state+6],byte 90h
- mov [Restore_FPU_MMX_SSE_state],dword 90909090h
- mov [Restore_FPU_MMX_SSE_state+4],word 9090h
- mov [Restore_FPU_MMX_SSE_state+6],byte 90h
- Write_Task_Table:
- mov [Current_Task],dword Task_Table
- xor ecx,ecx ; loop counter = 65536
- xor eax,eax
- mov edi,Task_Table
- rep stosw ; erase all words
- rep stosd ; erase all dwords
- Leave_System_Environment
- ret
- Create_Task_System:
- ; API Create_Task_System, Handle, Process, Stack, Address, Data, Size
- ; Handle = Process Handle (of the caller's one)
- ; Process = Process Handle of the Process to start the Task
- ; Stack = start stack (esp) of the new task (the value stack is from high to low)
- ; Address = start address (eip) of the new task
- ; Size = bytes to copy from Data (source) to the new Tasks stack (destination)
- ; NOTES:
- ; The Data is bytewise copied to the stack from low to high, and the new Task's
- ; stack pointer will point BEFORE the data.
- ; This function adds to the data the Task Handle, so esp+0 points to the Handle
- ; and esp+4 to the user sepcific data.
- ; The caller won't get the Handle.
- Enter_System_Environment
- ; set the correct Stack Pointer
- mov eax,[Param6]
- sub [Param3],eax
- ; search a free Task Handle
- mov esi,Task_Table
- xor ecx,ecx ; loop counter = 65536
- Enter_Multitasking MT_Task_Switcher ; coordinate Multitasking access (enter)
- Search_free_System_Task:
- add esi,02h
- lodsd
- or eax,eax
- jz Task_System_found
- loop Search_free_System_Task
- ; if here, there is no free Task Handle
- Leave_Multitasking MT_Task_Switcher ; coordinate Multitasking access (leave)
- stc
- mov eax,No_free_Task
- jmp Create_Task_System_Exit
- Task_System_found: ; if comes here, a free Task Handle is found
- Leave_Multitasking MT_Task_Switcher ; coordinate Multitasking access (leave)
- lea edi,[esi-06h]
- ; store the Process Handle
- mov ax,[Param2]
- stosw
- ; store the Stack Pointer
- mov eax,[Param3]
- sub eax,12+(4*5)+32+108
- stosd
- ; set the stack for the new process on the current stack
- ; push following values in the correct direction:
- ; gs, fs, es, ds, ad, FPU, iret, Handle (4, 4, 4, 4, 32, 108, 12, 4)
- sub esp,12+(4*5)+32+108
- mov edi,esp
- mov ebx,esp
- ; set gs, fs, es, ds
- xor eax,eax
- stosd
- stosd
- mov eax,Data_Selector
- stosd
- stosd
- ; set edi, esi, ebp & esp (all points to the start of stack)
- mov eax,[Param3]
- stosd
- stosd
- stosd
- stosd
- ; xor eax, ebx, ecx & edx
- xor eax,eax
- stosd
- stosd
- stosd
- stosd
- ; FPU registers (use current)
- fsave [edi]
- add edi,108
- ; store the iret (eip, cs, flags)
- mov eax,[Param4]
- stosd
- mov eax,Code_Selector
- stosd
- mov eax,User_EFLAG
- stosd
- ; store the Task Handle
- xor eax,eax
- sub eax,ecx ; 65536 - loop counter
- stosd
- ; check whether the data is to copy (or not)
- cmp [Param6],dword 0
- je Copy_System_finished
- ; copy the data
- API Copy_Process_Data, [Param1], [Param2], [Param5], [Param3], [Param6]
- jc Create_Task_System_Exit
- Copy_System_finished:
- ; copy the (system) stack
- sub [Param3],dword (12+(4*5)+32+108)
- API Copy_Process_Data, [Param1], [Param2], ebx, [Param3], (12+(4*5)+32+108)
- ; reset the stack (delete temporary other process stack)
- add esp,12+(4*5)+32+108
- Create_Task_System_Exit:
- Leave_System_Environment
- ret
- Create_Task:
- ; API Create_Task, Handle, Process, Stack, Address, Data, Size
- ; Handle = Process Handle (of the caller's one)
- ; Process = Process Handle of the Process to start the Task
- ; Stack = start stack (esp) of the new task (the value stack is from high to low)
- ; Address = start address (eip) of the new task
- ; Size = bytes to copy from Data (source) to the new Tasks stack (destination)
- ; NOTES:
- ; The Data is bytewise copied to the stack from low to high, and the new Task's
- ; stack pointer will point BEFORE the data.
- ; This function adds to the data the Task Handle, so esp+0 points to the Handle
- ; and esp+4 to the user sepcific data.
- ; The caller won't get the Handle.
- Enter_System_Environment
- ; set the correct Stack Pointer
- mov eax,[Param6]
- sub [Param3],eax
- ; search a free Task Handle
- mov esi,Task_Table
- xor ecx,ecx ; loop counter = 65536
- Enter_Multitasking MT_Task_Switcher ; coordinate Multitasking access (enter)
- Search_free_Task:
- add esi,02h
- lodsd
- or eax,eax
- jz Task_found
- loop Search_free_Task
- ; if here, there is no free Task Handle
- Leave_Multitasking MT_Task_Switcher ; coordinate Multitasking access (leave)
- stc
- mov eax,No_free_Task
- jmp Create_Task_Exit
- Task_found: ; if comes here, a free Task Handle is found
- Leave_Multitasking MT_Task_Switcher ; coordinate Multitasking access (leave)
- lea edi,[esi-06h]
- ; store the Process Handle
- mov ax,[Param2]
- stosw
- ; store the Stack Pointer
- mov eax,[Param3]
- sub eax,12+(4*5)+32+108
- stosd
- ; set the stack for the new process on the current stack
- ; push following values in the correct direction:
- ; gs, fs, es, ds, ad, FPU, iret, Handle (4, 4, 4, 4, 32, 108, 12, 4)
- sub esp,12+(4*5)+32+108
- mov edi,esp
- mov ebx,esp
- ; set gs, fs, es, ds
- xor eax,eax
- stosd
- stosd
- mov eax,Data_Selector_User
- stosd
- stosd
- ; set edi, esi, ebp & esp (all points to the start of stack)
- mov eax,[Param3]
- stosd
- stosd
- stosd
- stosd
- ; xor eax, ebx, ecx & edx
- xor eax,eax
- stosd
- stosd
- stosd
- stosd
- ; FPU registers (use current)
- fsave [edi]
- add edi,108
- ; store the iret (eip, cs, flags)
- mov eax,[Param4]
- stosd
- mov eax,Code_Selector_User
- stosd
- mov eax,User_EFLAG
- stosd
- ; store the Task Handle
- sub eax,ecx ; 65536 - loop counter
- stosd
- ; check whether the data is to copy (or not)
- cmp [Param6],dword 0
- je Copy_finished
- ; copy the data
- API Copy_Process_Data, [Param1], [Param2], [Param5], [Param3], [Param6]
- jc Create_Task_Exit
- Copy_finished:
- ; copy the (system) stack
- sub [Param3],dword (12+(4*5)+32+108)
- API Copy_Process_Data, [Param1], [Param2], ebx, [Param3], (12+(4*5)+32+108)
- ; reset the stack (delete temporary other process stack)
- add esp,12+(4*5)+32+108
- Create_Task_Exit:
- Leave_System_Environment
- ret
- Delete_Task:
- ; API Delete_Task, Handle
- ; Handle = Handle of the Task to delete; returned (on the stack) by Create_Task
- Enter_System_Environment
- ; edi = address of the Handle
- imul edi,[Param1],Handle_Size
- add edi,Task_Table
- xor eax,eax
- stosw
- stosd
- Leave_System_Environment
- ret
- Destroy_Task:
- ; API Destroy_Task, Task_ID
- ; (undocumented)
- Enter_System_Environment
- mov esi,Task_Table
- xor ecx,ecx ; loop counter = 65536
- mov bx,[Param1]
- Destroy_free_Task:
- lodsw
- cmp ax,bx
- jne Destroy_free_Task_nt
- mov [esi-2],word 0
- mov [esi],dword 0
- Destroy_free_Task_nt:
- add esi,04h
- loop Destroy_free_Task
- Leave_System_Environment
- ret
- Finite:
- ; (undocumented)
- ; test register content ???
- ; - esp
- ; test if current cr3 register/handle is in Task Table ???
- Enter_MT dispatcher_state
- jmp Scheduler
- Dispatcher:
- Enter_MT dispatcher_state
- ; 1. store the current Task's state
- sub esp,108
- fsave [esp]
- pushad
- mpush ds, es, fs, gs
- ; store special FPU, MMX and SSE state or do nop
- Store_FPU_MMX_SSE_state:
- CPU PentiumPro
- fxsave [FPU_MMX_SSE2_State]
- CPU 386
- ; store the stack
- mov ebx,[Current_Task]
- mov [ebx+2],esp
- ; 2. execute the (internal) Scheduler
- Scheduler:
- add [Current_Task],dword Handle_Size
- cmp [Current_Task],dword Task_Table_End
- jl Scheduler_Next
- mov [Current_Task],dword Task_Table
- Scheduler_Next:
- mov ebx,[Current_Task]
- mov eax,[ebx+2]
- or eax,eax
- jz Scheduler
- ; restore the stack
- mov esp,[ebx+2]
- ; 3. restore the new Task's state
- movzx ecx,word [ebx]
- API Get_CR3, ecx
- mov cr3,eax
- ; restore special FPU, MMX and SSE state or do nop
- Restore_FPU_MMX_SSE_state:
- CPU PentiumPro
- fxrstor [FPU_MMX_SSE2_State]
- CPU 386
- mpop ds, es, fs, gs
- popad
- frstor [esp]
- add esp,108
- Leave_MT dispatcher_state
- ret
- Switch_Task:
- ; (undocumented)
- Enter_System
- ; set the return stack
- pushfd
- push cs
- push Switch_Task_ret
- ; switch the task
- call Dispatcher
- iret
- Switch_Task_ret:
- Leave_System
- ret
- Check_Task_Handle:
- ; API Check_Task_Handle, Handle, Process_Handle
- ; Handle = Handle of the Task to check of validity; returned (on the stack) by Create_Task
- ; Process Handle = Process Handle of the Task (have to be the same as by Create_Task)
- Enter_System_Environment
- ; ebx = address of the Handle
- imul ebx,[Param1],Handle_Size
- add edi,Task_Table
- ; check the boundarys
- cmp [Param1],dword Task_Table_End
- jnc Check_Task_Handle_Invalid
- ; check if the Task_Handle(current).Process_Handle is euqal to the as parameter's one
- mov ax,[ebx]
- cmp ax,[Param2]
- jne Check_Task_Handle_Invalid
- ; esp = 0 ?
- cmp [ebx+2],TPointer NULL
- je Check_Task_Handle_Invalid
- ; Process Handle valid?
- API Check_Process_Handle, TProcessHandle [Param2]
- jc Check_Task_Handle_Exit
- xor eax,eax
- clc
- jmp Check_Task_Handle_Exit
- Check_Task_Handle_Invalid:
- stc
- mov eax,Invalid_Handle
- Check_Task_Handle_Exit:
- Leave_System_Environment
- ret
- Get_Current_Process:
- ; (undocumented)
- Enter_System
- mov esi,[Current_Task]
- movzx eax,word [esi]
- Leave_System
- ret
- ; Current_Task is a direct pointer to the current Task into the Task Table
- Current_Task dd 0
- FPU_MMX_SSE dd "no"
- dispatcher_state db 0
- ; the Task Table contains information about the Tasks, the descriptor format:
- ; Process Handle (word)
- ; esp (dword)
- ; ------------------------------
- ; a Task description 6 Bytes
advertising
Update the Post
Either update this post and resubmit it with changes, or make a new post.
You may also comment on this post.
Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.