15 KiB
5.4. 互斥量
互斥量又称互斥锁,一般用于共享资源的互斥排他性访问保护。
互斥量在任意时刻处于且仅会处于解锁或锁定状态,当一个任务获取到一把锁后(互斥量锁定),其他任务再尝试获得这把锁时会失败或进入阻塞状态,当该任务释放持有的锁时(互斥量解锁),会唤醒一个正阻塞等待此互斥量的任务,被唤醒的任务将会获取这把锁。
在多任务运行环境中,有些共享资源不具有多线程可重入性,对于这类不希望被多任务同时访问的资源(临界资源),可以采用互斥量来进行保护。
5.4.1. 常量
5.4.1.1. COS_MUTEX_NEST
#define COS_MUTEX_NEST (0x1u << 0)
互斥锁支持嵌套锁。
5.4.2. 类型
5.4.2.1. cos_mutex_t
互斥锁的句柄,代表一个互斥锁。可以通过句柄对互斥锁进行操作,如创建、申请、释放、销毁。
typedef void * cos_mutex_t;
5.4.3. 函数
5.4.3.1. cos_mutex_create
互斥锁创建
函数原型
cos_status_t cos_mutex_create(cos_mutex_t *mutex, char *name, uint32_t options);
描述
创建一个新的互斥锁并初始化,新的互斥锁的句柄由参数mutex返回,后续对互斥锁的操作可以通过参数mutex进行。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
mutex | 出参 | 互斥锁句柄 |
name | 入参 | 互斥锁名称 |
options | 入参 | 互斥锁选项,如是否支持嵌套锁 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_NOMEM | 内存不足 |
COS_ERR_PARAM | 非法参数 |
注意
此函数不能在中断上下文中使用。
5.4.3.2. cos_mutex_init
初始化一个互斥锁
函数原型
cos_status_t cos_mutex_init(cos_mutex_t mutex, char *name, uint32_t options);
描述
初始化一个新的互斥锁。
与创建一个互斥锁类型,区别是互斥锁的控制块内存由调用者传入,一般用于静态分配内存的场景。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
mutex | 入参 | 互斥锁的句柄 |
name | 入参 | 互斥锁名称 |
options | 入参 | 互斥锁选项,如是否支持嵌套锁 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_NOMEM | 内存不足 |
COS_ERR_PARAM | 非法参数 |
注意
此函数不能在中断上下文中使用。
5.4.3.3. cos_mutex_delete
删除动态创建的互斥锁
函数原型
cos_status_t cos_mutex_delete(cos_mutex_t mutex);
描述
销毁互斥锁。系统会唤醒所有等待该互斥锁的任务,返回互斥锁已经被销毁,然后销毁回收其资源。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
mutex | cos_mutex_t | 入参 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
5.4.3.4. cos_mutex_deinit
销毁静态创建的互斥锁
函数原型
cos_status_t cos_mutex_deinit(cos_mutex_t mutex);
描述
销毁静态创建的互斥锁。系统会唤醒所有等待该互斥锁的任务,返回互斥锁已经被销毁。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
mutex | cos_mutex_t | 入参 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
5.4.3.5. cos_mutex_lock
互斥锁上锁
函数原型
cos_status_t cos_mutex_lock(cos_mutex_t mutex, cos_tick_t timeout);
描述
申请互斥锁。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
mutex | 入参 | 互斥锁的句柄 |
timeout | 入参 | 申请超时时间,单位为tick |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_TIMEOUT | 申请超时 |
COS_ERR_DESTROY | 申请的互斥锁已被销毁 |
COS_ERR_MUTEX_NESTING | 已经拥有互斥锁,嵌套申请 |
注意
此函数不能在中断上下文中使用。
5.4.3.6. cos_mutex_unlock
互斥锁解锁
函数原型
cos_status_t cos_mutex_unlock(cos_mutex_t mutex);
描述
互斥锁解锁。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
mutex | 入参 | 互斥锁的句柄 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_DESTROY | 释放的互斥锁已被销毁 |
COS_ERR_MUTEX_NOT_OWNER | 未持有该互斥锁 |
COS_ERR_MUTEX_NESTING | 已经释放互斥锁,但还在嵌套中 |
5.4.4. 示例
5.5. 信号量
信号量是一种实现任务间同步的机制,一般用于多个任务间有限资源竞争访问。
通常来说,一个信号量中持有一个整形数值,用以表示可用资源的数量。当一个信号量的可用资源数量大于0时,任务尝试获取该信号量成功,信号量的可用资源数减一;当一个信号量的可用资源数等于0时,任务尝试获取该信号量失败或进入阻塞状态。信号量的这一模式,当可用资源数为1时,可将其用于资源的互斥访问;或者解决生产者-消费者问题中的资源生产-消费问题。编程实例章节会演示生产者-消费者问题的解决范式。
5.5.1. 常量
5.5.1.1. COS_SEM_NO_MAX
#define COS_SEM_NO_MAX (uint32_t)-1
信号量无最大值,可以用作计数信号量。
5.5.2. 类型
5.5.2.1. cos_sem_t
typedef void * cos_sem_t;
信号量的句柄,代表一个信号量。可以通过句柄对信号量进行操作,如创建、等待、释放、销毁。
5.5.3. 函数
5.5.3.1. cos_sem_create
创建一个信号量
函数原型
cos_status_t cos_sem_create(cos_sem_t *sem, char *name, uint32_t init_count, uint32_t max_count);
描述
创建一个新的信号量并初始化,新的信号量的句柄由参数sem返回,后续对信号量的操作可以通过参数sem进行。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
sem | 出参 | 信号量句柄 |
name | 入参 | 信号量的名称 |
init_count | 入参 | 信号量初始值 |
max_count | 入参 | 信号量最大值 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_NOMEM | 内存不足 |
COS_ERR_PARAM | 非法参数 |
注意
此函数不能在中断上下文中使用。
5.5.3.2. cos_sem_init
初始化一个信号量
函数原型
cos_status_t cos_sem_init(cos_sem_t sem, char *name, uint32_t init_count, uint32_t max_count);
描述
初始化一个信号量
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
sem | 入参 | 信号量句柄 |
name | 入参 | 信号量的名称 |
init_count | 入参 | 信号量初始值 |
max_count | 入参 | 信号量最大值 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_NOMEM | 内存不足 |
COS_ERR_PARAM | 非法参数 |
注意
此函数不能在中断上下文中使用。
5.5.3.3. cos_sem_delete
删除动态创建的信号量
函数原型
cos_status_t cos_sem_delete(cos_sem_t sem);
描述
删除动态创建的信号量。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
sem | 入参 | 信号量的句柄 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
5.5.3.4. cos_sem_deinit
销毁静态创建的信号量
函数原型
cos_status_t cos_sem_deinit(cos_sem_t sem);
描述
销毁静态创建的信号量。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
sem | 入参 | 信号量的句柄 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
5.5.3.5. cos_sem_wait
等待信号量
函数原型
cos_status_t cos_sem_wait(cos_sem_t *sem, cos_tick_t timeout);
描述
等待信号量。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
sem | 入参 | 信号量的句柄 |
timeout | 入参 | 申请超时时间,单位为tick |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_TIMEOUT | 申请超时 |
COS_ERR_DESTROY | 申请的信号量已被销毁 |
注意
此函数不能在中断上下文中使用。
5.5.3.6. cos_sem_release
释放信号量
函数原型
cos_status_t cos_sem_release(cos_sem_t sem);
描述
释放信号量。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
sem | 入参 | 信号量的句柄 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_DESTROY | 释放的信号量已被销毁 |
5.5.3.7. cos_sem_release_all
释放信号量
函数原型
cos_status_t cos_sem_release_all(cos_sem_t sem);
描述
释放信号量,并唤醒所有等待该信号量的任务。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
sem | 入参 | 信号量的句柄 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_DESTROY | 释放的信号量已被销毁 |
5.5.4. 示例
5.6. 事件
事件提供了一种任务间实现同步和信息传递的机制。一般来说,一个事件中包含了一个旗标,这个旗标的每一位表示一个“事件”。
一个任务可以等待一个或者多个“事件”的发生,其他任务在一定的业务条件下可以通过写入特定“事件”唤醒等待此“事件”的任务,实现一种类似信号的编程范式。
5.6.1. 常量
5.6.1.1. COS_EVENT_WAIT_ANY
#define COS_EVENT_WAIT_ANY (0x1u << 0)
等待事件时,用于指定等待其中任意一个。
5.6.1.2. COS_EVENT_WAIT_ALL
#define COS_EVENT_WAIT_ALL (0x1u << 1)
等待事件时,用于指定等待所有事件。
5.6.1.3. COS_EVENT_WAIT_CLR
#define COS_EVENT_WAIT_CLR (0x1u << 2)
等待事件时,用于指定等待后清除该事件。
5.6.1.4. COS_EVENT_RELEASE_KEEP
#define COS_EVENT_RELEASE_KEEP (0x1u << 3)
释放事件时,用于指定释放后是否保留该事件。
5.6.2. 类型
5.6.2.1. cos_event_t
typedef void * cos_event_t;
事件的句柄,代表一个事件。可以通过句柄对事件进行操作,如创建、等待、释放、销毁。
5.6.2.2. cos_event_flag_t
typedef uint32_t cos_event_flag_t;
用于存储事件标志。
5.6.3. 函数
5.6.3.1. cos_event_create
事件创建
函数原型
cos_status_t cos_event_create(cos_event_t *event, char *name, cos_event_flag_t init_flag);
描述
创建一个新的事件并初始化,新的事件的句柄由参数event返回,后续对事件的操作可以通过参数event进行。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
event | 出参 | 事件的句柄 |
name | 入参 | 事件的名称 |
init_flag | 入参 | 事件初始化标志 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_NOMEM | 内存不足 |
注意
此函数不能在中断上下文中使用。
5.6.3.2. cos_event_init
初始化一个事件
函数原型
cos_status_t cos_event_init(cos_event_t event, char *name, cos_event_flag_t init_flag);
描述
初始化一个事件
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
event | 入参 | 事件的句柄 |
name | 入参 | 事件的名称 |
init_flag | 入参 | 事件初始化标志 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_NOMEM | 内存不足 |
注意
此函数不能在中断上下文中使用。
5.6.3.3. cos_event_delete
删除动态创建的事件
函数原型
cos_status_t cos_event_delete(cos_event_t event);
描述
删除动态创建的事件。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
event | 入参 | 事件的句柄 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
5.6.3.4. cos_event_deinit
销毁事件
函数原型
cos_status_t cos_event_deinit(cos_event_t event);
描述
销毁静态创建的事件。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
event | 入参 | 事件的句柄 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
5.6.3.5. cos_event_wait
等待一个或多个事件。
函数原型
cos_status_t cos_event_wait(cos_event_t event, cos_event_flag_t expect_flag, cos_tick_t timeout, cos_event_flag_t *match_flag, uint32_t options);
描述
等待一个或多个事件。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
event | 入参 | 事件的句柄 |
expect_flag | 入参 | 期望等到的事件 |
timeout | 入参 | 申请超时时间,单位为tick |
match_flag | 出参 | 事件的匹配结果 |
options | 入参 | 事件匹配选项(任意一个匹配或者全部匹配) |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_ISR | 在中断上下文中调用 |
COS_ERR_TIMEOUT | 申请超时 |
COS_ERR_DESTROY | 事件已被销毁 |
注意
此函数不能在中断上下文中使用。
5.6.3.6. cos_event_release
释放事件
函数原型
cos_status_t cos_event_release(cos_event_t event, cos_event_flag_t flag, uint32_t options);
描述
释放事件。
参数
参数名称 | 参数方向 | 描述 |
---|---|---|
event | 入参 | 事件的句柄 |
expect_flag | 入参 | 释放的事件 |
options | 入参 | 事件释放选项,释放后是否保留 |
返回值
函数执行成功返回COS_OK,失败则返回错误码(均为负值)。
错误码 | 描述 |
---|---|
COS_ERR | 未知错误 |
COS_ERR_DESTROY | 事件已被销毁 |
5.6.4. 示例