2
votes

preempt_count variable keeps track of per CPU statistics::

 static __always_inline int preempt_count(void)
    {
            return current_thread_info()->preempt_count;
    }

Bits 0 - 7 keeps track of how many times kernel preemption is disabled.

Bits 8 - 15 if non-zero, means softirqs are disbaled that number of times.

Bits 16 - 27 specifies how many calls of irq_enter happened. It mean the number of nested interrupt handlers.

I am not able to comprehend why it is sufficient for preempt_count to be per thread. When a new process would be scheduled, off course bit 0-7 will be zero, otherwise it means preemption is disabled and switch is not allowed. But what about bits 8 - 27. Will they be 0 too? Does it mean that whenever there is a process schedule call, at that time preempt_count should be 0 and hence its value does not need to be copied across thread_info of different processes to keep the track of the status softirqs and irqs on a particular CPU?

2
Actually "sleeping" is forbidden when thread is in interrupt (see might_sleep() ). - myaut
so, you mean if in_interrupt() is true, process cannot be scheduled? So, indeed preempt_count is 0 at the time of actual schdule? It will be great if you can point me to the relevant code which does this check. - ashish

2 Answers

1
votes

Linux forbids thread being scheduled when in interrupt,this is a convention and there is no code to implement this restraint.So under this convention the preempt_count of new thread must be zero and there is no need copy preempt_count.If somebody call schedule in interrupt context there may be other problem for example new interrupt can't be processed because the previous interrupt has disabled interrupt.

-1
votes

current_thread_info is architecture dependent. It point to end of kernel stack. Before 2.6 at the end of kernel stack task_struct leave. But after task_struct move to slab and thread_info replaced task_struct. Each process have thread_info that lie in the end of kernel stack for that task. current_thread_info() return arch dependent pointer (calculate based on stack pointer and size). Thread_info have preempt_count it is a counter. If value is zero so kernel can be preempt (preempt_count += SOFTIRQ_OFFSET - disable bottom half). preempt_count incremented is lock is held and decremented if lock is freed. If irq handle finished and instruction pointer should point kernel code. Kernel should check if preempt_count is zero so code preemption is safe, also if need_reshed from the same thread_info is set. Sheduler should be start more important task. If preempt_count non zero - preemption not safe and next execution should be point to the same task that was interrupt. Only when all locks will be free by current task and preempt_count == 0 so code can by preempt safe. And again need_recshed check.

In other hand preempt_count() function can be very help full with preempt_disable(), preempt_enable() - two nested function. Preemption function can protect per cpu variable from concurrent access from more than one task that use the same per_cpu variable. It is important that only one task should work with shared per_cpu variable (in the meedle it can be changed by other task) and preemption should be disable. Preamption function is nested so we can use preempt_count(). in_atomic based on preempt_count() and actually it explain why it is not very good function.