成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

鴻蒙輕內核M核源碼分析系列九互斥鎖Mutex

開發
本文帶領大家一起剖析了鴻蒙輕內核的互斥鎖模塊的源代碼,包含互斥鎖的結構體、互斥鎖池初始化、互斥鎖創建刪除、申請釋放等。

[[401244]]

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

多任務環境下會存在多個任務訪問同一公共資源的場景,而有些公共資源是非共享的臨界資源,只能被獨占使用。鴻蒙輕內核使用互斥鎖來避免這種沖突,互斥鎖是一種特殊的二值性信號量,用于實現對臨界資源的獨占式處理。另外,互斥鎖可以解決信號量存在的優先級翻轉問題。用互斥鎖處理臨界資源的同步訪問時,如果有任務訪問該資源,則互斥鎖為加鎖狀態。此時其他任務如果想訪問這個臨界資源則會被阻塞,直到互斥鎖被持有該鎖的任務釋放后,其他任務才能重新訪問該公共資源,此時互斥鎖再次上鎖,如此確保同一時刻只有一個任務正在訪問這個臨界資源,保證了臨界資源操作的完整性。

接下來,我們看下互斥鎖的結構體,互斥鎖初始化,互斥鎖常用操作的源代碼。

1、互斥鎖結構體定義和常用宏定義

1.1 互斥鎖結構體定義

在文件kernel\include\los_mux.h定義的互斥鎖控制塊結構體LosMuxCB,源代碼如下,結構體成員的解釋見注釋部分。

  1. typedef struct { 
  2.     UINT8 muxStat;       /**< 互斥鎖狀態:OS_MUX_UNUSED, OS_MUX_USED */ 
  3.     UINT16 muxCount;     /**< 鎖被持有的次數 */ 
  4.     UINT32 muxID;        /**< 互斥鎖Id */ 
  5.     LOS_DL_LIST muxList; /**< 互斥鎖雙向鏈表 */ 
  6.     LosTaskCB *owner;    /**< 當前持有鎖的任務 */ 
  7.     UINT16 priority;     /**< 當前持有鎖的任務的優先級,為避免優先級翻轉,可能會更改任務的優先級,此時有備份的作用 */ 
  8. } LosMuxCB; 

 1.2 互斥鎖常用宏定義

系統支持創建多少互斥鎖是根據開發板情況使用宏LOSCFG_BASE_IPC_MUX_LIMIT定義的,互斥鎖muxId是UINT32類型的,muxId取值為[0,LOSCFG_BASE_IPC_MUX_LIMIT),表示互斥鎖池中各個的互斥鎖的編號。

  1. ⑴    #define OS_MUX_UNUSED 0 
  2.  
  3. ⑵    #define OS_MUX_USED   1 
  4.  
  5. ⑶    #define GET_MUX(muxid) (((LosMuxCB *)g_allMux) + (muxid)) 
  6.  
  7. ⑷    #define GET_MUX_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosMuxCB, muxList) 

 2、互斥鎖初始化

互斥鎖在內核中默認開啟,用戶可以通過宏LOSCFG_BASE_IPC_MUX進行關閉。開啟互斥鎖的情況下,在系統啟動時,在kernel\src\los_init.c中調用OsMuxInit()進行互斥鎖模塊初始化。

下面,我們分析下互斥鎖初始化的代碼。

⑴初始化雙向循環鏈表g_unusedMuxList,維護未使用的互斥鎖。

⑵處如果沒有設置宏LOSCFG_BASE_IPC_MUX,則返回錯誤碼。

⑶為互斥鎖申請內存,如果申請失敗,則返回錯誤LOS_ERRNO_MUX_NO_MEMORY

⑷循環每一個互斥鎖進行初始化,為每一個互斥鎖節點指定索引muxID,muxStat為未使用OS_MUX_UNUSED,并把互斥鎖節點插入未使用互斥鎖雙向鏈表g_unusedMuxList。

(5)如果開啟了互斥鎖調測開關,則調用函數UINT32 OsMuxDbgInit(VOID)進行初始化。

  1. LITE_OS_SEC_TEXT_INIT UINT32 OsMuxInit(VOID) 
  2.     LosMuxCB *muxNode = NULL
  3.     UINT32 index
  4.  
  5. ⑴  LOS_ListInit(&g_unusedMuxList); 
  6.  
  7. ⑵  if (LOSCFG_BASE_IPC_MUX_LIMIT == 0) { 
  8.         return LOS_ERRNO_MUX_MAXNUM_ZERO; 
  9.     } 
  10.  
  11. ⑶  g_allMux = (LosMuxCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_MUX_LIMIT * sizeof(LosMuxCB))); 
  12.     if (g_allMux == NULL) { 
  13.         return LOS_ERRNO_MUX_NO_MEMORY; 
  14.     } 
  15.  
  16. ⑷  for (index = 0; index < LOSCFG_BASE_IPC_MUX_LIMIT; index++) { 
  17.         muxNode = ((LosMuxCB *)g_allMux) + index
  18.         muxNode->muxID = index
  19.         muxNode->muxStat = OS_MUX_UNUSED; 
  20.         LOS_ListTailInsert(&g_unusedMuxList, &muxNode->muxList); 
  21.     } 
  22.     return LOS_OK; 

 3、互斥鎖常用操作

3.1 互斥鎖創建

我們可以使用函數UINT32 LOS_MuxCreate(UINT32 *muxHandle)來創建互斥鎖,下面通過分析源碼看看如何創建互斥鎖的。

⑴判斷未使用互斥鎖鏈表g_unusedMuxList是否為空,如果沒有可以使用的互斥鎖,跳轉到錯誤碼。

⑵處如果g_unusedMuxList不為空,則獲取第一個可用的互斥鎖節點,接著從雙向鏈表g_unusedMuxList中刪除,然后調用GET_MUX_LIST宏函數獲取LosMuxCB *muxCreated,接著初始化創建的互斥鎖信息,包含持有鎖的次數、狀態、優先級等信息。

⑶初始化雙向鏈表&muxCreated->muxList,阻塞在這個互斥鎖上的任務會掛在這個鏈表上。

⑷賦值給輸出參數*muxHandle,后續程序使用這個互斥鎖Id對互斥鎖進行其他操作。

  1. LITE_OS_SEC_TEXT_INIT UINT32 LOS_MuxCreate(UINT32 *muxHandle) 
  2.     UINT32 intSave; 
  3.     LosMuxCB *muxCreated = NULL
  4.     LOS_DL_LIST *unusedMux = NULL
  5.     UINT32 errNo; 
  6.     UINT32 errLine; 
  7.  
  8.     if (muxHandle == NULL) { 
  9.         return LOS_ERRNO_MUX_PTR_NULL; 
  10.     } 
  11.  
  12.     intSave = LOS_IntLock(); 
  13. ⑴  if (LOS_ListEmpty(&g_unusedMuxList)) { 
  14.         LOS_IntRestore(intSave); 
  15.         OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_ALL_BUSY); 
  16.     } 
  17.  
  18. ⑵  unusedMux = LOS_DL_LIST_FIRST(&(g_unusedMuxList)); 
  19.     LOS_ListDelete(unusedMux); 
  20.     muxCreated = (GET_MUX_LIST(unusedMux)); 
  21.     muxCreated->muxCount = 0; 
  22.     muxCreated->muxStat = OS_MUX_USED; 
  23.     muxCreated->priority = 0; 
  24.     muxCreated->owner = (LosTaskCB *)NULL
  25. ⑶  LOS_ListInit(&muxCreated->muxList); 
  26. ⑷  *muxHandle = (UINT32)muxCreated->muxID; 
  27.     LOS_IntRestore(intSave); 
  28.     OsHookCall(LOS_HOOK_TYPE_MUX_CREATE, muxCreated); 
  29.     return LOS_OK; 
  30. ERR_HANDLER: 
  31.     OS_RETURN_ERROR_P2(errLine, errNo); 

 3.2 互斥鎖刪除

我們可以使用函數LOS_MuxDelete(UINT32 muxHandle)來刪除互斥鎖,下面通過分析源碼看看如何刪除互斥鎖的。

⑴處判斷互斥鎖muxHandle是否超過LOSCFG_BASE_IPC_MUX_LIMIT,如果超過則返回錯誤碼。

⑵獲取互斥鎖控制塊LosMuxCB *muxDeleted。

⑶如果要刪除的互斥鎖處于未使用狀態,跳轉到錯誤標簽進行處理。

⑷如果互斥鎖的持有者數量不為空,不允許刪除,跳轉到錯誤標簽進行處理。

⑸把刪除的互斥鎖回收到未使用互斥鎖雙向鏈表g_unusedMuxList,然后更新為未使用狀態。

  1. LITE_OS_SEC_TEXT_INIT UINT32 LOS_MuxDelete(UINT32 muxHandle) 
  2.     UINT32 intSave; 
  3.     LosMuxCB *muxDeleted = NULL
  4.     UINT32 errNo; 
  5.     UINT32 errLine; 
  6.  
  7. ⑴  if (muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) { 
  8.         OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_INVALID); 
  9.     } 
  10.  
  11. ⑵  muxDeleted = GET_MUX(muxHandle); 
  12.     intSave = LOS_IntLock(); 
  13. ⑶  if (muxDeleted->muxStat == OS_MUX_UNUSED) { 
  14.         LOS_IntRestore(intSave); 
  15.         OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_INVALID); 
  16.     } 
  17.  
  18. ⑷  if ((!LOS_ListEmpty(&muxDeleted->muxList)) || muxDeleted->muxCount) { 
  19.         LOS_IntRestore(intSave); 
  20.         OS_GOTO_ERR_HANDLER(LOS_ERRNO_MUX_PENDED); 
  21.     } 
  22.  
  23. ⑸  LOS_ListAdd(&g_unusedMuxList, &muxDeleted->muxList); 
  24.     muxDeleted->muxStat = OS_MUX_UNUSED; 
  25.  
  26.     LOS_IntRestore(intSave); 
  27.  
  28.     OsHookCall(LOS_HOOK_TYPE_MUX_DELETE, muxDeleted); 
  29.     return LOS_OK; 
  30. ERR_HANDLER: 
  31.     OS_RETURN_ERROR_P2(errLine, errNo); 

 3.3 互斥鎖申請

我們可以使用函數UINT32 LOS_MuxPend(UINT32 muxHandle, UINT32 timeout)來請求互斥鎖,需要的2個參數分別是互斥鎖Id和等待時間timeout,單位Tick,取值范圍為[0, LOS_WAIT_FOREVER]。

下面通過分析源碼看看如何請求互斥鎖的。

申請互斥鎖時首先會進行互斥鎖Id、參數的合法性校驗,這些比較簡單。

⑴處代碼獲取當前運行的任務,

⑵如果互斥鎖沒有被持有,更新互斥鎖的持有次數、持有者信息和優先級,完成互斥鎖的申請。

⑶處如果互斥鎖的持有次數不為0,并且被當前任務持有,可以持有次數加1,再次嵌套持有,完成互斥鎖的申請。如果代碼執行到,

⑷說明申請的互斥鎖被其他任務持有著,此時如果等待時間為0,則申請失敗返回。

⑸處更新當前任務阻塞在申請的互斥鎖上。

⑹處代碼表示在當前申請互斥鎖的任務優先級高于持有互斥鎖的任務優先級時,修改持有互斥鎖的優先級為當前任務的優先級。通過這樣的修改,可以避免優先級翻轉。

⑺處調用函數OsSchedTaskWait()更新當前任務的狀態,設置等待時間,然后調用函數LOS_Schedule觸發任務調度。后續程序暫時不再執行,需要等到可以獲取互斥鎖或者時間超時。

如果時間超時或者申請到互斥鎖,系統重新調度到執行此任務,程序從⑻處繼續執行。如果是時間超時,⑼處更新任務狀態并返回碼,申請互斥鎖失敗。如果成功申請到互斥鎖,執行⑽,返回成功。

  1. LITE_OS_SEC_TEXT UINT32 LOS_MuxPend(UINT32 muxHandle, UINT32 timeout) 
  2.     UINT32 intSave; 
  3.     LosMuxCB *muxPended = NULL
  4.     UINT32 retErr; 
  5.     LosTaskCB *runningTask = NULL
  6.  
  7.     if (muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) { 
  8.         OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID); 
  9.     } 
  10.  
  11.     muxPended = GET_MUX(muxHandle); 
  12.     intSave = LOS_IntLock(); 
  13.     retErr = OsMuxValidCheck(muxPended); 
  14.     if (retErr) { 
  15.         goto ERROR_MUX_PEND; 
  16.     } 
  17.  
  18. ⑴  runningTask = (LosTaskCB *)g_losTask.runTask; 
  19. ⑵  if (muxPended->muxCount == 0) { 
  20.         muxPended->muxCount++; 
  21.         muxPended->owner = runningTask; 
  22.         muxPended->priority = runningTask->priority; 
  23.         LOS_IntRestore(intSave); 
  24.         goto HOOK; 
  25.     } 
  26.  
  27. ⑶  if (muxPended->owner == runningTask) { 
  28.         muxPended->muxCount++; 
  29.         LOS_IntRestore(intSave); 
  30.         goto HOOK; 
  31.     } 
  32.  
  33. ⑷  if (!timeout) { 
  34.         retErr = LOS_ERRNO_MUX_UNAVAILABLE; 
  35.         goto ERROR_MUX_PEND; 
  36.     } 
  37.  
  38. ⑸  runningTask->taskMux = (VOID *)muxPended; 
  39.  
  40. ⑹  if (muxPended->owner->priority > runningTask->priority) { 
  41.         (VOID)OsSchedModifyTaskSchedParam(muxPended->owner, runningTask->priority); 
  42.     } 
  43.  
  44. ⑺  OsSchedTaskWait(&muxPended->muxList, timeout); 
  45.  
  46.     LOS_IntRestore(intSave); 
  47.     OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended); 
  48.     LOS_Schedule(); 
  49.  
  50. ⑻  intSave = LOS_IntLock(); 
  51.     if (runningTask->taskStatus & OS_TASK_STATUS_TIMEOUT) { 
  52. ⑼      runningTask->taskStatus &= (~OS_TASK_STATUS_TIMEOUT); 
  53.         retErr = LOS_ERRNO_MUX_TIMEOUT; 
  54.         goto ERROR_MUX_PEND; 
  55.     } 
  56.  
  57.     LOS_IntRestore(intSave); 
  58. ⑽  return LOS_OK; 
  59.  
  60. HOOK: 
  61.     OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended); 
  62.     return LOS_OK; 
  63.  
  64. ERROR_MUX_PEND: 
  65.     LOS_IntRestore(intSave); 
  66.     OS_RETURN_ERROR(retErr); 

 3.4 互斥鎖釋放

我們可以使用函數UINT32 LOS_MuxPost(UINT32 muxHandle)來釋放互斥鎖,下面通過分析源碼看看如何釋放互斥鎖的。

釋放互斥鎖時首先會進行互斥鎖Id、參數的合法性校驗,這些比較簡單,自行閱讀即可。

⑴處如果要釋放的互斥鎖沒有被持有、或者不是被當前任務持有,返回錯誤碼。

⑵互斥鎖的持有數量減1,如果不為0,當前任務嵌套持有該互斥鎖,不需要調度,返回釋放互斥鎖成功。如果釋放一次后,當前任務不再持有互斥鎖,則執行。

⑶如果持有互斥鎖任務的優先級不等于互斥鎖的備份優先級低,需要恢復當前任務的優先級。

⑷如果互斥鎖上還有其他任務阻塞著,獲取阻塞的任務resumedTask,該任務成功獲取到互斥鎖,然后執行。

⑸更新互斥鎖的持有信息。執行⑹更新任務resumedTask的狀態,然后調用函數LOS_Schedule觸發調度。

  1. LITE_OS_SEC_TEXT UINT32 LOS_MuxPost(UINT32 muxHandle) 
  2.     UINT32 intSave; 
  3.     LosMuxCB *muxPosted = GET_MUX(muxHandle); 
  4.     LosTaskCB *resumedTask = NULL
  5.     LosTaskCB *runningTask = NULL
  6.  
  7.     intSave = LOS_IntLock(); 
  8.  
  9.     if ((muxHandle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT) || 
  10.         (muxPosted->muxStat == OS_MUX_UNUSED)) { 
  11.         LOS_IntRestore(intSave); 
  12.         OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID); 
  13.     } 
  14.  
  15.     runningTask = (LosTaskCB *)g_losTask.runTask; 
  16. ⑴  if ((muxPosted->muxCount == 0) || (muxPosted->owner != runningTask)) { 
  17.         LOS_IntRestore(intSave); 
  18.         OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID); 
  19.     } 
  20.  
  21. ⑵  if (--(muxPosted->muxCount) != 0) { 
  22.         LOS_IntRestore(intSave); 
  23.         OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted); 
  24.         return LOS_OK; 
  25.     } 
  26.  
  27. ⑶  if ((muxPosted->owner->priority) != muxPosted->priority) { 
  28.         (VOID)OsSchedModifyTaskSchedParam(muxPosted->owner, muxPosted->priority); 
  29.     } 
  30.  
  31. ⑷  if (!LOS_ListEmpty(&muxPosted->muxList)) { 
  32.         resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(muxPosted->muxList))); 
  33.  
  34. ⑸      muxPosted->muxCount = 1; 
  35.         muxPosted->owner = resumedTask; 
  36.         muxPosted->priority = resumedTask->priority; 
  37.         resumedTask->taskMux = NULL
  38.  
  39. ⑹      OsSchedTaskWake(resumedTask); 
  40.  
  41.         LOS_IntRestore(intSave); 
  42.         OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted); 
  43.         LOS_Schedule(); 
  44.     } else { 
  45.         LOS_IntRestore(intSave); 
  46.     } 
  47.  
  48.     return LOS_OK; 

 小結

本文帶領大家一起剖析了鴻蒙輕內核的互斥鎖模塊的源代碼,包含互斥鎖的結構體、互斥鎖池初始化、互斥鎖創建刪除、申請釋放等。

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區
相關推薦

2021-05-27 09:43:56

鴻蒙HarmonyOS應用

2021-06-04 09:57:49

鴻蒙HarmonyOS應用

2022-01-10 15:31:44

鴻蒙HarmonyOS應用

2022-01-12 10:50:23

鴻蒙HarmonyOS應用

2021-10-20 16:08:57

鴻蒙HarmonyOS應用

2021-05-17 09:28:59

鴻蒙HarmonyOS應用

2021-06-04 14:15:10

鴻蒙HarmonyOS應用

2021-05-08 15:14:50

鴻蒙HarmonyOS應用

2021-05-31 20:30:55

鴻蒙HarmonyOS應用

2022-04-13 11:02:12

鴻蒙事件模塊事件Event

2022-03-03 18:28:28

Harmony進程任務管理模塊

2022-03-11 20:23:14

鴻蒙源碼分析進程管理

2021-05-11 09:54:55

鴻蒙HarmonyOS應用

2021-06-09 09:48:01

鴻蒙HarmonyOS應用

2021-05-21 09:25:11

鴻蒙HarmonyOS應用

2021-07-06 09:45:03

鴻蒙HarmonyOS應用

2021-09-22 14:36:32

鴻蒙HarmonyOS應用

2021-05-12 09:45:20

鴻蒙HarmonyOS應用

2021-04-30 15:06:34

鴻蒙HarmonyOS應用

2022-01-14 08:39:47

鴻蒙HarmonyOS應用
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人小视频在线免费观看 | 国产剧情一区 | 国产清纯白嫩初高生在线播放视频 | 国产精品免费在线 | 精品一区二区在线观看 | 五月综合激情婷婷 | 中文字幕国产 | 久久亚洲一区二区三区四区 | 在线观看成人小视频 | 淫片专区 | 一区二区不卡视频 | 黄 色 毛片免费 | 国产不卡在线 | 五月综合激情网 | 成人二区 | 91av视频在线观看 | 免费看国产一级特黄aaaa大片 | 国产精品免费在线 | 精品伦精品一区二区三区视频 | 99成人在线视频 | 能看的av | 国产一区二区三区四区 | 久久久国产精品视频 | 亚洲福利一区 | 成人免费视频网站 | 欧美黄色小视频 | www.久久99 | 中日韩av| 91毛片在线看 | 日本激情视频中文字幕 | 日韩精品视频在线播放 | 亚洲视频一区在线观看 | 久久国产亚洲 | 亚洲日本免费 | 欧美一级在线免费 | 男人的天堂久久 | 成人亚洲精品 | 亚洲综合色站 | 久久噜噜噜精品国产亚洲综合 | 国产乱码久久久 | 成人在线观看欧美 |