内核中自旋锁spinlock的使用

自旋锁的一个特性就是忙等待,循环过程中会大量消耗CPU,可以在中断上下文中使用。

只要有一个任务持有自旋锁,其他任务就可能在等待的时候自旋,使用自旋锁要确保不会长时间持有。

在单处理器系统上,应该使用spin_lock_irqsave()和spin_lock_irqrestore(),禁用处理器上中断,防止中断并发。

自旋锁与互斥锁的比较:
1、互斥锁保护进程关键资源,而自旋锁保护IRQ处理程序的关键部分。
2、互斥锁让竞争者在获得锁之前睡眠,而自旋锁在获得锁之前一直自旋循环(消耗CPU)
3、自旋锁不能长时间持有,因为等待者在等待取锁期间会浪费CPU时间,互斥锁可以长时间持有,竞争者被放入等待队列中进入睡眠状态。

持有自旋锁的线程被禁止抢占,自旋锁抢占者没有被禁止抢占。

以下为一些常见自旋锁加解锁相关函数

// 主要数据结构
typedef struct spinlock {
	union {
		struct raw_spinlock rlock;

#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
		struct {
			u8 __padding[LOCK_PADSIZE];
			struct lockdep_map dep_map;
		};
#endif
	};
} spinlock_t;

// 静态初始化
#define DEFINE_SPINLOCK(x)	spinlock_t x = __SPIN_LOCK_UNLOCKED(x)

// 动态初始化
#define spin_lock_init(_lock)				\
do {							\
	spinlock_check(_lock);				\
	raw_spin_lock_init(&(_lock)->rlock);		\
} while (0)

// 获取给定的自旋锁
static __always_inline void spin_lock(spinlock_t *lock)
{
	raw_spin_lock(&lock->rlock);
}
// 释放锁给定的自旋锁
static __always_inline void spin_unlock(spinlock_t *lock)
{
	raw_spin_unlock(&lock->rlock);
}

// 禁止软件中断并且获取给定的自旋锁
static __always_inline void spin_lock_bh(spinlock_t *lock)
{
	raw_spin_lock_bh(&lock->rlock);
}
// 释放给定的自旋锁并且启动软件中断
static __always_inline void spin_unlock_bh(spinlock_t *lock)
{
	raw_spin_unlock_bh(&lock->rlock);
}

// 禁止本地处理器上的中断,并且不保存之前的中断状态的标识
static __always_inline void spin_lock_irq(spinlock_t *lock)
{
	raw_spin_lock_irq(&lock->rlock);
}
static __always_inline void spin_unlock_irq(spinlock_t *lock)
{
	raw_spin_unlock_irq(&lock->rlock);
}

// 禁止本地处理器上的中断,并且保存之前的中断状态的标识
// flags类型为:unsigned long
#define spin_lock_irqsave(lock, flags)				\
do {								\
	raw_spin_lock_irqsave(spinlock_check(lock), flags);	\
} while (0)
static __always_inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
{
	raw_spin_unlock_irqrestore(&lock->rlock, flags);
}

自旋锁初始化的两种方式:
1、动态初始化

spinlock_t lock;
spin_lock_init (&lock);

2、静态初始化

DEFINE_SPINLOCK(lock);

以下为一些自旋锁的相关辅助函数

// 判断自旋锁是否已经被持有
/**
 * spin_is_locked() - Check whether a spinlock is locked.
 * @lock: Pointer to the spinlock.
 *
 * This function is NOT required to provide any memory ordering
 * guarantees; it could be used for debugging purposes or, when
 * additional synchronization is needed, accompanied with other
 * constructs (memory barriers) enforcing the synchronization.
 *
 * Returns: 1 if @lock is locked, 0 otherwise.
 *
 * Note that the function only tells you that the spinlock is
 * seen to be locked, not that it is locked on your CPU.
 *
 * Further, on CONFIG_SMP=n builds with CONFIG_DEBUG_SPINLOCK=n,
 * the return value is always 0 (see include/linux/spinlock_up.h).
 * Therefore you should not rely heavily on the return value.
 */
static __always_inline int spin_is_locked(spinlock_t *lock)
{
	return raw_spin_is_locked(&lock->rlock);
}

自旋锁使用流程

spinlock_t my_spin_lock;

spin_lock_init(my_spin_lock);
spin_lock(&my_spin_lock);
spin_unlock(&my_spin_lock);

读写自旋锁的使用场景:对临界区读多写少的情况。

// 主要数据结构
typedef struct {
        arch_rwlock_t raw_lock;
#ifdef CONFIG_DEBUG_SPINLOCK
        unsigned int magic, owner_cpu;
        void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map dep_map;
#endif        
} rwlock_t;

// 读写自旋锁的初始化
# define rwlock_init(lock)                                      \
do {                                                            \
        static struct lock_class_key __key;                     \
                                                                \
        __rwlock_init((lock), #lock, &__key);                   \
} while (0)

// 与普通自选锁一样,也存在以下函数
#define write_lock(lock)        _raw_write_lock(lock)
#define read_lock(lock)         _raw_read_lock(lock)
#define read_lock_irq(lock)             _raw_read_lock_irq(lock)
#define read_lock_bh(lock)              _raw_read_lock_bh(lock)
#define write_lock_irq(lock)            _raw_write_lock_irq(lock)
#define write_lock_bh(lock)             _raw_write_lock_bh(lock)
#define read_unlock(lock)               _raw_read_unlock(lock)
#define write_unlock(lock)              _raw_write_unlock(lock)
#define read_unlock_irq(lock)           _raw_read_unlock_irq(lock)
#define write_unlock_irq(lock)          _raw_write_unlock_irq(lock)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值