本章节介绍互斥信号量(mutex),该处理方式与信号量不同,互斥信号量的获取是完全互斥的,即同一时刻,mutex只能被一个任务获取。

概述

信号量(sem)按照起始count的配置,存在多个任务获取同一信号量的情况,直到count减为0,则后续任务无法再获取信号量,当然sem的count初值设置为1,同样有互斥的效果。

Mutex的释放必须由占有该mutex的任务进行,其他任务进行释放,会直接返回失败。

为了解决优先级反转问题,高优先级的任务获取mutex时,如果该mutex被某低优先级的任务占用, 会动态提升该低优先级任务的优先级等于高优先级,并且将该优先级值依次传递给该低优先级任务依赖的互斥量关联的任务,以此递归下去。当某任务释放mutex时,会查找该任务的基础优先级,以及获取到的互斥量所阻塞的最高优先级的任务的优先级,取两者中高的优先级来重新设定此任务的优先级。

总原则:高优先级任务被mutex阻塞时,会将占用该mutex的低优先级任务临时提高;mutex释放时,相应任务的优先级需要恢复。

API列表

API名称 说明
aos_mutex_new() 动态创建互斥信号量
aos_mutex_free() 删除互斥信号量
aos_mutex_lock() 请求互斥信号量
aos_mutex_unlock() 释放互斥信号量
aos_mutex_is_valid() 判断是否为有效的互斥信号量

aos_mutex_new()

定义描述
定义 描述
函数原型 int aos_mutex_new(aos_mutex_t *mutex)
描述 动态创建互斥信号量
入参 mutex:互斥信号量结构体指针,需要用户定义一个aos_mutex_t结构体,并把该结构体指针传入
返回值 类型:int,返回成功或失败,返回0表示互斥信号量创建成功,非0表示失败

aos_mutex_free()

定义描述
定义 描述
函数原型 void aos_mutex_free(aos_mutex_t *mutex)
描述 删除互斥信号量
入参 mutex:互斥信号量结构体指针
返回值

aos_mutex_lock()

定义描述
定义 描述
函数原型 int aos_mutex_lock(aos_mutex_t *mutex, unsigned int timeout)
描述 请求互斥信号量
入参
  • mutex:互斥信号量结构体指针
  • timeout:等待超时时间,单位ms。
    • 0表示非阻塞请求,立即返回
    • AOS_WAIT_FOREVER表示永久等待
    • 其他值则等待timeout ms,超时后返回。
    可通过返回值判断是否获得互斥信号量。
返回值 类型:int,返回成功或失败,返回0表示请求互斥信号量成功,非0表示失败

aos_mutex_unlock()

定义描述
定义 描述
函数原型 int aos_mutex_unlock(aos_mutex_t *mutex);
描述 释放互斥信号量
入参 mutex:互斥信号量结构体指针
返回值 类型:int,返回成功或失败,返回0表示释放互斥信号量成功,非0表示失败

aos_mutex_is_valid()

定义描述
定义 描述
函数原型 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() {
    int ret = -1;
    while (1) {
        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() {
    int ret = -1;
    while (1) {
        ret = aos_mutex_is_valid(&test_mutex);
        if (ret != 1) {
            return;
        }
        ret = aos_mutex_lock(&test_mutex, 1000);
        if (ret != 0) {
            continue;
        }
        /*访问临界资源*/
        printf("task2 entry access critical zone\n");

        aos_mutex_unlock(&test_mutex);
    }
}

int application_start(int argc, char *argv[])
{
    int ret = -1;
    ret = aos_mutex_new(&test_mutex);
    if (ret != 0) {
        return;
    }
    aos_task_new("task1", task1_entry, NULL, 512);
    aos_task_new("task2", task2_entry, NULL, 512);
}

使用注意事项

  • 只有获得互斥信号量的任务才能释放互斥信号量,中断也不能释放互斥信号量。
  • 互斥信号量的请求与释放需成对使用,避免只有请求没有释放,导致其他任务无法获得互斥信号量。