Korona wrote:
That's true if you only ever want to restore the context by returning to the caller. For example, in this design, dispatching signals to a preempted user-space threads is not possible anymore. This is not necessarily a problem (they can still be dispatched after returning to the caller), you might want to thing about whether you want to be able to introspect (or modify) registers of preempted threads.
This doesn't seem to make sense to me. The context_switch() function only has one caller: the kernel scheduler. You can simply record signals in the ThreadBlock structure of the target thread and check for them in the scheduler after context_switch() returns (or anywhere else that is convenient). Register manipulations required for signal handling would be done when transitioning back from kernel space to user space (or if you are not going back to user mode, you handle them right then).
Korona wrote:
You might also want to take into account that not all interrupts will run from per-thread kernel stacks and you might still want to context switch from those, so it can make sense to store the preempted state in a struct (with enough space for all registers) instead of the stack. You can still avoid saving all registers when the context switch does run from a per-thread kernel stack.
I saw your other post about NMI / MCE... Does it even make sense to do a context switch (calling the scheduler) inside a NMI/MCE interrupt handler?
Korona wrote:
Last but not least, you can think of designs that avoid per-thread kernel stacks altogether. This is something I would not recommend: It makes blocking in the kernel much harder: Basically all locations where a thread can block must be enumerated in some way because you need to be able to somehow save the state at that point. That is harder than it sounds - for example, kernels might sometimes want to block until enough memory is available to satisfy an internal allocation. That might be desirable in context where an allocation must not fail because there is no meaningful way to return failure to userspace, e.g., in some asynchronous driver operation.
I agree with this, but the OP explicitly stated that he is thinking of switching stack between processes (threads).