www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > Linux閱碼場
[導(dǎo)讀]序言:近期讀Linux5.15的發(fā)布說明,該版本合并了實時鎖機(jī)制,當(dāng)開啟配置宏CONFIG_PREEMPT_RT的時候,這些鎖被基于實時互斥鎖的變體替代:mutex、ww_mutex、rw_semaphore、spinlock和rwlock。第一次聽說ww_mutex,在百度上查...

序言:近期讀Linux 5.15的發(fā)布說明,該版本合并了實時鎖機(jī)制,當(dāng)開啟配置宏CONFIG_PREEMPT_RT的時候,這些鎖被基于實時互斥鎖的變體替代:mutex、ww_mutex、rw_semaphore、spinlock和rwlock。第一次聽說ww_mutex,在百度上查找的時候發(fā)現(xiàn)介紹文檔很少,于是自己學(xué)習(xí),寫成筆記。在某些場合必須同時持有多個鎖,并且獲取鎖的順序可能不同,為了避免死鎖,應(yīng)該使用傷害/等待互斥鎖(Wound/Wait Mutexes)。獲取一個鎖集合稱為一個事務(wù)(transaction),每個事務(wù)關(guān)聯(lián)一張門票(ticket),門票也稱為序列號,根據(jù)門票判斷哪個事務(wù)年輕。有2種處理死鎖的方法,如下。(1)?等待-死亡(Wait-Die)算法:一個事務(wù)申請另一個事務(wù)已經(jīng)獲取的鎖的時候,如果持有鎖的事務(wù)年輕,那么申請鎖的事務(wù)等待(wait);如果持有鎖的事務(wù)年老,那么申請鎖的事務(wù)退并且死亡(die)(2) 4.19版本開始支持傷害-等待(Wound-Wait)算法:一個事務(wù)申請另一個事務(wù)已經(jīng)獲取的鎖的時候,如果持有鎖的事務(wù)年輕,那么申請鎖的事務(wù)傷害(wound)持有鎖的事務(wù),請求它去死亡;如果持有鎖的事務(wù)年老,那么申請鎖的事務(wù)等待(wait)。

假設(shè)進(jìn)程1和進(jìn)程2分別在2個處理器上運(yùn)行,進(jìn)程1獲取鎖A,進(jìn)程2獲取鎖B,然后進(jìn)程1申請鎖B,進(jìn)程2申請鎖A。假設(shè)進(jìn)程1的門票編號比進(jìn)程2的門票編號小,也就是進(jìn)程1年老,進(jìn)程2年輕。假設(shè)選擇等待-死亡算法。年老的進(jìn)程1申請鎖B,發(fā)現(xiàn)持有鎖B的進(jìn)程2年輕,那么年老的進(jìn)程1等待。年輕的進(jìn)程2申請鎖A,發(fā)現(xiàn)持有鎖A的進(jìn)程1年老,那么年輕的進(jìn)程2死亡(即申請鎖的函數(shù)返回“-EDEADLK”),接著回滾(即釋放已經(jīng)獲取的鎖B),然后重新開始:先申請鎖A然后申請鎖B(必須改變申請順序,如果先申請鎖B,那么會把剛釋放的鎖B搶回來)。假設(shè)選擇傷害-等待算法。年老的進(jìn)程1申請鎖B,發(fā)現(xiàn)持有鎖B的進(jìn)程2年輕,那么傷害年輕的進(jìn)程2,請求它死亡。年輕的進(jìn)程2申請鎖A,發(fā)現(xiàn)持有鎖A的進(jìn)程1年老,那么年輕的進(jìn)程2等待,在收到進(jìn)程1的死亡請求以后,年輕的進(jìn)程2死亡(即申請鎖的函數(shù)返回“-EDEADLK”),接著回滾(即釋放已經(jīng)獲取的鎖B),然后重新開始:先申請鎖A然后申請鎖B。兩種算法都是公平的,因為其中一個事務(wù)最終會成功。和等待-死亡算法相比,傷害-等待算法生成的退避少,但是從一次退避恢復(fù)的時候要做更多的工作。傷害-等待算法是一種搶占性的算法(因為事務(wù)被其它事務(wù)傷害),需要一種可靠的方法來選擇受傷狀態(tài)和搶占正在運(yùn)行的事務(wù)。在傷害-等待算法中,一個事務(wù)在受傷后死亡(返回“-EDEADLK”),就認(rèn)為這個事務(wù)被搶占。如果競爭鎖的進(jìn)程少,并且希望減少回滾的次數(shù),那么應(yīng)該選擇傷害-等待算法。?和普通的互斥鎖相比,傷害/等待互斥鎖增加了下面2個概念。(1)?獲取上下文(acquire context):一個獲取上下文表示一個事務(wù),關(guān)聯(lián)一張門票(ticket),門票也稱為序列號,門票編號小表示年老,門票編號大表示年輕。獲取上下文跟蹤調(diào)試狀態(tài),捕獲對傷害/等待互斥鎖接口的錯誤使用。

(2)?傷害/等待類初始化獲取上下文的時候需要指定鎖類,鎖類會給獲取上下文分配門票。鎖類也指定算法:等待-死亡(Wait-Die)或傷害-等待(Wound-Wait)。當(dāng)多個進(jìn)程競爭同一個鎖集合的時候,它們必須使用相同的鎖類。

?3種獲取傷害/等待互斥鎖的函數(shù),如下。(1) 普通的獲取鎖函數(shù)ww_mutex_lock(),帶有獲取上下文。

(2) 進(jìn)程在回滾(即釋放所有已經(jīng)獲取的鎖)以后,使用慢路徑獲取鎖函數(shù)ww_mutex_lock_slow()獲取正在競爭的鎖。帶有“_slow”后綴的函數(shù)不是必需的,因為可以調(diào)用函數(shù)ww_mutex_lock()獲取正在競爭的鎖。帶有“_slow”后綴的函數(shù)的優(yōu)點(diǎn)是接口安全,如下。

  • 函數(shù)ww_mutex_lock()有一個整數(shù)返回值,而函數(shù)ww_mutex_lock_slow()沒有返回值。
  • 當(dāng)開啟調(diào)試的時候,函數(shù)ww_mutex_lock_slow()檢查所有已經(jīng)獲取的鎖已經(jīng)被釋放,并且確保進(jìn)程阻塞在正在競爭的鎖上面。
(3) 只獲取一個傷害/等待互斥鎖,和獲取普通的互斥鎖完全相同。調(diào)用函數(shù)ww_mutex_lock(),把獲取上下文指定為空指針。

?傷害/等待互斥鎖的使用方法如下。(1) 定義一個鎖類,鎖類在初始化獲取上下文的時候需要,鎖類也指定算法:等待-死亡(Wait-Die)或傷害-等待(Wound-Wait)。

/* 指定等待-死亡算法 */static DEFINE_WD_CLASS(my_class);
/* 指定傷害-等待算法 */static?DEFINE_WW_CLASS(my_class);(2) 初始化一個獲取上下文,鎖類會給獲取上下文分配一張門票。

void ww_acquire_init(struct ww_acquire_ctx *ctx, struct ww_class *ww_class);(3) 獲取鎖,返回0表示獲取成功,返回“-EDEADLK”表示檢測出死鎖。
int ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx);(4) 獲取需要的所有鎖以后,標(biāo)記獲取階段結(jié)束。目前這個函數(shù)沒有執(zhí)行任何操作,但是將來可能改變。
void ww_acquire_done(struct ww_acquire_ctx *ctx);(5) 釋放鎖。
void ww_mutex_unlock(struct ww_mutex *lock);(6) 釋放所有鎖以后,釋放獲取上下文。
void ww_acquire_fini(struct ww_acquire_ctx *ctx);?

下面是一個例子,注意:調(diào)用函數(shù)ww_mutex_lock()申請鎖失敗以后,應(yīng)該先釋放已經(jīng)獲取的鎖,然后調(diào)用慢路徑函數(shù)ww_mutex_lock_slow()獲取正在競爭的鎖,最后獲取其它鎖。重新開始申請鎖的時候必須改變申請順序,因為如果按照原來的順序申請鎖,那么會把剛釋放的鎖搶回來。
/* 第1步:定義鎖類,指定傷害-等待算法。*/static DEFINE_WW_CLASS(ww_class);
struct obj { struct ww_mutex lock; /* obj data */};
struct obj_entry { struct list_head head; struct obj *obj;};
int lock_objs(struct list_head *list, struct ww_acquire_ctx *ctx){ struct obj *res_obj = NULL; struct obj_entry *contended_entry = NULL; struct obj_entry *entry; int ret;
/* 第2步:初始化獲取上下文。*/ ww_acquire_init(ctx,
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉