Linux 内核的排队自旋锁

本文深入分析了排队自旋锁(FIFOTicketSpinlock)在Linux内核2.6.25版本中的引入背景、设计原理及加锁、解锁实现,详细解释了其如何解决传统自旋锁存在的‘不公平’问题,同时提供了一个清晰的加锁过程概述,旨在帮助读者理解自旋锁的公平性与效率之间的权衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

排队自旋锁(FIFO Ticket Spinlock)是 Linux 内核 2.6.25 版本中引入的一种新型自旋锁,它解决了传统自旋锁由于无序竞争导致的“公平性”问题。
长期以来,人们总是关注于自旋锁的安全和高效,而忽视了自旋锁的“公平”性。传统的自旋锁本质上用一个整数来表示,值为1代表锁未被占用。这种无序竞争的本质特点导致执行线程无法保证何时能取到锁,某些线程可能需要等待很长时间。随着计算机处理器个数的不断增长,这种“不公平”问题将会日益严重。
排队自旋锁的设计原理
传统自旋锁的“不公平”问题在锁竞争激烈的服务器系统中尤为严重,因此 Linux 内核开发者 Nick Piggin 在 Linux 内核 2.6.25 版本中引入了排队自旋锁:通过保存执行线程申请锁的顺序信息来解决“不公平”问题。
排队自旋锁仍然使用原有的 raw_spinlock_t 数据结构,但是赋予 slock 域新的含义。为了保存顺序信息,slock 域被分成两部分,分别保存锁持有者和未来锁申请者的票据序号。
注:slock为:
typedef struct {
unsigned int slock;
} raw_spinlock_t;
只有 Next 域与 Owner 域相等时,才表明锁处于未使用状态(此时也无人申请该锁)。排队自旋锁初始化时 slock 被置为 0,即 Owner 和 Next 置为 0。内核执行线程申请自旋锁时,原子地将 Next 域加 1,并将原值返回作为自己的票据序号。如果返回的票据序号等于申请时的 Owner 值,说明自旋锁处于未使用状态,则直接获得锁;否则,该线程忙等待检查 Owner 域是否等于自己持有的票据序号,一旦相等,则表明锁轮到自己获取。线程释放锁时,原子地将 Owner 域加 1 即可,下一个线程将会发现这一变化,从忙等待状态中退出。线程将严格地按照申请顺序依次获取排队自旋锁,从而完全解决了“不公平”问题
加锁实现:

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
    short inc = 0x0100;

    __asm__ __volatile__ (
        LOCK_PREFIX "xaddw %w0, %1\n"
        "1:\t"
        "cmpb %h0, %b0\n\t"
        "je 2f\n\t"
        "rep ; nop\n\t"
        "movb %1, %b0\n\t"
        /* don't need lfence here, because loads are in-order */
        "jmp 1b\n"
        "2:"
        :"+Q" (inc), "+m" (lock->slock)
        :
        :"memory", "cc");
}

a:LOCK_PREFIX 宏就是“lock”前缀。
b:xaddw 汇编指令将 slock 和 inc 的值交换,然后把这两个值相加后的和存到 slock 中。也就是说,该指令执行完毕后,inc 存有原来的 slock 值作为票据序号,而 slock 的 Next 域被加 1。
c:cmpb 比较 inc 变量的高位和低位字节是否相等,如果相等,表明锁处于未使用状态,直接跳转到标签 2 的位置退出函数。
d:如果锁处于使用状态,则不停地将当前的 slock 的 Owner 域复制到 inc 的低字节处(movb 指令),然后重复 c 步骤。不过此时 inc 变量的高位和低位字节相等表明轮到自己获取了自旋锁。
解锁实现:

static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
    __asm__ __volatile__(
        UNLOCK_LOCK_PREFIX "incb %0"
        :"+m" (lock->slock)
        :
        :"memory", "cc");
}

原子地给当前的 slock 的 Owner 域加1.
转载自:http://www.ibm.com/developerworks/cn/linux/l-cn-spinlock/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值