互斥锁是管理临界资源的一种有效手段。因为互斥锁是独占的,所以在一个时刻只允许一个线程占有互斥锁,利用这个性质来实现共享资源的互斥锁保护。任何时刻只允许一个线程获得互斥量对象,未能够获得互斥量对象的线程被挂起在该互斥量的等待线程队列上。
1 互斥锁控制块
/**
* Mutual exclusion (mutex) structure
*/
struct rt_mutex
{
struct rt_ipc_object parent; /**< inherit from ipc_object *///派生自IPC对象
rt_uint16_t value; /**< value of mutex *///此互斥锁的值
rt_uint8_t original_priority; /**< priority of last thread hold the mutex *///原始优先级,即此互斥锁拥有者线程的优先级
rt_uint8_t hold; /**< numbers of thread hold the mutex *///此互斥锁当前已被几个线程(同一线程)take的次数
struct rt_thread *owner; /**< current owner of mutex *///此互斥锁的拥有者线程
};
typedef struct rt_mutex *rt_mutex_t;
由上述源码可知,互斥锁控制块也是派生自IPC对象,而IPC对象又派生自内核对象.
value大于1时表示此互斥锁可用,小于或等于0都表示此互斥锁当前不可用.
original_priority保存着互斥锁拥有者的初始优先级,因此rt-thread为了处理互斥锁导致线程优先级翻转的问题,可能会提升互斥锁拥有者线程的优先级,这里保存原先优先级便于恢复.
hold表示此互斥锁被同一线程成功take的次数,一般情况下一个线程只会take一次互斥锁,但rt-thread也允许线程重复take同一线程,此时hold的值就用来做记录线程重复take互斥锁的次数,以便在realse同样多次时才去唤醒互斥锁上的挂起的线程.
而owner表示此互斥锁的拥有者线程,rt-thread只允许同一时间只有一个线程拥有这个互斥锁,此参数就是用来记录此线程的.
2 初始化及创建互斥锁
2.1 初始化互斥锁
/**
* This function will initialize a mutex and put it under control of resource
* management.
*
* @param mutex the mutex object
* @param name the name of mutex
* @param flag the flag of mutex
*
* @return the operation status, RT_EOK on successful
*/
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
{
RT_ASSERT(mutex != RT_NULL);
/* init object */
rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name);//初始化互斥锁的内核对象
/* init ipc object */
rt_ipc_object_init(&(mutex->parent));//初始化互斥锁的IPC对象
mutex->value = 1;//设置互斥锁值初始化为1
mutex->owner = RT_NULL;//初始化互斥锁当前没有拥有者
mutex->original_priority = 0xFF;//初始化互斥锁原始优先级为255,即拥有者线程的优先级
mutex->hold = 0;//初化为当前互斥锁的被take的次数为0(同一线程)
/* set flag */
mutex->parent.parent.flag = flag;//设置互斥锁的内核对象标志
return RT_EOK;
}
注意互斥锁在初始化时其值value被初始化为1,即默认情况下其是可用的.在其被take之后value值减1变为0时才不可用.
2.2 创建互斥锁
/**
* This function will create a mutex from system resource
*
* @param name the name of mutex
* @param flag the flag of mutex
*
* @return the created mutex, RT_NULL on error happen
*
* @see rt_mutex_init
*/
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
{
struct rt_mutex *mutex;
RT_DEBUG_NOT_IN_INTERRUPT;//确保此函数不是在ISR中使用
/* allocate object */
mutex = (rt_mutex_t)rt_object_allocate(RT_Object_Class_Mutex, name);//动态分配一个互斥锁
if (m