typedef struct { volatile int32_t cnt; /**< -1 when W lock held, > 0 when R locks held. */ } rte_rwlock_t;
dpdk在实现读写锁的时候,使用了原子锁机制
读锁加锁的时候,判断cnt是否小于0,如果是,表示当前处于写加锁状态,则需要把自己pause,否则直接使用原子操作cmpset把cnt+1.
static inline void rte_rwlock_read_lock(rte_rwlock_t *rwl) { int32_t x; int success = 0; while (success == 0) { x = rwl->cnt; /* write lock is held */ if (x < 0) { rte_pause(); continue; } success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt, (uint32_t)x, (uint32_t)(x + 1)); } }
写锁的实现,判断当前cnt是否为0,为0表示没有读锁处于加锁状态,则把cnt使用原子操作cmpset设置为-1,
如果cnt>0,则把自己pause,等待读锁解锁。
static inline void rte_rwlock_write_lock(rte_rwlock_t *rwl) { int32_t x; int success = 0; while (success == 0) { x = rwl->cnt; /* a lock is held */ if (x != 0) { rte_pause(); continue; } success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt, 0, (uint32_t)-1); } }
读写自旋锁主要用于比较短小的代码片段,线程等待期间不应该进入睡眠状态,因为睡眠/唤醒操作相当耗时,大大延长了获得锁的等待时间,所以我们要求忙等待。 申请锁的线程必须不断地查询是否发生退出等待的事件,不能进入睡眠状态。这个要求只是描述线程执行锁申请操作未成功时的行为,并不涉及锁自身的正确性。