4

I am looking at scheduler code in Linux:

if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
    if (unlikely(signal_pending_state(prev->state, prev))) {
        prev->state = TASK_RUNNING;
    } else {
        deactivate_task(rq, prev, DEQUEUE_SLEEP);
        prev->on_rq = 0;

As I understand, if the prev task is uninterruptible, this code will deactivate the task (and remove from runqueue) provided

preempt_count() & PREEMPT_ACTIVE == 0

Can someone explain to me what is preempt_count in thread_info for and when will this condition met or not?

red0ct
  • 4,840
  • 3
  • 17
  • 44
Saksham Jain
  • 537
  • 3
  • 14
  • preempt_counts upper bits are used for things like IRQ counts, one of the bits is used to signal if PREEMPT is active, which is what the line is checking for. – Secto Kia Oct 30 '16 at 22:28
  • But I thought schedule() couldn't be called in IRQ handler as schedule can sleep. (You are only preempted by interrupt right? Otherwise you would be schedule out right?) – Saksham Jain Oct 31 '16 at 10:16

1 Answers1

1

preempt_count is the counter used by preempt_disable() and preempt_enable(), which enables their nested use. Higher order bits of preempt_count are used for hardirq and softirq counters, an NMI bit and a PREEMPT_ACTIVE bit. These are defined in include/linux/preempt_mask.h. In x86 architectures a PREEMPT_NEED_RESCHED bit is also used in preempt_count, for optimization of deciding to reschedule.

Now, I am not clear on the exact need for the PREEMPT_ACTIVE bit in preempt_count. In kernel version 3.17, which I have worked on, PREEMPT_ACTIVE is set in preempt_count exactly before calling __schedule() and reset immediately after the call, in all cases, except when it is called from schedule(). This would mean, inside __schedule(), PREEMPT_ACTIVE is set in preempt_count, when __schedule() was called because of kernel preemption, i.e., not intentionally for some other OS functionality, which would use schedule(). What would such "other OS functionality" be varies, depending on whether you build the kernel with CONFIG_PREEMPT, CONFIG_PREEMPT_VOLUNTARY, or CONFIG_PREEMPT_NONE, but it includes explicit blocking on a mutex.

kavadias
  • 1,074
  • 10
  • 15