(2) 4.19版本開始支持傷害-等待(Wound-Wait)算法:一個事務申請另一個事務已經(jīng)獲取的鎖的時候,如果持有鎖的事務年輕,那么申請鎖的事務傷害(wound)持有鎖的事務,請求它去死亡;如果持有鎖的事務年老,那么申請鎖的事務等待(wait)。
假設進程1和進程2分別在2個處理器上運行,進程1獲取鎖A,進程2獲取鎖B,然后進程1申請鎖B,進程2申請鎖A。假設進程1的門票編號比進程2的門票編號小,也就是進程1年老,進程2年輕。假設選擇等待-死亡算法。年老的進程1申請鎖B,發(fā)現(xiàn)持有鎖B的進程2年輕,那么年老的進程1等待。年輕的進程2申請鎖A,發(fā)現(xiàn)持有鎖A的進程1年老,那么年輕的進程2死亡(即申請鎖的函數(shù)返回“-EDEADLK”),接著回滾(即釋放已經(jīng)獲取的鎖B),然后重新開始:先申請鎖A然后申請鎖B(必須改變申請順序,如果先申請鎖B,那么會把剛釋放的鎖B搶回來)。假設選擇傷害-等待算法。年老的進程1申請鎖B,發(fā)現(xiàn)持有鎖B的進程2年輕,那么傷害年輕的進程2,請求它死亡。年輕的進程2申請鎖A,發(fā)現(xiàn)持有鎖A的進程1年老,那么年輕的進程2等待,在收到進程1的死亡請求以后,年輕的進程2死亡(即申請鎖的函數(shù)返回“-EDEADLK”),接著回滾(即釋放已經(jīng)獲取的鎖B),然后重新開始:先申請鎖A然后申請鎖B。兩種算法都是公平的,因為其中一個事務最終會成功。和等待-死亡算法相比,傷害-等待算法生成的退避少,但是從一次退避恢復的時候要做更多的工作。傷害-等待算法是一種搶占性的算法(因為事務被其它事務傷害),需要一種可靠的方法來選擇受傷狀態(tài)和搶占正在運行的事務。在傷害-等待算法中,一個事務在受傷后死亡(返回“-EDEADLK”),就認為這個事務被搶占。如果競爭鎖的進程少,并且希望減少回滾的次數(shù),那么應該選擇傷害-等待算法。 和普通的互斥鎖相比,傷害/等待互斥鎖增加了下面2個概念。(1)獲取上下文(acquire context):一個獲取上下文表示一個事務,關(guān)聯(lián)一張門票(ticket),門票也稱為序列號,門票編號小表示年老,門票編號大表示年輕。獲取上下文跟蹤調(diào)試狀態(tài),捕獲對傷害/等待互斥鎖接口的錯誤使用。
(2)傷害/等待類:初始化獲取上下文的時候需要指定鎖類,鎖類會給獲取上下文分配門票。鎖類也指定算法:等待-死亡(Wait-Die)或傷害-等待(Wound-Wait)。當多個進程競爭同一個鎖集合的時候,它們必須使用相同的鎖類。
有3種獲取傷害/等待互斥鎖的函數(shù),如下。(1) 普通的獲取鎖函數(shù)ww_mutex_lock(),帶有獲取上下文。
(2) 進程在回滾(即釋放所有已經(jīng)獲取的鎖)以后,使用慢路徑獲取鎖函數(shù)ww_mutex_lock_slow()獲取正在競爭的鎖。帶有“_slow”后綴的函數(shù)不是必需的,因為可以調(diào)用函數(shù)ww_mutex_lock()獲取正在競爭的鎖。帶有“_slow”后綴的函數(shù)的優(yōu)點是接口安全,如下。
- 函數(shù)ww_mutex_lock()有一個整數(shù)返回值,而函數(shù)ww_mutex_lock_slow()沒有返回值。
- 當開啟調(diào)試的時候,函數(shù)ww_mutex_lock_slow()檢查所有已經(jīng)獲取的鎖已經(jīng)被釋放,并且確保進程阻塞在正在競爭的鎖上面。
(3) 只獲取一個傷害/等待互斥鎖,和獲取普通的互斥鎖完全相同。調(diào)用函數(shù)ww_mutex_lock(),把獲取上下文指定為空指針。
傷害/等待互斥鎖的使用方法如下。(1) 定義一個鎖類,鎖類在初始化獲取上下文的時候需要,鎖類也指定算法:等待-死亡(Wait-Die)或傷害-等待(Wound-Wait)。
/* 指定等待-死亡算法 */static DEFINE_WD_CLASS(my_class);/* 指定傷害-等待算法 */staticDEFINE_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) 獲取需要的所有鎖以后,標記獲取階段結(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()申請鎖失敗以后,應該先釋放已經(jīng)獲取的鎖,然后調(diào)用慢路徑函數(shù)ww_mutex_lock_slow()獲取正在競爭的鎖,最后獲取其它鎖。重新開始申請鎖的時候必須改變申請順序,因為如果按照原來的順序申請鎖,那么會把剛釋放的鎖搶回來。
責任編輯:haq/* 第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, &ww_class);/* 第3步:獲取鎖。*/retry:list_for_each_entry(entry, list, head) {if (entry->obj == res_obj) {res_obj = NULL;continue;}ret = ww_mutex_lock(&entry->obj->lock, ctx);if (ret < 0) {contended_entry = entry;goto err;}}/* 第4步:標記獲取階段結(jié)束。*/ww_acquire_done(ctx);return 0;err:/* 回滾,釋放已經(jīng)獲取的鎖。*/list_for_each_entry_continue_reverse(entry, list, head) {ww_mutex_unlock(&entry->obj->lock);}if (res_obj) {ww_mutex_unlock(&res_obj->lock);}if (ret == -EDEADLK) {/* 使用慢路徑獲取鎖函數(shù)獲取正在競爭的鎖。*/ww_mutex_lock_slow(&contended_entry->obj->lock, ctx);res_obj = contended_entry->obj;/* 獲取其它鎖。*/goto retry;}ww_acquire_fini(ctx);return ret;}void unlock_objs(struct list_head *list, struct ww_acquire_ctx *ctx){struct obj_entry *entry;/* 第5步:釋放鎖。*/list_for_each_entry (entry, list, head) {ww_mutex_unlock(&entry->obj->lock);}/* 第6步:釋放獲取上下文。*/ww_acquire_fini(ctx);}
-
鎖相環(huán)
+關(guān)注
關(guān)注
36文章
633瀏覽量
90817 -
Linux
+關(guān)注
關(guān)注
88文章
11628瀏覽量
217989
原文標題:傷害/等待互斥鎖
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
飛凌嵌入式ElfBoard-文件I/O的深入學習之文件鎖
Linux-RT特點及簡單應用
【書籍評測活動NO.67】成為硬核Linux開發(fā)者:《Linux 設備驅(qū)動開發(fā)(第 2 版)》
一個硬件SPI兩個CS操作兩個norflash,怎么互斥操作兩個norflash?
五大認證加冕!德施曼以“首創(chuàng)AI智能鎖”重構(gòu)智能鎖競爭格局
使用lv_label_set_text釋放內(nèi)存沒對齊是什么原因?qū)е碌模?/a>
官網(wǎng)nrf24l01的例程demo會出現(xiàn)互斥鎖報錯是為什么?
如何在Linux中配置DNS服務器
突然短路 對電機繞組有什么傷害?
自鎖電路工作原理 自鎖電路與常開電路的區(qū)別
自鎖電路使用的元器件介紹
自鎖電路在工業(yè)自動化中的應用
自鎖電路在家居控制中的應用
24路電磁鎖主板在智能存儲系統(tǒng)中的作用
Linux中的用戶與創(chuàng)建

Linux中的傷害/等待互斥鎖介紹
評論