1. 适用范围

    本文档可作为Linux驱动源码或库源码快速移植至SylixOS的参考。

2. 互斥信号量

2.1 概念简介

   互斥信号量(Linux中亦称为互斥锁)是因为多线程对临界区访问而存在的。只有拥有互斥对象的线程才具有访问资源的权限,当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。

   互斥信号量可以理解为初始值为TRUE的带优先级天花板和优先级继承机制(意在解决优先级反转问题)的二进制信号量。

   因为互斥信号量需要记录拥有者线程和调整优先级,所以中断服务程序不能等待和释放互斥信号量,并且只有互斥信号量的拥有者线程才有权释放互斥信号量。


2.2 Linux接口与SylixOS接口对应关系

   Linux中操作互斥信号量的API与SylixOS中操作互斥信号量的API对应关系如表 2-1所示。

2-1互斥信号量接口对应关系

Linux中接口SylixOS中接口功能说明
mutex_initAPI_SemaphoreMCreate创建互斥信号量
mutex_destroyAPI_SemaphoreMDelete销毁互斥信号量
mutex_lockAPI_SemaphoreMPend阻塞申请互斥信号量
mutex_trylockAPI_SemaphoreMPend非阻塞申请互斥信号量
mutex_unlockAPI_SemaphoreMPost释放互斥信号量
mutex_is_lockedAPI_SemaphoreMStatus判断互斥信号量状态

 

3. 详细说明

3.1 互斥信号量结构

   在Linux中互斥信号量是使用struct mutex表示的,结构如程序清单 3-1所示,而在SylixOS中,互斥信号量是通过LW_HANDLE类型的互斥信号量句柄表示。

程序清单 3-1 Linuxstruct 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库时采用。