Files
RTOS/Kernel/SingleCore/os_mutex.c
T
2026-05-19 11:49:22 +08:00

105 lines
2.6 KiB
C

#include <os_mutex.h>
#include "os_critical.h"
void os_mutex_init(os_mutex_t* self){
self->owner = 0;
os_waitobject_init(&self->wait_obj);
}
void os_mutex_destroy(os_mutex_t* self){
OS_ASSERT(self->owner==0);
}
os_err_t os_mutex_trylock(os_mutex_t* self){
os_critical_enter();
os_task_t* p_thread = os_task_self();
if(self->owner!=0){ // 已经被锁定了
if(self->owner==p_thread){ // 是当前任务锁定的
os_critical_leave();
return OS_ERR_OK;
}
// 当前任务不是 owner,判断优先级是否反转
if(os_priority_cmp(p_thread->curr_priority, self->owner->curr_priority)==OS_PRIORITY_CMP_HIGH){
// 当前任务的优先级更高,优先级反转了,提升 owner 优先级
self->owner->curr_priority = p_thread->curr_priority;
}
os_critical_leave();
return OS_ERR_FAIL;
}
// 到这里说明没有owner
self->owner = (os_task_t*)p_thread;
os_critical_leave();
return OS_ERR_OK;
}
os_err_t os_mutex_lock(os_mutex_t* self){
while(os_mutex_trylock(self)!=OS_ERR_OK){
os_task_yield(); // 未获得锁,主动让出
}
return OS_ERR_OK;
}
os_err_t os_mutex_timed_lock(os_mutex_t* self, os_tick_t ticks){
if(os_mutex_trylock(self)!=OS_ERR_OK){
os_critical_enter();
os_task_t* p_task = os_task_self();
os_critical_leave();
return os_waitobject_timed_wait(&self->wait_obj, p_task, ticks);
}
return OS_ERR_OK;
}
void os_mutex_unlock(os_mutex_t* self){
os_critical_enter();
os_task_t* p_task = os_task_self();
if(self->owner != p_task){
// 只有 owner 才能 unlock
os_critical_leave();
os_task_yield();
return;
}
if(self->owner->curr_priority!=self->owner->init_priority) {
self->owner->curr_priority = self->owner->init_priority; /* 恢复优先级 */
}
self->owner = 0;
os_critical_leave();
os_waitobject_notify_all(&self->wait_obj);
}
void os_mutex_unlock_one(os_mutex_t* self){
os_critical_enter();
os_task_t* p_task = os_task_self();
if(self->owner != p_task){
// 只有 owner 才能 unlock
os_critical_leave();
os_task_yield();
return;
}
if(self->owner->curr_priority!=self->owner->init_priority) {
self->owner->curr_priority = self->owner->init_priority; /* 恢复优先级 */
}
self->owner = 0;
// 将所有等待任务加入就绪表,等待当前任务用时完成后进行调度
os_critical_leave();
os_waitobject_notify_one(&self->wait_obj);
}