Page 1 of 1
deleting a task
Posted: Thu Jan 08, 2004 3:33 am
by finda
I have implement my task manager and task switching code. I can add new tasks to my task queue. But my probem is to catch a task when it finishes. I mean all my tasks must be infinite. if a task finishes, my kernel couse an invalid opcode. How can I delete a task from my queue after task returns?(I implement my delete task function, but dont know how to understand if a task finishes...)
Re:deleting a task
Posted: Thu Jan 08, 2004 4:22 am
by BI lazy
Well: you need to have the task inform the kernel about exit with some call like: exit(0). Immediately after this call, you have to put the task in some kind of infinite loop to take care that it doesnt stroll out of its adress space. It is caught in this loop and just sits and waits for deletion.
Additionally, you can move the task to some queue like "tasks_to_delete" and have some kernel thread take care of it, when nothing else is to do in the system: it triggers all the clean up stuff, claims the tasks adress space back for system, moves pages back to the free pages stack, eventually zeroes them out ... one can imagine many many way. The idea of a "buffy - the dead thread slayer" kernel thread stems not from me originally. But it is a good idea.
Re:deleting a task
Posted: Thu Jan 08, 2004 6:40 am
by Pype.Clicker
for someone that is used to Unix programming, killing a task may sound weird, because under unix, you needn't to call "exit(0)" explicitly: returning from main() function is sufficient.
What you need to know is that your unix C code is not naked when the system executes it: it has been wrapped into a cute "crt.o" binary file that contains something like
Code: Select all
__start:
; prepare args & argv on the stack
call main
mov ebx,eax (keep C function result)
mov eax, SYS_EXIT_CODE
int SYSTEM_CALL_INTERRUPT
Re:deleting a task
Posted: Thu Jan 08, 2004 7:03 am
by BI lazy
hmmm ... and who takes care the task doesn't stroll out of bounds if not slayed immediately?
I've seen somewhere, that after performing the exit epilogue the processes/tasks are caught in an endless loop untill they are dropped to the graveyard - ere they become zombies and you have to take the wooden stanchion of kill to get rid of 'em.
Re:deleting a task
Posted: Thu Jan 08, 2004 11:04 am
by Pype.Clicker
BI lazy wrote:
hmmm ... and who takes care the task doesn't stroll out of bounds if not slayed immediately?
Err ... what i was showing was not intended to replace the good 'Thread Slayer' of the system, just to replace the "main() {exit(0);}" by "main() {return 0;}" ...
I suspect i do not have the simplest solution, but in Clicker, when a thread want to die (or is killed), its id is sent to a special thread that can go to that address space and cleanup what has to be cleaned (kernel and user stack for this thread, for instance).
It's especially hard to have a thread killing itself properly, if you think about it a few minutes ...
Re:deleting a task
Posted: Thu Jan 08, 2004 11:47 am
by proxy
the way i handled this, was when i am setting up the task for entry in the task queue, i setup the stack in such a way that it will jump to a "thread_finish" function when it returns from the outermost function. This function marks the thread as finished, calls the threads terminiation code (unblock waiting threadsd, etc), then the scheduler will delete it at a later time.
i found this to be simplest, as it "just works"
proxy
Re:deleting a task
Posted: Thu Jan 08, 2004 12:26 pm
by Tim
In Mobius, all user-mode threads have their entry point set to a function within libsys.dll, which looks like: (from memory)
Code: Select all
void ThrStartup(void)
{
thread_info_t *info = ThrGetThreadInfo();
ThrExitThread(info->entry(info->param));
}
ThrExitThread is a system call which frees most of the thread's resources, makes the thread unrunnable, then switches threads. The thread's kernel stack ought to be given to a special kernel thread for later disposal, but I haven't written that yet.
Re:deleting a task
Posted: Thu Jan 08, 2004 2:55 pm
by proxy
call me crazy, but i don't understand the "need" for a reaper thread at all, or these wrapper functions.
my code to setup a thread basically looks like this: (C++, not C, but clear enough, also using setjmp switch technique for now)
Code: Select all
setName(name);
// get a resonable snapshot of the system state to start...
setjmp(m_State);
// allocate a stack (remember it for destruction)
stack_ptr = calloc(MAX_THREAD_STACK, 1);
// get a 32-bit pointer to end of stack
uint32 *stack = (uint32 *)((char *)stack_ptr + MAX_THREAD_STACK);
// push on some objects (return address, etc)
// args start here (reverse order)
*--stack = (uint32)func_arg;
// return address here
*--stack = (uint32)Scheduler::thread_finished;
// setup stack pointer (grows down)
m_State[0].esp = (uint32)stack;
// set the address to the function we want to run
m_State[0].eip = (uint32)func_ptr;
// interrupts enabled
m_State[0].eflags = 0x0200;
// set to runable
m_Status = RUNNABLE;
// add to scheduler
Scheduler::instance()->enqueue(this);
the important thing is:
Code: Select all
*--stack = (uint32)Scheduler::thread_finished;
that places the address of the thread_finished function in a spot on the stack so that when the outer most function returns, it just jumps to that which changes the thread to a FINISHED state, unblocks any waiting threads, and calls my yield function to continue execution.
then the scheduler wil actually delete the object next time it tries to schedule it because it is marked as finished.
no need for "reaper threads", or infinite loops to keep it all sane, just a return address
perhaps there is some advantage to these other techniques i dont see, if so please let me know.
proxy
Re:deleting a task
Posted: Thu Jan 08, 2004 3:03 pm
by Tim
A reaper thread is needed because as soon as the kernel frees the thread's kernel-mode stack, that memory is available for reuse. So the thread must not be current when its kernel-mode stack is freed.
There is the same problem with exiting a process: the kernel can't free the page directory while the process is current.
Re:deleting a task
Posted: Thu Jan 08, 2004 8:05 pm
by proxy
oh i agree it cannot be freed while it is currently in use, this is why i have my scheduler do the actual deleting, basically when it picks the next task, if it is in a "finished" state, it get's deleted and it picks again.
You might say, that this is inefficient because there is redundant thread selection, but compared to the amount of context switches, the number of delete ones hit is pretty rare.
i guess you could sort of call my scheduler my "reaper thread" in that sense, it is sort of doing the same thing.
proxy
Re:deleting a task
Posted: Fri Jan 09, 2004 1:20 am
by BI lazy
@pype: ok.
@proxy: The scheduler shouldn't have to do this. It sounds like too much overhead ere a new task is selected.
In my opinin it is way better to drop the task to a dedicated thread which takes it, triggers all the necessary clean up work (sends messages to other tasks...) and then removes it from the system. I also think it is not under all circumstances necessary to catch it in an endless loop after doing the exit system call - especially when the task is marked as not runnable or moved to a dedicated queue say "zombie tasks" which is kept by buffy the grim reaper thread.
Re:deleting a task
Posted: Fri Jan 09, 2004 5:58 am
by Slasher
Why no have system call, like task_destroy or something. Then the tasks can destroy themselves directly by calling it or indirectly by the stack return method.
I think a task or thread dedicated to destroying tasks is overkill.
After all it is just
close Files,release resources - memory,dedicated devices, and remove pcb from system.
Re:deleting a task
Posted: Fri Jan 09, 2004 7:31 am
by Tim
Code Slasher: The reaper thread is still necessary at least for the thread's kernel stack. This is because the ThrExitThread (in my case) system call runs in the context of the calling thread, which like any other interrupt uses the current thread's kernel stack. You can't free the kernel stack pages if the code that's doing the freeing is using them at the time.