spinlock
Dovetail引入了两种自旋锁类型:
- hard spinlock:hard spinlock操作 CPU 中断掩码,并且在加锁/解锁操作中不会影响内核抢占状态(preempt)。硬旋锁不受虚拟中断掩码的影响,因此可以用于与带外活动进行序列化,包括来自内带内核代码的活动。无论如何,这些临界区应该尽可能短,以保持低延迟。
- hybrid spinlock:hybrid spinlock用于保护对 IRQ 描述符(struct irq_desc::lock)的访问,以便我们可以保持通用 IRQ 核心的原始加锁方案不变,用于处理带外中断。在pipeline中只是hard spinlock,在inband中还会额外禁用抢占,都也要使用hard spinlock。这种类型的锁不适合在任何其他情况下使用。
static inline void hybrid_spin_lock(struct raw_spinlock *rlock)
{
if (in_pipeline())
hard_lock_acquire(rlock, 0, _THIS_IP_);
else
__hybrid_spin_lock(rlock);
}
/*
* A hybrid spinlock behaves in different ways depending on the
* current interrupt stage on entry.
*
* Such spinlock always leaves hard IRQs disabled once locked. In
* addition, it stalls the in-band stage when protecting a critical
* section there, disabling preemption like regular spinlocks do as
* well. This combination preserves the regular locking logic when
* called from the in-band stage, while fully disabling preemption by
* other interrupt stages.
*
* When taken from the pipeline entry context, a hybrid lock behaves
* like a hard spinlock, assuming that hard IRQs are already disabled.
*
* The irq descriptor lock (struct irq_desc) is a typical example of
* such lock, which properly serializes accesses regardless of the
* calling context.
*/
void __hybrid_spin_lock(struct raw_spinlock *rlock)
{
struct hybrid_spinlock *lock;
unsigned long __flags;
if (running_inband())
preempt_disable();
__flags = hard_local_irq_save();
hard_lock_acquire(rlock, 0, _RET_IP_);
lock = container_of(rlock, struct hybrid_spinlock, rlock);
lock->hwflags = __flags;
}
Preempt(抢占)与硬件中断不一样。在某些情况下,抢占和硬件中断开关会同时使用。例如,在 spin_lock_irq() 和临界区:
- Preempt:抢占机制通常用于调度器中,以确保高优先级任务能够及时运行。在 Linux 内核中,抢占是通过 preempt_count 来控制的。当 preempt_count 为 0 时,任务是可抢占的;当 preempt_count 大于 0 时,任务是不可抢占的。用于临界区保护。在访问共享资源时,防止任务被抢占。
- 硬件中断:用于控制 CPU 是否响应硬件中断请求(IRQ)。当硬件中断被禁用时,CPU 不会响应外部硬件设备的中断请求。在处理硬件中断时,禁用中断以防止中断嵌套,确保中断处理的原子性。
Lockdep
锁验证器会自动协调实际和虚拟中断状态,因此它可以为在带内和带外上下文中定义的锁构造提供正确的诊断。这意味着当启用 LOCKDEP 时,硬和混合自旋锁包含在验证集中。然而,当启用 LOCKDEP 时,延迟数据可能会非常糟糕,因为锁验证器可能需要在 CPU 禁用中断的情况下执行大量工作,以强制执行临界区。
LOCKDEP 是 Linux 内核中的一个调试工具,用于检测和分析多线程并发时可能出现的锁相关问题。它可以帮助开发人员发现潜在的死锁、竞争条件和其他与锁有关的并发问题。
远程调用
smp_call_function_oob用于在目标CPU上调度一个函数调用。其功能与常规的smp_call_function_single()函数在语义上等价,但不同之处在于,在带外(out-of-band)阶段运行回调函数,并且关闭硬中断(hard irqs off)。
void smp_call_function_oob(int cpu, smp_call_func_t func, void *info, bool wait)