为什么每个线程的preempt_count足够了

时间:2015-03-30 12:01:39

标签: multithreading linux-kernel scheduler

preempt_count变量跟踪每个CPU统计信息::

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

位0 - 7跟踪禁用内核抢占的次数。

如果非零,则为第8-15位,表示softirqs被拔掉了很多次。

第16 - 27位指定irq_enter的调用次数。它表示嵌套中断处理程序的数量。

我无法理解为什么preempt_count足够了 每个帖子。 当一个新的进程被安排时,当然位0-7将为零,否则意味着抢占被禁用并且不允许切换。但是8到27位呢。它们也会是0吗? 这是否意味着每当有进程调度调用时,preempt_count应该为0,因此不需要在不同进程的thread_info中复制其值以保持特定CPU上状态softirqs和irqs的跟踪? / p>

2 个答案:

答案 0 :(得分:1)

Linux禁止在中断时调度线程,这是一种约定,并且没有代码来实现这种约束。所以在这种约定下,新线程的preempt_count必须为零,并且不需要复制preempt_count。如果有人调用schedule在中断上下文中可能存在其他问题,例如,由于先前的中断已禁用中断,因此无法处理新的中断。

答案 1 :(得分:-1)

current_thread_info取决于架构。它指向内核堆栈的结束。在2.6之前的内核堆栈task_struct离开。但是在task_struct移动到slab并且thread_info替换了task_struct之后。每个进程都有thread_info,它位于该任务的内核堆栈的末尾。 current_thread_info()返回与arch相关的指针(根据堆栈指针和大小计算)。 Thread_info有preempt_count它是一个计数器。如果value为零,那么内核可以抢占(preempt_count + = SOFTIRQ_OFFSET - 禁用下半部分)。 preempt_count递增是锁定被保持并且如果释放锁定则递减。如果irq句柄完成,指令指针应该指向内核代码。内核应检查preempt_count是否为零,因此代码抢占是安全的,如果设置了相同thread_info的need_reshed。谢德勒应该开始更重要的任务。如果preempt_count非零 - 抢占不安全,下一次执行应指向中断的同一任务。只有当所有锁都可以通过当前任务和preempt_count == 0释放时,所以代码可以通过抢占安全。再次need_recshed检查。

另一方面,preempt_count()函数可以非常有用preempt_disable(),preempt_enable() - 两个嵌套函数。 Preemption函数可以保护每个cpu变量免受来自多个使用相同per_cpu变量的任务的并发访问。重要的是,只有一个任务应该使用共享的per_cpu变量(在meedle中它可以被其他任务更改)并且应该禁用抢占。前置放大器功能是嵌套的,因此我们可以使用preempt_count()。 in_atomic基于preempt_count(),实际上它解释了为什么它不是很好的函数。