(Hello! First post!)
I'm trying to implement preemptive multitasking for the first time, but I've hit a bit of a snag with how x86 does interrupt handling. My OS has a kernel process in addition to all the user processes, which the scheduler treats exactly the same as any other task except that it happens to be in ring 0. The problem, though, is that interrupts in x86 only push SS:ESP and load the new stack from the TSS if there's a privilege change from user to kernel, and iret only loads SS:ESP from the stack when going from kernel to user. This means there's a misalignment when switching between the kernel process and a user process or vice versa. I've come up with a partial solution that involves manually switching stacks, copying between them, etc., but it has to handle four different cases (kernel to user, user to kernel, user to user, and kernel to kernel) so it's a bit convoluted and I haven't gotten it to work yet, and I can't help but think there's probably an easier way to do this. (Or maybe there isn't and I just have to suffer through getting this to work...)
I've searched around a little bit but haven't found anything on my own about how to handle this, but I'm sure it's something anyone else who's also made kernel processes has had to work around, so I'd like to hear what the recommended way of dealing with this is.
Process switching between kernel and user processes
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Process switching between kernel and user processes
It sounds like you don't have enough stacks. The typical kernel design has one kernel stack per thread. Any threads that run in ring 3 will have an additional stack in ring 3, but that's irrelevant to your multitasking code - all you need to do to switch tasks is switch kernel stacks.
This wiki article does a pretty good job of explaining things, though keep in mind the example code is only an example - you shouldn't blindly trust it to be correct or ideal for your OS. (And, of course, you might not want the typical kernel design. But in that case, you should still learn how the usual design works before you try to come up with something else.)
This wiki article does a pretty good job of explaining things, though keep in mind the example code is only an example - you shouldn't blindly trust it to be correct or ideal for your OS. (And, of course, you might not want the typical kernel design. But in that case, you should still learn how the usual design works before you try to come up with something else.)
Re: Process switching between kernel and user processes
I posted this quite a while ago and had to wait for it to be approved since it was my first post, but fortunately this isn't still an issue I'm working on! Originally I was doing a really basic microkernel-esque design that only had one kernel stack, as most system calls would just be quick non-interruptible message passing. (Probably should have clarified this design decision in the original post.) I did eventually write some more clever assembly code in the interrupt handler that solved the original problem I was having and worked fine, though since then I have actually switched to the kernel stack per task design, so this isn't relevant anymore.