Zephyr spinlock

SMP 与自旋锁

  • SMP 即对称多处理技术,在多核CPU上,各CPU之间共享内存和其他资源,但是只有一个操作系统,操作系统将各个任务均匀的分配该多个CPU执行,从而极大的提高系统的并行处理能力。

  • 由于多个CPU之间的内存是共享的,当CPU使用共享资源时需要通过互斥机制获得其使用权,实现其互斥的方式有两种,一种是互斥锁,另一种是自旋锁,两者在同一时间都只能一个持有者,但是在工作方式上有很大区别,互斥锁在获取锁时如果发现资源不可用时会使调用线程进入睡眠,而自旋锁不同,获取互斥锁失败时会在原地等待资源可用,不会使调用线程进入睡眠。

  • 单核计算机系统中多个进程访问同一个共享资源时通过屏蔽中断实现互斥,但是在多核计算机系统中,该方式不再有效,屏蔽中断只是让当前CPU不再响应中断请求,但是其他CPU仍然可以响应中断,为此引入了互斥锁,当系统中存在多个CPU时,竞争自旋锁的CPU首先屏蔽中断,然后通过自旋竞争获得共享资源的使用权,而竞争失败的CPU需要等待自旋锁被释放重新进行竞争使用权。

  • 自旋锁适用于锁使用者持锁时间比较短的情况,正是由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。

spinlock 加锁

static ALWAYS_INLINE k_spinlock_key_t k_spin_lock(struct k_spinlock *l)
{
	ARG_UNUSED(l);
	k_spinlock_key_t k;

	/* 关中断 */
	k.key = arch_irq_lock();

#ifdef CONFIG_SPIN_VALIDATE
	/* 确认当前CPU未获取到互斥锁 */
	__ASSERT(z_spin_lock_valid(l), "Recursive spinlock %p", l);
# ifdef CONFIG_KERNEL_COHERENCE
	__ASSERT_NO_MSG(z_spin_lock_mem_coherent(l));
# endif
#endif

#ifdef CONFIG_SMP
	/* 自旋等待锁可用,获取失败继续尝试直到成功 */
	while (!atomic_cas(&l->locked, 0, 1)) {
	}
#endif

#ifdef CONFIG_SPIN_VALIDATE
    /* 设置自旋锁持有持有线程和持有CPU */
	z_spin_lock_set_owner(l);
#if defined(CONFIG_SPIN_LOCK_TIME_LIMIT) && (CONFIG_SPIN_LOCK_TIME_LIMIT != 0)
	l->lock_time = sys_clock_cycle_get_32();
#endif /* CONFIG_SPIN_LOCK_TIME_LIMIT */
#endif/* CONFIG_SPIN_VALIDATE */
	return k;
}

spinlock 解锁

static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l,
					k_spinlock_key_t key)
{
	ARG_UNUSED(l);
#ifdef CONFIG_SPIN_VALIDATE
	/* 确认锁的持有者为当前CPU和当前线程 */
	__ASSERT(z_spin_unlock_valid(l), "Not my spinlock %p", l);

#if defined(CONFIG_SPIN_LOCK_TIME_LIMIT) && (CONFIG_SPIN_LOCK_TIME_LIMIT != 0)
	uint32_t delta = sys_clock_cycle_get_32() - l->lock_time;

	__ASSERT(delta < CONFIG_SPIN_LOCK_TIME_LIMIT,
		 "Spin lock %p held %u cycles, longer than limit of %u cycles",
		 l, delta, CONFIG_SPIN_LOCK_TIME_LIMIT);
#endif /* CONFIG_SPIN_LOCK_TIME_LIMIT */
#endif /* CONFIG_SPIN_VALIDATE */

#ifdef CONFIG_SMP
	/* Strictly we don't need atomic_clear() here (which is an
	 * exchange operation that returns the old value).  We are always
	 * setting a zero and (because we hold the lock) know the existing
	 * state won't change due to a race.  But some architectures need
	 * a memory barrier when used like this, and we don't have a
	 * Zephyr framework for that.
	 */

	 /* 自旋锁解锁 */
	atomic_clear(&l->locked);
#endif
	/* 开启中断 */
	arch_irq_unlock(key.key);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕咚.萌西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值