2017-03-03
Unfortunately before the introduction of the process scheduling article, although involved in the kernel preemption, but not in-depth introduction to it, today a little summary of the kernel preemption.
Kernel preemption reduces the latency of response to an event to some extent, which is also the purpose of kernel preemption being introduced. In the previous kernel, in addition to displaying some of the points called the System scheduler, the kernel is not allowed to interrupt other places, if the kernel is doing some more complex work, it will cause some rush to deal with the matter can not be timely response. The kernel preemption is essentially also for the current process (it is not known whether this is appropriate) because the kernel is serving the user program, in other words, it does not actively perform an action. Here the kernel preemption, the focus is that when the user program requests the kernel service, the CPU switches to the kernel state during the execution of a system service, is preempted.
Of course, even if kernel preemption is supported, it is not always possible to consider the protection of critical areas. Similar to a multiprocessor architecture, if process a falls into kernel mode to access a critical resource, and during access, process B also accesses the critical section, and if this preemption is allowed, then a critical section is re-entered. Therefore, the kernel preemption needs to be forbidden when accessing the critical resource, and the kernel preemption should be turned on in the critical section.
In order to support kernel preemption, there is a preempt_count field in the thread_info structure of the process structure to record whether the current kernel (activity) can be preempted. When the value is 0 o'clock, it is allowed to be preempted, otherwise it is not allowed.
There are several functions for kernel preemption:
#define Do { inc_preempt_count (); while (0) #define Do { preempt_enable_no_resched (); Barrier (); while (0)
#define INC_PREEMPT_COUNT () add_preempt_count (1) #define DEC_PREEMPT_COUNT () sub_preempt_count (1)# define Add_ Preempt_count (val) do {preempt_count () + = (val);} while (0) # define Sub_preempt_count (val) do {Preempt_ Count ()-= (val); } while (0)
The above two functions are forbidden and enable kernel preemption. is actually a macro definition. Preventing kernel preemption is essentially adding 1 to the Preempt_count field in the thread_info structure of the current process, while enabling kernel preemption is minus 1. Note that when kernel preemption is enabled, the Preempt_check_ is called Resched Check whether the current need to reschedule, which is also a macro, implemented as follows:
#define Do { if (Unlikely (Test_thread_flag (tif_need_resched))) while (0 )
Is that after the kernel preemption is turned on, check if there is a more important process waiting for execution, if any, then call the Preempt_schedule function to execute the schedule, it is shown that after the opening of the kernel preemption, it is a time to trigger the kernel preemption. The scheduling process itself is not allowed to be preempted. The Preempt_schedule function is as follows
Asmlinkagevoid__sched Notrace Preempt_schedule (void){ structThread_info *ti =Current_thread_info (); /** If There is a non-zero preempt_count or interrupts be disabled, * we do not want to preempt the current TA Sk. Just return: */ if(Likely (Ti->preempt_count | |irqs_disabled ())) return; Do{add_preempt_count_notrace (preempt_active); __schedule (); Sub_preempt_count_notrace (preempt_active); /** Check again in case we missed a preemption opportunity * between schedule and now. */barrier (); } while(need_resched ());}
If the preemption counter is not 0 or is currently in the shutdown hardware interrupt state, it cannot be preempted.
Also, after the hardware interrupt request is processed, it is possible to check the dispatch identity and the preemption counter.
Resources:
1. Linux 3.10.1 kernel
2. In-depth Linux kernel architecture
Kernel preemption under Linux