互斥锁
概述
互斥信号量(mutex)的获取是完全互斥的,即同一时刻,mutex只能被一个任务获取。而信号量(sem)按照起始count的配置,存在多个任务获取同一信号量的情况,直到count减为0,则后续任务无法再获取信号量,当然sem的count初值设置为1,同样有互斥的效果。 Mutex的释放必须由占有该mutex的任务进行,其他任务进行释放,会直接返回失败。 为了解决优先级反转问题,高优先级的任务获取mutex时,如果该mutex被某低优先级的任务占用, 会动态提升该低优先级任务的优先级等于高优先级,并且将该优先级值依次传递给该低优先级任务依赖的互斥量关联的任务,以此递归下去。当某任务释放mutex时,会查找该任务的基础优先级,以及获取到的互斥量所阻塞的最高优先级的任务的优先级,取两者中高的优先级来重新设定此任务的优先级。总的原则就是,高优先级任务被mutex阻塞时,会将占用该mutex的低优先级任务临时提高;mutex释放时,相应任务的优先级需要恢复。
接口定义
动态创建互斥信号量
int aos_mutex_new(aos_mutex_t *mutex)
动态创建互斥信号量
参数:
- mutex:互斥信号量结构体指针,需要用户定义一个aos_mutex_t结构体,并把该结构体指针传入
返回值:
- 类型:int 返回成功或失败;返回0表示互斥信号量创建成功,非0表示失败。
删除互斥信号量
void aos_mutex_free(aos_mutex_t *mutex)
删除互斥信号量
参数:
- mutex:互斥信号量结构体指针
返回值:
- 无
请求互斥信号量
int aos_mutex_lock(aos_mutex_t *mutex, unsigned int timeout)
请求互斥信号量
参数:
- mutex:互斥信号量结构体指针
- timeout:等待超时时间,单位ms。0表示非阻塞请求,立即返回;AOS_WAIT_FOREVER表示永久等待;其他值则等待timeout ms,超时后返回。可通过返回值判断是否获得互斥信号量。
返回值:
- 类型:int 返回成功或失败;返回0表示请求互斥信号量成功,非0表示失败。
释放互斥信号量
int aos_mutex_unlock(aos_mutex_t *mutex);
释放互斥信号量
参数:
- mutex:互斥信号量结构体指针
返回值:
- 类型:int 返回成功或失败;返回0表示释放互斥信号量成功,非0表示失败。
判断是否为有效的互斥信号量
int aos_mutex_is_valid(aos_mutex_t *mutex)
判断是否为有效的互斥信号量
参数:
- mutex:互斥信号量结构体指针
返回值:
- 类型:int 返回有效或无效; 返回0表示mutex为无效互斥信号量,返回1表示mutex为有效的互斥信号量。
示例代码
#include <aos/aos.h>
aos_mutex_t test_mutex;
void task1_entry(void)
{
int ret = -1;
while (1) {
/* 判断mutex是否有效 */
ret = aos_mutex_is_valid(&test_mutex);
if (ret != 1) {
return;
}
/* 永久请求互斥信号量 */
ret = aos_mutex_lock(&test_mutex, AOS_WAIT_FOREVER);
if (ret != 0) {
continue;
}
/* 访问临界资源 */
printf("task1 entry access critical zone\n");
/* 释放互斥信号量 */
aos_mutex_unlock(&test_mutex);
}
}
void task2_entry(void)
{
int ret = -1;
while (1) {
/* 判断mutex是否有效 */
ret = aos_mutex_is_valid(&test_mutex);
if (ret != 1) {
return;
}
/* 请求互斥信号量,timeout为1000ms */
ret = aos_mutex_lock(&test_mutex, 1000);
if (ret != 0) {
continue;
}
/*访问临界资源*/
printf("task2 entry access critical zone\n");
/* 释放互斥信号量 */
aos_mutex_unlock(&test_mutex);
}
}
int test_mutex_start(void)
{
int ret = -1;
/* 创建一个mutex */
ret = aos_mutex_new(&test_mutex);
if (ret != 0) {
return;
}
/* 创建task1 & task2 */
aos_task_new("task1", task1_entry, NULL, 512);
aos_task_new("task2", task2_entry, NULL, 512);
}