一、互斥量控制块:在include/rtdef.h中
#ifdef RT_USING_MUTEX
/**
* 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;
#endif
互斥锁控制块也是派生自IPC对象,而IPC对象又派生自内核对象.
value: 大于0时表示此互斥锁可用,小于或等于0都表示此互斥锁当前不可用.
original_priority:保存着互斥锁拥有者的初始优先级,因此rt-thread为了处理互斥锁导致线程优先级翻转的问题,可能会提升互斥锁拥有者线程的优先级,这里保存原先优先级便于恢复。
hold: 表示此互斥锁被同一线程成功take的次数,一般情况下一个线程只会take一次互斥锁,但rt-thread也允许线程重复take同一线程,此时hold的值就用来做记录线程重复take互斥锁的次数,以便在realse同样多次时才去唤醒互斥锁上的挂起的线程。
owner: 表示此互斥锁的拥有者线程,rt-thread只允许同一时间只有一个线程拥有这个互斥锁,此参数就是用来记录此线程的。
二、互斥量相关接口:在src/ipc.c中
创建互斥量:
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag);
可以调用rt_mutex_create函数创建一个互斥量,它的名字有name所指定。创建的互斥量由于指定的flag不同,而有不同的意义: 使用PRIO优先级flag创建的IPC对象,在多个线程等待资源时,将由优先级高的线程优先获得资源。而使用FIFO先进先出flag创建的IPC对象,在多个线程等待资源时,将按照先来先得的顺序获得资源。 删除互斥量:
rt_err_t rt_mutex_delete(rt_mutex_t mutex);
当删除一个互斥量时,所有等待此互斥量的线程都将被唤醒,等待线程获得的返回值是-RT_ERROR。然后系统将该互斥量从内核对象管理器链表中删除并释放互斥量占用的内存空间。
初始化互斥量:
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag);
使用该函数接口时,需指定互斥量对象的句柄(即指向互斥量控制块的指针),互斥量名称以及互斥量标志。互斥量标志可用上面创建互斥量函数里提到的标志。 脱离互斥量:
rt_err_t rt_mutex_detach(rt_mutex_t mutex);
使用该函数接口后,内核先唤醒所有挂在该互斥量上的线程(线程的返回值是-RT_ERROR),然后系统将该互斥量从内核对象管理器链表中删除。
获取互斥量:
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time);
线程通过互斥量申请服务获取互斥量的所有权。线程对互斥量的所有权是独占的,某一个时刻一个互斥量只能被一个线程持有。
如果互斥量没有被其他线程控制,那么申请该互斥量的线程将成功获得该互斥量。如果互斥量已经被当前线程线程控制,则该互斥量的持有计数加1,当前线程也不会挂起等待。如果互斥量已经被其他线程占有,则当前线程在该互斥量上挂起等待,直到其他线程释放它或者等待时间超过指定的超时时间。
当前线程获取互斥量的时间已到还是未成功时,当前线程的thread->error将在定时器的超时回调函数中设置为-RT_ETIMEOUT,而如果另一线程在释放互斥锁rt_mutex_release函数中如果唤醒当前阻塞的线程,在这个过程中thread->error的值将一直保持原样RT_EOK。这就是为什么可以通过判断thread->error的值来得知当前线程是否已经获得互斥量。 释放互斥量:
rt_err_t rt_mutex_release(rt_mutex_t mutex);
使用该函数接口时,只有已经拥有互斥量控制权的线程才能释放它,每释放一次该互斥量,它的持有计数就减1。当该互斥量的持有计数为零时(即持有线程已经释放所有的持有操作),它变为可用,等待在该信号量上的线程将被唤醒。如果线程的运行优先级被互斥量提升,那么当互斥量被释放后,线程恢复为持有互斥量前的优先级。
只有在确保互斥量再没有线程take时,即hold=0时,才去唤醒挂起在此互斥量上的第一个线程,并将此互斥量的拥有者线程设置为此被唤醒的线程,并记录唤醒线程的优先级,因为唤醒线程即将成功拥有互斥量,所以互斥量的hold值再次加1。
控制互斥量:
rt_err_t rt_mutex_control(rt_mutex_t mutex, rt_uint8_t cmd, void *arg);
该函数为空函数。函数只返回-RT_ERROR。