1. Upon returning to user-space or returning from an interrupt, the need_resched flag is checked. If it is set, the kernel invokes the scheduler before continuing.
2. Process preemption
3. Running out of time slice
4. Waiting for event
5. Waiting for IO
6. In idle loop cpu_idle_loop() (from code sched/idle.c)
In short, user preemption can occur
1. When returning to user-space from a system call
2. When returning to user-space from an interrupt handler
Kernel preemption:
So when is it safe to reschedule? The kernel can preempt a task running in the kernel
so long as it does not hold a lock.That is, locks are used as markers of regions of nonpre-
emptibility. Because the kernel is SMP-safe, if a lock is not held, the current code is reen-
trant and capable of being preempted.
The first change in supporting kernel preemption was the addition of a preemption
counter, preempt_count , to each process’s thread_info .This counter begins at zero and
increments once for each lock that is acquired and decrements once for each lock that is
released.When the counter is zero, the kernel is preemptible. Upon return from interrupt,
if returning to kernel-space, the kernel checks the values of need_resched and
preempt_count . If need_resched is set and preempt_count is zero, then a more impor-
tant task is runnable, and it is safe to preempt.Thus, the scheduler is invoked. If
preempt_count is nonzero, a lock is held, and it is unsafe to reschedule. In that case, the
interrupt returns as usual to the currently executing task.When all the locks that the cur-
rent task is holding are released, preempt_count returns to zero.At that time, the unlock
code checks whether need_resched is set. If so, the scheduler is invoked.
In short, Kernel preemption can occur
1. When an interrupt handler exits, before returning to kernel-space
2. When kernel code becomes preemptible again
3. If a task in the kernel explicitly calls schedule()
4. If a task in the kernel blocks (which results in a call to schedule() )
Unlike softirqs, however, two of the same tasklets never run concurrently—although two different tasklets can run at the same time on two different processors
Recall that two tasklets of the same type do not ever run simultaneously.Thus, there is no need to protect data used only within a single type of tasklet. If the data is shared between two different tasklets, however, you must obtain a normal spin lock before accessing the data in the bottom half.You do not need to disable bottom halves because a tasklet never preempts another running tasklet on the same processor.
With softirqs, regardless of whether it is the same softirq type, if data is shared bysoftirqs, it must be protected with a lock. Recall that softirqs, even two of the same type, might run simultaneously on multiple processors in the system. A softirq never preempts another softirq running on the same processor, however, so disabling bottom halves is not needed.