查看: 838|回复: 0

[技术交流] Alios之互斥机制(mutex)

[复制链接]

74

主题

169

帖子

573

积分

利尔达员工

Rank: 9Rank: 9Rank: 9

积分
573
发表于 2019-12-9 13:55:50 | 显示全部楼层 |阅读模式
1、前言
信号量的处理核心原则在于,如果任务能获得信号量则返回成功,如果获取不到,则任务按照优先级挂载到sem的pend列表,等待信号量释放,或者等待超时时间到自动唤醒,或者立马及时上报获取错误。
与信号量相比,mutex的区别主要在于:
(1)mutex的获取完全互斥,即同一个时刻,mutex只能被一个任务获取。
(2)信号量的释放可以由其他任务上下文进行释放,并且可以选择释放单个任务或者所有阻塞任务。mutex的释放必须占用该mutex的任务进行,其他任务进行释放,会直接返回失败。
(3)为了解决优先级反转问题,高优先级的任务获取mutex时,如果该mutex被低优先级的任务占用,会动态提升该低优先级任务的优先级至等于高的优先级。并且该优先级值依次传递给该低优先级任务的依赖的互斥量关联的任务,依次递归下去。当某任务释放mutex时,会查找该任务的基础优先级,以及获取到的互斥量所阻塞的最高优先级的任务,取其优先级的最小值,来重新设定此任务的优先级。总的原则就是,高优先级任务被mutex阻塞时,会将占用该mutex的低优先级任务的优先级临时提高;mutex被释放时,相应任务的优先级需要恢复。
2、互斥量的创建与删除
(1)mutex创建
函数原型:kstart_t krhino_mutex_create(kmutex_t mutex, const name_t name),mutex的创建默认都是静态内存方式,mutex的创建主要目的在于初始化kmutex_t管理结构。管理结构体kmutex_t最主要的数据成员包括:
blk_obj:等待该mutex的任务队列,此处和sem阻塞队列管理类似;
mutex_task:当前占用该mutex的任务;
mutex_list:对挂接在占用该mutex的任务的信号量链表进行管理,任务会获取到多个mutex。
(2) mutex删除
函数原型:kstart_t krhino_mutex_del(kmutex_t *mutex)
删除的主要目的包括:
从该互斥量的阻塞队列blk_obj里面,释放被阻塞的任务。此释放机制的处理过程和sem一样;
从获取到该互斥量的任务的mutex_list列表中删除此任务;
重置该任务量的任务优先级。重置优先级参考为:该任务创建时的基础优先级,该任务获取到的剩余mutex列表所阻塞的最高优先级任务的优先级,取两者中的较高优先级。
3、互斥量的获取与释放
(1)mutex获取
函数原型:kstart_t krhino_mutex_lock(kmutex_t mutex, tick_t ticks)
某个mutex同时只能由一个任务占用,同任务多次获取会造成mutex嵌套。
获取互斥量的步骤包括:
①检测该mutex是否已经被当前任务获取,如果是,则表明进入mutex获取嵌套,增加嵌套次数mutex -> owner_nested,返回RHINO_MUTEX_OWNER_NESTED;
②如果该互斥量未有任务占用,即mutex->mutex_task为NULL,则当前任务顺利获取mutex,并将其挂载到任务的互斥量链表mutex_list进行管理,并返回成功;
③如果当前互斥量已经被其他任务占用,且其优先级比当前active任务优先级低,则动态提升该占用该互斥量的任务优先级等于当前active任务的优先级;并且递归修改其他关联任务的优先级。
④将当前任务放入mutex的阻塞队列blk_list进行管理,并且如果设置了超时,咋加入tick队列g_tick_head等待超时处理;
⑤调用core_sched进行任务调度。
(2)mutex释放
函数原型:kstart_t krhino_mutex_unlock(kmutex_t
mutex)
mutex的释放只能由获取到该mutex的任务自己进行释放,其处理步骤包括:
①检测当前调用krhino_mutex_unlock是否为获取到该mutex的任务,如果不是,返回失败;
②检测mutex的占用嵌套次数mutex->owner_nested,如果不为0,则计数减一,并直接返回,表示未释放成功。因此krhino_mutex_unlock调用次数需要和krhino_mutex_lock一致,才能最终释放成功;
③将此mutex从当前任务获取的mutex_list中删除,并且重新设置任务优先级。设置的优先级参考该任务原始创建的优先级以及剩余列表中阻塞所有任务的最高优先级;
④从该mutex中取出优先级最高的一个阻塞任务并唤醒,并调用core_sched进行任务切换。
4、互斥量的任务优先级变迁图
任务优先级的动态调整主要出现在以下两个阶段:
(1)调用krhino_mutex_lock时,如果此mutex被另一低优先级任务占用,则此时需要提升低优先级任务的优先级至当前任务的优先级;并且此低优先级任务依赖的mutex所占用的另一任务优先级也需要提升,并按照此原则递归处理。

(2)调用krhino_mutex_unlock时,需要恢复此任务的优先级,取值为任务创建时的原始优先级和任务获取mutex列表所阻塞的所有任务优先级的最小值,并且递归修改拥有当前任务依赖的mutex的任务优先级。



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表