I can already spawn threads which store thier information in the TSS and use software based task switching (for portability between architectures, mostly). The way I vision it, a task is handled as a kernel thread if it supplies the special flags in the CreateTask() function.
So far, two tasks are spawned on the kernel init, this is Zombie Slayer and VC Manager
The only time a task switch occurs is when an interrupt fires in IRQ0 (PIT Timer), who's interval I have set to 100Hz.
My IRQHandler then forwards it to my scheduling function which makes all the necessary switches (context switch if necessary, stores old EIP, loads new one, etc..) Then does an explicit CALL or JMP to the new task code. Which is either the last instruction performed or the first instruction of the new task.
My zombie slayer handles tasks which have not been destroyed yet. The way Optimix does it, it doesn't destroy tasks right on the dot, it sets thier status as STATUS_ZOMBIE and STATE_FROZEN which removes them from the list of running tasks and makes them a zombie task. The slayer searches for Zombie Tasks and kills them by removing them once and for all and free()'ing up all thier (virtual and physical) memory.
The VC manager will hopefully do what I suggested above and in making it a thread I effectively stop it from blocking anything which is useful to the kernel (like the actual kernel
).