Page 1 of 1

Terminating current task

Posted: Thu Jun 23, 2016 3:17 pm
by glauxosdever
Hi,


I am not really sure how should I implement current thread termination. The steps needed to be done are (in a random order):
  • Remove the thread structure from the thread list.
  • Free the thread structure and the stack of this thread.
  • Switch to another thread.
The problem arises when trying to design this. When I free the thread structure and the stack of the thread before I switch to the next thread, then it will crash because the stack will be not present. When I switch to the next thread before I free the thread structure and the stack of the thread, then freeing will never be run, since the other thread will not know that something irrelevant to itself needs to be cleaned. Maybe I should have a thread dedicated to freeing stacks and thread structures (though I would prefer having as less as possible worker threads)?

It would be nice if anybody enlightened me on this matter.


Thanks in advance,
glauxosdever

Re: Terminating current task

Posted: Thu Jun 23, 2016 3:19 pm
by mariuszp
I just have a special thread called a system management thread, and when a thread wants to exit, it puts its thread description onto a queue for the SMT, and the SMT is responsible for then removing the (now sleeping) terminating thread from the process list, releasing its stack, etc. The SMT never exits so the problems you've describe cannot occur.

Re: Terminating current task

Posted: Thu Jun 23, 2016 3:30 pm
by mariuszp
My apologies, I didn't notice the note about how you prefer less worker threads. Here's another solution, which may or may not work depending on your design. This assumes that your kernel stacks are allocated on the kernel heap.

1. ensure that the handle of the thread description, and the stack base, are placed in registers.
2. disable interrupts
3. remove the thread from the queue.
4. free the thread description.
5. free the stack, by marking its heap block as free (without actually using the stack to do this; in my case this would work since the block header, which stores whether or not the block is free, is placed right before the start of the block, so it's just a constant offset).
6. switch to the next process without using the stack; this includes actually jumping onto another thread's stack.
7. you may now safely enable interrupts, and the thread was removed :)

if your stack is allocated not on the kernel heap, but as a list of pages, then you'd have to unmap the pages, again using only registers, and not the stack.

Re: Terminating current task

Posted: Thu Jun 23, 2016 3:48 pm
by Boris
Hi,
If you can, do not allocate kernel stacks in the kernel heap.
Using pages to allocate stack gives you the opportunity to set up non present " guard pages". Small stack overflow ( less than a page size) will be caught by page faults, instead of corrupting the kernel heap,which can be catastrophic

Re: Terminating current task

Posted: Thu Jun 23, 2016 11:45 pm
by glauxosdever
Hi,


It seems that not having a worker thread is much more complex and involves doing tricks that are not straightforward for code readers, though it would be probably easier to achieve it if my OS was written in assembly for the whole part.

Maybe I will reconsider not liking worker threads (though I will definitely think about it).


Regards,
glauxosdever

Re: Terminating current task

Posted: Fri Jun 24, 2016 12:08 am
by MollenOS
So how I solved thread termination;

1. Thread calls ThreadingExit
2. Thread marks itself with a flag that indicates that it's done and needs cleanup
3. Thread yields control instantly after this
4. Scheduler sees the current thread for the current cpu is done, removes it from thread list, adds it to cleanup list and signals to the garbage collector thread (which sleeps when np cleaning is needed) that new cleanup is possible.
5. Scheduler gets a new thread

To be honest you only need one worker thread, and that worker thread can be kept off scheduling when no cleaning is needed, thus making it pretty efficient anyway.

Re: Terminating current task

Posted: Fri Jun 24, 2016 12:41 am
by glauxosdever
Hi,


This looks as a more convenient way, although I will let the scheduler clean up the thread information when it sees that "done" is set to true. I might change it later.

Thank you all for your ideas!


Regards,
glauxosdever

Re: Terminating current task

Posted: Fri Jun 24, 2016 2:39 am
by MollenOS
That is not possible, the threads stack is in use even in the scheduler untill the scheduler has actually switched tasks. You can't clean the thread untill you have switched away from its context

Re: Terminating current task

Posted: Sat Jun 25, 2016 3:39 pm
by Rusky
Unix leaves old threads as "zombies" until their parent threads call wait() on them, at which point their resources can be freed from there. This gives parents a chance to retrieve the child's exit status, etc.

If you don't want to leave anything laying around for parent threads to pick up with a wait()-like call, you can just switch to the next thread before freeing the old one's resources.

Re: Terminating current task

Posted: Sun Jun 26, 2016 12:33 am
by xenos
Another option (the one I am using in my kernel) is that threads don't have their own kernel stacks. In this approach, kernel stacks are per CPU, not per thread. That means that interrupts and syscall entries must be designed differently, as the thread's data such as register values is not saved on the kernel stack, but in some data structure belonging to the thread. But it makes it easier to terminate a thread. Since the kernel stack is per CPU, it is never freed, and just stays in use while being in kernel mode. The structures holding the thread's data can simply be freed, because they are not used by anything while being in kernel mode (they are only written on kernel entry and read on exit, to restore the state of the thread chosen to run).