As part of reviving SA, I'm re-adding all of the kernel infrastructure we ripped out. In doing this, I looked at re-adding the preempt(int more) code we had. However, I have serious questions about it. Like why do it? We call preempt() when we want to give the scheduler a convenient moment to run something else. In -current, we do this at some times when we realize another thread/sub-system has requested we do this (curcpu()->ci_want_resched set for instance). I believe we send a BLOCKED upcall to the process because this thread of execution has stopped. The thing however is we send the upcall when mi_switch() returns (and in the case when we actually ran a different thread). So we send the BLOCKED upcall _after_ we were blocked, not before/durring like we do for blocking. Among other things, we send the BLOCKED upcall after we not only hop away, but after we hop back. So we have in effect UNBLOCKED at the time when we send the BLOCKED upcall. Further, we aren't blocked. I understand the BLOCKED upcall to be a way for libpthread to schedule something else on the virtual CPU that we were running on. However a call to mi_switch() does not represent a point at which libpthread can schedule something else on our virtual CPU - our thread is still runable in the eyes of the kernel scheduler, so it will hop back to it when it decides to. And we generate an UNBLOCKED upcall when we get back to userland. Most importantly, we don't offer a new lwp to userland on which it can run threads. So the net effect will be we pull the user thread that triggered code that blocked off of the (front of the) run queue, put it on the back of the run queue, then go back to running. I note that there are/were only two places in the code that call preempt(0), sys_sched_yield() and midiwrite(). I really don't understand why midiwrite() calls preempt(0) other than probably the fact that chap wasn't sure what to do when he added the code in 2006. I think sched_yield is the one place where we would want to do this rescheduling. However I think it's much cleaner on the whole kernel to just have sched_yield just manually inject a BLOCKED upcall. When we get back to userland we will auto-generate an unblocked upcall too, so we will rattle the userland run queues. Intercepting sched_yield() in userland is a better way to go, but this branch is about compatability at this point. :-) I realize I have been somewhat thinking out loud; I now better understand the problem than I did when i started writing this EMail. However anyone have any thoughts on this? Take care, Bill
Attachment:
pgpL0yMI8xDHJ.pgp
Description: PGP signature