By sameers on May 31, 2006
Solaris kernel is pre-emptible by default
It is the fact that Solaris kernel can be pre-empted at any point of time. To verify this, fortunately we had a systemcall which would cause kernel to loop in while(1) for ever. At the same time we had 2 CPU machine. we made that system call from the application which caused CPU 1 to loop for ever. Now we started a while(1) loop in the user land and associated \*real time\* priority with the process and requested the kernel to bind it to CPU 1 on which kernel was already looping in while(1). The moment we did this, system got hung. The caue of the hang was that the while(1) inside the kernel got \*pre-empted\* and was switched to CPU 2 and the CPU 1 started running \*user land while(1) with real time priority\* on CPU 1. This caused both the CPU to loop in while 1.
This makes clear that the Solaris kernel is pre-emptible between CPU's by default. Now there was a question that when kernel is looping on the CPU, who forced it to switch to different CPU. It was found that when we return from \*interrupt\* a check is made for pre-emption. If any higher priority thread(than the current thread) is runnable on the CPU, OS forces the current thread to switch to different. That's how kernel got switched to the other CPU.
TO summarise it -
1. Solaris kernel can be prempted it some higher priotiry thread(RT) is runnable on the same CPU.
2. To Avoid this, we have to specially place a request to the kernel to not to preempt when we are executing critical code.
3. If we are holding a spin lock in the kernel we wont get pre-empted.
A small question here that comes to my mind is that if there was only one CPU, what would have happened ? I'm not very sure that Solaris would comeback to user land if while(1) loop is started in the kernel. It was only because there were 2 CPU's on the system, kernel while(1) got switched to another CPU. To verify this we can have shell running with real time priority on single CPU machine. From this shell we can start same application that invokes systemcall which will start while (1) loop within the kernel. If we are able to comeback to the shell prompt, this will make sure that the kernel was preempted for higher priority process. If the above is TRUE, kernel is completely preemptible in following situations -
- Kernel code is executing without any lock held
Otherwise we can assume that there are pre-emption points in the Solaris kernel releasing locks etc., where the check is made to yield CPU.
It may happen that the kernel may be preempted while holding a lock. If a kernel control path is holding multiple locks, it may be forced to yield CPU when it releases very first lock with other locks held. To avoid this, we may explicitely set flags to not to yield the kernel.
Linux 2.4 on the other hand is non-preemptible by default. The kernel control path has to yield it self to giveup CPU or it preempts itself when it goes to sleep on some wait queue. Where as Linux 2.6 can be configured to be preemptible. While returning from interrupt/exception, we can check if scheduling is required to yield CPU to high priority task even if kernel was interrupted. If kernel code was holding spin lock or was inside scheduler or handling soft IRQ's, we won't preempt else we can. While releasing spin locks, we check if pre-emption is required. If there is any higher priority thread runable on the CPU.
Nornally, Linux while returning from the interrupt/exception, just checks if the CPU was running in kernel mode earlier to the event(from the CS register). If so, it would just continue to resume from where it had left the kernel. Even if the timer interrupt has occured and the time slice of the current process has elasped.
Attempt is made to make Monta vista Linux kernel fully pre-emptible.