sync rw_semaphore_debug - ceragon/LinuxDoc GitHub Wiki

总结

sem->count 被分为高32位和低32位。高位不为0,用于表示是否有写锁在使用或等待。 低位不为0,用于表示当前是否上锁。所以分为如下情况:

count 值 状态 备注
0x0000000000000000L 无锁
0x0000000000000001L 读者上锁
0x0000000000000002L 两个读者上锁 因为读锁不互斥
0xFFFFFFFF00000001L 写者上锁
0xFFFFFFFF00000001L 写者上锁

读者加锁流程

无竞争

变化时刻 count 值 备注
初始状态 0x00000000_00000000L
原子操作 +1 0x00000000_00000001L
加锁成功 0x00000000_00000001L 符号位为0就加锁成功
解锁后 0x00000000_00000000L

读者R - 读者owner

变化时刻 count 值 备注
初始状态 0x00000000_00000001L 读者A获取了锁
owner 原子操作 +1 0x00000000_00000002L
owner 加锁成功 0x00000000_00000002L 读读不互斥
读者R 解锁 0x00000000_00000001L
owner 解锁 0x00000000_00000000L

写者W - 读者owner

情况一

变化时刻 count 值 adjustment 值 temp count 值 备注
初始状态 0xFFFF_FFFF_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 写者W获取了锁
owner 原子操作 +1 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL 符号位不为0,加锁失败
owner 获取 wait_lock 后 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFE_FFFF_FFFFL
owner 加入等待队列后 0xFFFF_FFFE_0000_0001L 0xFFFF_FFFE_FFFF_FFFFL 0xFFFF_FFFE_0000_0001L owner 进入等待状态
写者W 释放锁 0xFFFF_FFFF_0000_0000L 0x0000_0000L 由于 count 为负,且旧值低位-1后为0,继续执行写者W唤醒流程
写者W 计算读者数量 0xFFFF_FFFF_0000_0000L 0x0000_0000_0000_0001L
写者W 由于最后一个waiter是读者 0xFFFF_FFFF_0000_0000L 0x0000_0001_0000_0001L
写者W 唤醒所有读等待者 0x0000_0000_0000_0001L 0x0000_0001_0000_0001L
owner 被唤醒 0x0000_0000_0000_0001L
owner 释放锁 0x0000_0000_0000_0000L 由于 count 为0,释放成功

情况二

变化时刻 count 值 adjustment 值 temp count 值 备注
初始状态 0xFFFF_FFFF_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 写者W获取了锁
owner 原子操作 +1 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL 符号位不为0,加锁失败
写者W 释放锁 0x0000_0000_0000_0001L 0x0000_0001L 由于 count 为正,释放锁成功
owner 获取 wait_lock 后 0x0000_0000_0000_0001L 0xFFFF_FFFE_FFFF_FFFFL
owner 加入等待队列后 0xFFFF_FFFF_0000_0000L 0xFFFF_FFFE_FFFF_FFFFL 0xFFFF_FFFF_0000_0000L temp count == RWSEM_WAITING_BIAS,执行owner唤醒流程
owner 计算读者数量 0xFFFF_FFFF_0000_0000L 0x0000_0000_0000_0001L
owner 由于最后一个waiter是读者 0xFFFF_FFFF_0000_0000L 0x0000_0001_0000_0001L
owner 唤醒所有读等待者 0x0000_0000_0000_0001L 0x0000_0001_0000_0001L
owner 也是被唤醒者 0x0000_0000_0000_0001L
owner 释放锁 0x0000_0000_0000_0000L 由于 count 为0,释放成功

情况三

变化时刻 count 值 adjustment 值 temp count 值 备注
初始状态 0xFFFF_FFFF_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 写者W获取了锁
owner 原子操作 +1 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL 符号位不为0,加锁失败
owner 获取 wait_lock 后 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFE_FFFF_FFFFL
写者W 释放锁 0x0000_0000_0000_0001L 0x0000_0000L 由于 count 为正,释放锁成功
owner 加入等待队列后 0xFFFF_FFFF_0000_0000L 0xFFFF_FFFE_FFFF_FFFFL 0xFFFF_FFFF_0000_0000L temp count == RWSEM_WAITING_BIAS,执行owner唤醒流程
owner 计算读者数量 0xFFFF_FFFF_0000_0000L 0x0000_0000_0000_0001L
owner 由于最后一个waiter是读者 0xFFFF_FFFF_0000_0000L 0x0000_0001_0000_0001L
owner 唤醒所有读等待者 0x0000_0000_0000_0001L 0x0000_0001_0000_0001L
owner 也是被唤醒者 0x0000_0000_0000_0001L
owner 释放锁 0x0000_0000_0000_0000L 由于 count 为0,释放成功

写者W - 读者R - 读者owner

情况一

变化时刻 count 值 adjustment 值 temp count 值 备注
初始状态 0xFFFF_FFFF_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 写者W获取了锁
读者R 原子操作 +1 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL 符号位不为0,加锁失败
读者R 获取 wait_lock 后 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFE_FFFF_FFFFL
读者R 加入等待队列后 0xFFFF_FFFE_0000_0001L 0xFFFF_FFFE_FFFF_FFFFL 0xFFFF_FFFE_0000_0001L 读者R 进入等待状态
owner 原子操作 +1 0xFFFF_FFFE_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL 符号位不为0,加锁失败
owner 获取 wait_lock 后 0xFFFF_FFFE_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL
owner 加入等待队列后 0xFFFF_FFFE_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 0xFFFF_FFFE_0000_0001L 读者R 进入等待状态
写者W 释放锁 0xFFFF_FFFF_0000_0000L 0x0000_0000L 由于 count 为负,且旧值低32位-1后为0,继续执行写者W唤醒流程
写者W 计算读者数量 0xFFFF_FFFF_0000_0000L 0x0000_0000_0000_00002L
写者W 由于最后一个waiter是读者 0xFFFF_FFFF_0000_0000L 0x0000_0001_0000_0002L
写者W 唤醒所有读等待者 0x0000_0000_0000_0002L 0x0000_0001_0000_0002L
读者R 被唤醒 0x0000_0000_0000_0002L
读者R 释放锁 0x0000_0000_0000_0001L
owner 被唤醒 0x0000_0000_0000_0001L
owner 释放锁 0x0000_0000_0000_0000L

情况二

变化时刻 count 值 adjustment 值 temp count 值 备注
初始状态 0xFFFF_FFFF_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 写者W获取了锁
读者R 原子操作 +1 0xFFFF_FFFF_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL 符号位不为0,加锁失败
owner 原子操作 +1 0xFFFF_FFFF_0000_0003L 0xFFFF_FFFF_FFFF_FFFFL 符号位不为0,加锁失败
读者R 获取 wait_lock 后 0xFFFF_FFFF_0000_0003L 0xFFFF_FFFE_FFFF_FFFFL
读者R 加入等待队列后 0xFFFF_FFFE_0000_0002L 0xFFFF_FFFE_FFFF_FFFFL 0xFFFF_FFFE_0000_0002L 读者R 进入等待状态
owner 获取 wait_lock 后 0xFFFF_FFFE_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL
owner 加入等待队列后 0xFFFF_FFFE_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 0xFFFF_FFFE_0000_0001L 读者R 进入等待状态
写者W 释放锁 0xFFFF_FFFF_0000_0000L 0x0000_0000L 由于 count 为负,且旧值低32位-1后为0,继续执行写者W唤醒流程
写者W 计算读者数量 0xFFFF_FFFF_0000_0000L 0x0000_0000_0000_00002L
写者W 由于最后一个waiter是读者 0xFFFF_FFFF_0000_0000L 0x0000_0001_0000_0002L
写者W 唤醒所有读等待者 0x0000_0000_0000_0002L 0x0000_0001_0000_0002L
读者R 被唤醒 0x0000_0000_0000_0002L
读者R 释放锁 0x0000_0000_0000_0001L
owner 被唤醒 0x0000_0000_0000_0001L
owner 释放锁 0x0000_0000_0000_0000L

写者W1 - 写者W2 - 读者owner

变化时刻 count 值 adjustment 值 temp count 值 备注
初始状态 0xFFFF_FFFF_0000_0001L 0x0000_0000_FFFF_FFFFL 写者W1获取了锁
W2 原子操作+0xFFFFFFFF_00000001L 0xFFFF_FFFE_0000_0002L 0x0000_0000_FFFF_FFFFL 旧值不为0
W2 获取 wait_lock 后 0xFFFF_FFFE_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL 等待队列为空
W2 加入等待队列后 0xFFFF_FFFE_0000_0001L 0xFFFF_FFFF_FFFF_FFFFL 0xFFFF_FFFE_0000_0001L
owner 原子操作+1 0xFFFF_FFFE_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL
owner 获取 wait_lock 后 0xFFFF_FFFE_0000_0002L 0xFFFF_FFFF_FFFF_FFFFL
owner 加入等待队列后 0xFFFF_FFFE_0000_0001L 0xFFFF_FFFE_FFFF_FFFFL 0xFFFF_FFFE_0000_0001L owner 进入等待状态
W1 释放锁 0xFFFF_FFFF_0000_0000L 0xFFFF_FFFE_0000_0001L 由于 count 为负, 且旧值低32位-1后为0,继续执行w1的唤醒流程
W1 判定旧值 0xFFFF_FFFF_0000_0000L 0x0000_0000L 旧值是0,继续执行 w1 的唤醒流程
W1 判定下一个等待者是写者 0xFFFF_FFFF_0000_0000L 0xFFFFFFFF00000001L
W1 准备唤醒写者 0xFFFF_FFFE_0000_0001L 0xFFFFFFFF00000001L 0xFFFF_FFFF_0000_0000L temp count 与操作 0xFFFFFFFFL 为0,继续唤醒
W1 唤醒写者W2 0xFFFF_FFFE_0000_0001L
W2 被唤醒 0xFFFF_FFFE_0000_0001L
W2 释放锁 0xFFFF_FFFF_0000_0000L 0xFFFF_FFFE_0000_0001L
W2 判定旧值 0xFFFF_FFFF_0000_0000L 0x0000_0000L 旧值是0,继续执行 w2 的唤醒流程
W2 判定下一个等待者是读者 0xFFFF_FFFF_0000_0000L 0xFFFF_FFFF_0000_0000L 由于old count == 0xFFFFFFFF00000000L,所以继续唤醒
W2 计算唤醒读者数量 0xFFFF_FFFF_0000_0000L 0x0000_0000_0000_0001L
W2 判断最后一个waiter是读者 0xFFFF_FFFF_0000_0000L 0x0000_0001_0000_0001L
W2 唤醒所有等待者 0x0000_0000_0000_0001L
owner 被唤醒 0x0000_0000_0000_0001L
owner 释放锁 0x0000_0000_0000_0000L

写者上锁

无竞争

变化时刻 count 值 备注
初始状态 0x00000000_00000000L
原子操作 +1 0xFFFFFFFF_00000001L
加锁成功 0xFFFFFFFF_00000001L 旧值为0就加锁成功
解锁后 0x00000000_00000000L

写者W - 写者owner

变化时刻 count 值 adjustment 值 temp count 值 备注
初始状态 0xFFFF_FFFF_0000_0001L
owner 加锁 0xFFFF_FFFE_0000_0002L
⚠️ **GitHub.com Fallback** ⚠️