I guess both schemes are just different ways to make sure that things that need to be done before a task switch are done before a task switch. My scheme might give better performance in some cases, while your scheme might be simpler in some cases.Colonel Kernel wrote:What is the advantage of your scheme...? Conversely, what is the disadvantage of my scheme? For that matter, which is more conventional?
As for which is more conventional, I've got no idea - I've never actually studied any other OS properly - I just do what I think is best at the time until I find a better way, which isn't recommended but after many years it can work (if you've got many years to spare ).
Colonel Kernel wrote:Did allowing nested interrupts fix this? If so, how? I briefly forgot that the kernel itself ought to deal with the timer in its own ISRs.At the time I had (unrelated) design problems with level triggered interrupts, and (more recently) interrupt latency problems that caused IRQ8 to be missed on some computers which led to the OS locking up/waiting forever (although this could be attributed to setting the RTC periodic timer's frequency too fast).
Allowing nested interrupts didn't fix the IRQ8 problems, as the kernel allows IRQ8 to be handled immediately (unless interrupts are disabled) anyway. The problem was caused by the high frequency of the RTC periodic interrupt combined with disabling interrupts for too long. The only place the kernel disables interrupts for more than a few instructions is during the "find a next thread to run" code and the "switch to the selected thread" code.
The "find the next thread to run" code was the main problem, as it used "O(2 * N)" algorithms where the more threads there are the longer it disables interrupts for. My plan was to change all scheduling algorithms to "O(1)" and make the "switch to the selected thread" code interruptable, but at the time I was in the middle of other things and chose to reduce the frequency of the RTC periodic interrupt instead.
I tried fixing the scheduler properly afterwards, but it's a complex thing (multi-CPU, domains and sub-domains, CPU affinity, 4 policy levels with different scheduling algorithms for each policy, etc) and it's not seperated from other parts of the kernel very well. This is one of the reasons I'm converting the kernel into seperate modules (so the scheduler itself is a seperate binary with a clearly documented interface between it and other parts of the kernel, and can be replaced with a different "scheduler module" during boot).
It's a little funny, because "clearly seperated parts" was one of the reasons I chose not to write a monolithic kernel - to have the same problem within a micro-kernel was a surprise (my previous kernels were single-CPU only, which is much much simpler).
Cheers,
Brendan