xenomai4的dovetail学习(3)——自旋锁和远程调用

发布于:2025-03-01 ⋅ 阅读:(7) ⋅ 点赞:(0)


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)