5.14:
preempt_count 是 Linux 内核中的一个线程级别变量,因为它用于跟踪每个独立线程的抢占状态,确保关键操作的原子性。
和之前的印象有些不太一样,原来一直以为是CPU level的。需要修改。
preempt_count 是一个计数器,其主要目的是:
控制内核抢占: 当 preempt_count 的值大于零时,表示当前线程处于一个不可被抢占的临界区。这意味着调度器不能在此时中断当前线程并切换到另一个线程。
保护临界区: 内核中的许多操作(例如,持有自旋锁、处理中断、访问共享数据结构)需要原子性。通过在进入这些临界区时增加 preempt_count,并在退出时减少它,可以防止在这些关键操作中间发生抢占,从而避免数据损坏和竞态条件。
preempt_count 必须是线程级别的变量,原因如下:
独立的抢占状态: 每个线程都有其自己的执行路径和可能进入的临界区。一个线程可能正在执行一个需要禁用抢占的关键操作,而另一个线程则可能处于可以安全抢占的状态。如果 preempt_count 是全局的,那么一个线程禁用抢占会影响所有其他线程,导致不必要的延迟和性能问题。
上下文切换的需要: 当内核进行上下文切换时,它会从一个线程切换到另一个线程。每个线程的 preempt_count 值是其执行上下文的一部分。通过将其存储在 thread_info 结构中(如您提供的代码片段 current_thread_info()->preempt_count 所示,current_thread_info() 返回当前线程的 thread_info 结构),可以确保在线程切换时,每个线程都能恢复其正确的抢占状态。
避免竞态条件: 如果 preempt_count 是一个全局变量,多个 CPU 上的不同线程会同时尝试修改它,这将引入复杂的同步问题和竞态条件。将其作为线程局部变量,每个线程在自己的私有副本上操作,从而避免了这些问题。
简而言之,preempt_count 是线程级别的,以确保每个线程能够独立地管理其自身的抢占状态,从而在保证内核操作正确性的同时,最大化系统的并发性和响应性。
c
static __always_inline volatile int *preempt_count_ptr(void)
{
return ¤t_thread_info()->preempt_count;
}