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:
-
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: