序列計數器和順序鎖

序列計數器（seqcount_t）

``````/* 動態 */
seqcount_t foo_seqcount;
seqcount_init(&foo_seqcount);

/* 靜態 */
static seqcount_t foo_seqcount = SEQCNT_ZERO(foo_seqcount);

/* C99 結構初始化 */
struct {
.seq   = SEQCNT_ZERO(foo.seq),
} foo;
``````

``````/* 禁用搶佔的串行化上下文 */

write_seqcount_begin(&foo_seqcount);

/* ... [[寫端臨界區]] ... */

write_seqcount_end(&foo_seqcount);
``````

``````do {

/* ... [[讀端臨界區]] ... */

``````

帶關聯鎖的序列計數器（seqcount_LOCKNAME_t）

• seqcount_spinlock_t
• seqcount_raw_spinlock_t
• seqcount_rwlock_t
• seqcount_mutex_t
• seqcount_ww_mutex_t

``````/* 動態 */
seqcount_LOCKNAME_t foo_seqcount;
seqcount_LOCKNAME_init(&foo_seqcount, &lock);

/* 靜態 */
static seqcount_LOCKNAME_t foo_seqcount =
SEQCNT_LOCKNAME_ZERO(foo_seqcount, &lock);

/* C99 結構初始化 */
struct {
.seq   = SEQCNT_LOCKNAME_ZERO(foo.seq, &lock),
} foo;
``````

順序鎖（seqlock_t）

``````/* 動態 */
seqlock_t foo_seqlock;
seqlock_init(&foo_seqlock);

/* 靜態 */
static DEFINE_SEQLOCK(foo_seqlock);

/* C99 結構初始化 */
struct {
.seql   = __SEQLOCK_UNLOCKED(foo.seql)
} foo;
``````

``````write_seqlock(&foo_seqlock);

/* ... [[寫端臨界區]] ... */

write_sequnlock(&foo_seqlock);
``````

1. 普通序列讀取器永遠不會阻塞寫者，但如果檢測到序列號的變化，它們必須重試，因爲寫者正在進行中。寫者不會等待序列讀取器：
``````    do {

/* ... [[讀端臨界區]] ... */

``````
1. 鎖定讀取器會在寫者或另一個鎖定讀取器進行中時等待。進行中的鎖定讀取器還會阻止寫者進入其臨界區。此讀鎖是獨佔的。與rwlock_t不同，只有一個鎖定讀取器可以獲取它：
``````    read_seqlock_excl(&foo_seqlock);

/* ... [[讀端臨界區]] ... */

``````
1. 根據傳遞的標記，條件無鎖讀取器（如1）或鎖定讀取器（如2）。這用於避免在寫活動急劇增加時無鎖讀取器飢餓（太多重試循環）。首先嚐試無鎖讀取（傳遞偶數標記）。如果該嘗試失敗（返回奇數序列計數，用作下一次迭代標記），則無鎖讀取將轉換爲完全鎖定讀取，不需要重試循環：
``````    /* 標記；偶數初始化 */
int seq = 0;
do {

/* ... [[讀端臨界區]] ... */

} while (need_seqretry(&foo_seqlock, seq));
done_seqretry(&foo_seqlock, seq);
``````

API 文檔

https://www.kernel.org/doc/html/v6.6/locking/seqlock.html#api-documentation