Sequence locks

Conventional reader-writer locks are designed with reader priority, and they might cause a writer task to wait for a non-deterministic duration, which might not be suitable on shared data with time-sensitive updates. This is where sequential lock comes in handy, as it aims at providing a quick and lock-free access to shared resources. Sequential locks are best when the resource that needs to be protected is small and simple, with write access being quick and non-frequent, as internally sequential locks fall back on the spinlock primitive.

Sequential locks introduce a special counter that is incremented every time a writer acquires a sequential lock along with a spinlock. After the writer completes, it releases the spinlock and increments the counter again and opens the access for other writers. For read, there are two types of readers: sequence readers and locking readers. The sequence reader checks for the counter before it enters the critical section and then checks again at the end of it without blocking any writer. If the counter remains the same, it implies that no writer had accessed the section during read, but if there is an increment of the counter at the end of the section, it is an indication that a writer had accessed, which calls for the reader to re-read the critical section for updated data. A locking reader, as the name implies, will get a lock and block other readers and writers when it is in progress; it will also wait when another locking reader or writer is in progress.

A sequence lock is represented by the following type:

typedef struct {
        struct seqcount seqcount;
        spinlock_t lock;
} seqlock_t;

We can initialize a sequence lock statically using the following macro:

#define DEFINE_SEQLOCK(x) 
               seqlock_t x = __SEQLOCK_UNLOCKED(x)

Actual initialization is done using the __SEQLOCK_UNLOCKED(x), which is defined here:

#define __SEQLOCK_UNLOCKED(lockname)                 
       {                                               
               .seqcount = SEQCNT_ZERO(lockname),     
               .lock = __SPIN_LOCK_UNLOCKED(lockname)   
       }

To dynamically initialize sequence lock, we need to use the seqlock_init macro, which is defined as follows:

  #define seqlock_init(x)                                     
       do {                                                   
               seqcount_init(&(x)->seqcount);                 
               spin_lock_init(&(x)->lock);                    
       } while (0)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.30.162