Seq锁是在2.6内核版本中引入的一种新型锁。这种锁提供了一种很简单的机制,用于读写共享数据。实现这种锁主要依靠一个序列计数器。当有疑义的数据被写入时,会得到一个锁,并且序列值会增加。在读取数据之前和之后,序列号都被读取。如果序列号值相同,说明读操作进行的过程中没有被写操作打断。如果读取的值是偶数,那么就表明写操作没有发生(锁的初值是0,写锁会使值变成奇数,释放的时候变成偶数)。
- 在<Seqlock.h(include/linux)>中
- typedef struct {
- unsigned sequence;
- spinlock_t lock;
- } seqlock_t;
- /* Lock out other writers and update the count.
- * Acts like a normal spin_lock/unlock.
- * Don't need preempt_disable() because that is in the spin_lock already.
- */
- static inline void write_seqlock(seqlock_t *sl)
- {
- spin_lock(&sl->lock);
- ++sl->sequence;
- smp_wmb();
- }
- static inline void write_sequnlock(seqlock_t *sl)
- {
- smp_wmb();
- sl->sequence++;
- spin_unlock(&sl->lock);
- }
- static inline int write_tryseqlock(seqlock_t *sl)
- {
- int ret = spin_trylock(&sl->lock);
- if (ret) {
- ++sl->sequence;
- smp_wmb();
- }
- return ret;
- }
写锁的方法和普通自旋锁类似,不同的情况发生在读时:
- /* Start of read calculation -- fetch last complete writer token */
- static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
- {
- unsigned ret = sl->sequence;
- smp_rmb();
- return ret;
- }
- /* Test if reader processed invalid data.
- * If initial values is odd,
- * then writer had already started when section was entered
- * If sequence value changed
- * then writer changed data while in section
- *
- * Using xor saves one conditional branch.
- */
- static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
- {
- smp_rmb();
- return (iv & 1) | (sl->sequence ^ iv);
- }
在多个读者和少数写者共享一把锁的时候,seq锁有助于提供一种非常轻量和具有可扩展性的外观。但是seq锁对写者更有利。只要没有其他写者,写锁总是能够被成功获得。读者不会影响写锁。挂起的写锁会不断的使得读操作循环,直到不在有任何写者持有锁为止。