User Preemption
When the kernel is about to return to the user space, if need_resched is set, schedule () will be called and user preemption will occur. When the kernel returns to the user space, it knows that it is safe, because since it can continue to execute the current process, it can certainly select a new process for execution. Therefore, the kernel checks the need_resched flag whether it is returned from the interrupt handler or after the system call. If it is set, the kernel selects another (more suitable) process for running. The Code returned from the interrupt handler or system call is related to the architecture and is implemented in the entry. s file using the assembly language.
In short, user preemption occurs in the following situations:
Return the user space from the system call;
Return the user space from the interrupt handler;
Kernel preemption
Unlike most other UNIX variants and most other operating systems, Linux fully supports kernel preemption. In a kernel that does not support kernel preemption, the kernel code can be executed until it is completed. That is to say, the Scheduler cannot reschedule a kernel-level task while it is being executed. All tasks in the kernel are scheduled in a collaborative manner and cannot be preemptible. The kernel code is always executed until it is completed (returned to the user space) or obviously blocked. In the kernel version 2.6, the kernel introduced preemption. Now, as long as rescheduling is secure, the kernel can seize the tasks being executed at any time.
So when is rescheduling secure? As long as no lock is held, the kernel can be preemptible. The identifier of the domain in which the lock is not preemptible. Because the kernel supports SMP, if no lock is held, the code being executed can be re-imported, that is, it can be preemptible.
The first change to support kernel preemption is the introduction of the preempt_count counter for thread_info of each process. The initial value of the counter is 0. When the lock is used, the value is 1. When the lock is released, the value is reduced by 1. When the value is 0, the kernel can perform preemption. When the kernel space is returned from the interrupt, the kernel checks the need_resched and preempt_count values. If need_resched is set and preempt_count is 0, it indicates that a more important task needs to be executed and can be safely preemptible. Then, the scheduler will be called. If the value of preempt_count is not 0, the current task holds a lock, so preemption is insecure. In this case, the current execution process is directly returned from the interrupt as usual. If the locks held by the current process are released, the preempt_count value is 0 again. At this time, the code for releasing the lock checks whether need_resched is set. If yes, the scheduler will be called. Some kernel code needs to allow and disable kernel preemption, which is not discussed here.
If the process in the kernel sink is blocked, or it explicitly calls schedule (), kernel preemption also occurs. Kernel preemption in this form is always supported. Because no additional logic is required to ensure that the kernel can be securely preemptible. If the kernel code explicitly calls schedule (), it should be clear that it can be safely preemptible.
Kernel preemption occurs in:
1. When the slave interrupt handler is being executed and the kernel space is returned (the premptcount flag must be 0 and need_resched is set );
2. When the kernel code is once again preemptible, such as unlocking and enabling soft interruptions;
3. If a task in the kernel explicitly calls schedule ();
4. If the task in the kernel is blocked (this also causes schedule () to be called ())
User Preemption
When the kernel is about to return to the user space, if need_resched is set, schedule () will be called and user preemption will occur. When the kernel returns to the user space, it knows that it is safe, because since it can continue to execute the current process, it can certainly select a new process for execution. Therefore, the kernel checks the need_resched flag whether it is returned from the interrupt handler or after the system call. If it is set, the kernel selects another (more suitable) process for running. The Code returned from the interrupt handler or system call is related to the architecture and is implemented in the entry. s file using the assembly language.
In short, user preemption occurs in the following situations:
Return the user space from the system call;
Return the user space from the interrupt handler;
Kernel preemption
Unlike most other UNIX variants and most other operating systems, Linux fully supports kernel preemption. In a kernel that does not support kernel preemption, the kernel code can be executed until it is completed. That is to say, the Scheduler cannot reschedule a kernel-level task while it is being executed. All tasks in the kernel are scheduled in a collaborative manner and cannot be preemptible. The kernel code is always executed until it is completed (returned to the user space) or obviously blocked. In the kernel version 2.6, the kernel introduced preemption. Now, as long as rescheduling is secure, the kernel can seize the tasks being executed at any time.
So when is rescheduling secure? As long as no lock is held, the kernel can be preemptible. The identifier of the domain in which the lock is not preemptible. Because the kernel supports SMP, if no lock is held, the code being executed can be re-imported, that is, it can be preemptible.
The first change to support kernel preemption is the introduction of the preempt_count counter for thread_info of each process. The initial value of the counter is 0. When the lock is used, the value is 1. When the lock is released, the value is reduced by 1. When the value is 0, the kernel can perform preemption. When the kernel space is returned from the interrupt, the kernel checks the need_resched and preempt_count values. If need_resched is set and preempt_count is 0, it indicates that a more important task needs to be executed and can be safely preemptible. Then, the scheduler will be called. If the value of preempt_count is not 0, the current task holds a lock, so preemption is insecure. In this case, the current execution process is directly returned from the interrupt as usual. If the locks held by the current process are released, the preempt_count value is 0 again. At this time, the code for releasing the lock checks whether need_resched is set. If yes, the scheduler will be called. Some kernel code needs to allow and disable kernel preemption, which is not discussed here.
If the process in the kernel sink is blocked, or it explicitly calls schedule (), kernel preemption also occurs. Kernel preemption in this form is always supported. Because no additional logic is required to ensure that the kernel can be securely preemptible. If the kernel code explicitly calls schedule (), it should be clear that it can be safely preemptible.
Kernel preemption occurs in:
1. When the slave interrupt handler is being executed and the kernel space is returned (the premptcount flag must be 0 and need_resched is set );
2. When the kernel code is once again preemptible, such as unlocking and enabling soft interruptions;
3. If a task in the kernel explicitly calls schedule ();
4. If the task in the kernel is blocked (this also causes schedule () to be called ())