1. 適用範圍
本文檔可作爲Linux驅動源碼或庫源碼快速移植至SylixOS的參考。
2. 互斥信號量
2.1 概念簡介
互斥信號量(Linux中亦稱爲互斥鎖)是因爲多線程對臨界區訪問而存在的。只有擁有互斥對象的線程才具有訪問資源的權限,當前佔據資源的線程在任務處理完後應將擁有的互斥對象交出,以便其他線程在獲得後得以訪問資源。
互斥信號量可以理解爲初始值爲TRUE的帶優先級天花板和優先級繼承機制(意在解決優先級反轉問題)的二進制信號量。
因爲互斥信號量需要記錄擁有者線程和調整優先級,所以中斷服務程序不能等待和釋放互斥信號量,並且只有互斥信號量的擁有者線程纔有權釋放互斥信號量。
2.2 Linux接口與SylixOS接口對應關係
Linux中操作互斥信號量的API與SylixOS中操作互斥信號量的API對應關係如表 2-1所示。
表 2-1互斥信號量接口對應關係
Linux中接口 | SylixOS中接口 | 功能說明 |
mutex_init | API_SemaphoreMCreate | 創建互斥信號量 |
mutex_destroy | API_SemaphoreMDelete | 銷燬互斥信號量 |
mutex_lock | API_SemaphoreMPend | 阻塞申請互斥信號量 |
mutex_trylock | API_SemaphoreMPend | 非阻塞申請互斥信號量 |
mutex_unlock | API_SemaphoreMPost | 釋放互斥信號量 |
mutex_is_locked | API_SemaphoreMStatus | 判斷互斥信號量狀態 |
3. 詳細說明
3.1 互斥信號量結構
在Linux中互斥信號量是使用struct mutex表示的,結構如程序清單 3-1所示,而在SylixOS中,互斥信號量是通過LW_HANDLE類型的互斥信號量句柄表示。
程序清單 3-1 Linux的struct mutex結構
struct mutex { /* 1: unlocked, 0: locked, negative: locked, possible waiters */ atomic_t count; spinlock_t wait_lock; struct list_head wait_list; #if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP) struct task_struct *owner; #endif #ifdef CONFIG_MUTEX_SPIN_ON_OWNER void *spin_mlock; #endif #ifdef CONFIG_DEBUG_MUTEXES const char *name; void *magic; #endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif };
3.2 創建互斥信號量
Linux : void mutex_init (struct mutex *mutex); SylixOS: LW_HANDLE Lw_SemaphoreM_Create (CPCHAR pcName, UINT8 ucCeilingPriority, ULONG ulOption, LW_OBJECT_ID *pulId);
Linux:
創建一個互斥信號量只需要定義一個struct mutex變量並調用mutex_init即可,Linux系統會自己爲mutex命名。
創建成功後,申請和釋放互斥信號量時可以直接使用該已定義的mutex變量。
SylixOS:
創建互斥信號量時需要指定信號量的名稱,並且手動設置選項。
創建成功後,申請和釋放互斥信號量時需要使用Lw_SemaphoreM_Create返回的信號量句柄。
3.3 銷燬互斥信號量
Linux : void mutex_init (struct mutex *mutex); SylixOS: LW_HANDLE Lw_SemaphoreM_Create (CPCHAR pcName, UINT8 ucCeilingPriority, ULONG ulOption, LW_OBJECT_ID *pulId);
Linux:
銷燬一個互斥信號量是將mutex變量的地址傳入。
SylixOS:
銷燬一個互斥信號量是將互斥信號量句柄地址傳入。
3.4 阻塞申請互斥信號量
Linux : void mutex_lock (struct mutex *mutex); SylixOS: ULONG Lw_SemaphoreM_Wait (LW_HANDLE ulId, ULONG ulTimeout);
Linux:
mutex_lock的基本邏輯爲:如果互斥鎖可以獲得,則直接獲取,跳出;否則進入循環反覆測試互斥鎖的狀態。
在循環中,判斷如果可以獲取到互斥鎖,則退出循環;否則設置當前進程的狀態爲不可中斷狀態,解鎖自身的自旋鎖,進入睡眠狀態。待被調度喚醒時,再獲得自身的自旋鎖,進入新一次的查詢其自身狀態(該互斥鎖的狀態)的循環。
SylixOS:
如果將參數ulTimeout設置爲LW_OPTION_WAIT_INFINITE,則使用效果和Linux的mutex_lock相同。
3.5 非阻塞申請互斥信號量
Linux : int mutex_trylock (struct mutex *mutex); SylixOS: ULONG Lw_SemaphoreM_Wait (LW_HANDLE ulId, ULONG ulTimeout);
Linux:
mutex_trylock用於不等待地嘗試獲取互斥鎖,如果成功獲取則返回1,否則返回0,不等待。
SylixOS:
將ulTimeout設置爲LW_OPTION_NOT_WAIT,則使用效果和mutex_trylock相同。
3.6 釋放互斥信號量
Linux : int mutex_unlock (struct mutex *mutex); SylixOS: ULONG Lw_SemaphoreM_Post (LW_HANDLE ulId);
Linux:
釋放一個互斥信號量是將mutex變量的地址傳入。
SylixOS:
銷燬一個互斥信號量是將互斥信號量句柄傳入。
3.7 判斷互斥信號量狀態
Linux : int mutex_is_locked (struct mutex *mutex); SylixOS: ULONG Lw_SemaphoreM_Status (LW_HANDLE ulId, BOOL *pbValue, ULONG *pulOption, ULONG *pulThreadBlockNum); ULONG Lw_SemaphoreM_StatusEx (LW_HANDLE ulId, BOOL *pbValue, ULONG *pulOption, ULONG *pulThreadBlockNum, LW_HANDLE *pulOwnerId);
Linux:
mutex_is_locked可以返回一個mutex當前狀態,返回1表示互斥量已經被申請,0則表示未被申請。
SylixOS:
獲取互斥量的當前狀態,需要使用Lw_SemaphoreM_Status或Lw_SemaphoreM_StatusEx接口。這兩個函數參數pbValue可以返回當前互斥信號量的狀態。
4. 總結
本文章說明了Linux驅動源碼或庫源碼中使用到互斥信號量時,怎樣快速移植到SylixOS中,並沒有詳細講解各接口實現時原理有何不同,目前這種替換關係已經在移植gpu庫時採用。