Files
RTOS/Kernel/SingleCore/os_condv.c
T

180 lines
4.9 KiB
C
Raw Normal View History

2026-05-19 11:49:22 +08:00
#include <os_condv.h>
#include "os_critical.h"
#include "os_rdy_list.h"
#include "os_sched.h"
#include "os_timewheel.h"
void os_condv_init(os_condv_t* self){
os_list_init(&self->wait_list);
}
void os_condv_destroy(os_condv_t* self){
OS_ASSERT(os_list_is_empty(&self->wait_list));
}
void os_condv_wait(os_condv_t* self, os_mutex_t* lock){
os_mutex_unlock(lock);
os_critical_enter();
os_task_t* p_thread = os_task_self();
os_list_insert_before(&self->wait_list, &p_thread->node);
p_thread->state = kOsTaskState_Wait;
os_critical_leave();
os_sched();
os_mutex_lock(lock);
}
void os_condv_notify_one(os_condv_t* self){
os_critical_enter();
if(os_list_is_empty(&self->wait_list)){
os_critical_leave();
return;
}
os_list_node_t* p = self->wait_list.next;
os_task_t* thread = os_list_member_of(p, os_task_t, node);
os_list_remove(&thread->node);
os_rdy_list_insert(thread);
os_critical_leave();
os_sched();
}
void os_condv_notify_all(os_condv_t* self){
os_critical_enter();
for(os_list_node_t* p = self->wait_list.next; p!=&self->wait_list; ){
os_task_t* thread = os_list_member_of(p, os_task_t, node);
p = p->next;
os_list_remove(&thread->node);
os_rdy_list_insert(thread);
}
os_critical_leave();
os_sched();
}
static void os_condv_ontimeout(os_timer_t* p_timer){
os_task_t* p_thread = os_list_member_of(p_timer, os_task_t, timer);
os_list_remove(&p_thread->node); // 从 WAIT 列表中移除
p_thread->errors = OS_ERR_TIMEOUT; // 标记超时了
os_rdy_list_insert(p_thread); // 加入就绪表
}
os_err_t os_condv_timed_wait(os_condv_t* self, os_mutex_t* lock, os_tick_t ticks){
os_err_t err = OS_ERR_OK;
os_mutex_unlock(lock);
{
os_critical_enter();
os_task_t* p_thread = os_task_self();
os_list_insert_before(&self->wait_list, &p_thread->node);
p_thread->state = kOsTaskState_Wait;
if(ticks==0){
// TIMEOUT
p_thread->errors = OS_ERR_TIMEOUT;
os_critical_leave();
os_mutex_lock(lock);
return OS_ERR_TIMEOUT;
}else if(ticks!=OS_WAIT_INFINITY){
// 定时
p_thread->errors = OS_ERR_OK;
os_timewheel_add_timer((os_timer_t*)&p_thread->timer, os_condv_ontimeout, 0, ticks, OS_TIMER_FLAG_ONCE);
}
os_critical_leave();
}
os_sched();
{
// 返回当前线程
os_critical_enter();
os_task_t* p_task = os_task_self();
err = p_task->errors;
if(err!=OS_ERR_OK){
p_task->errors = OS_ERR_OK;
os_critical_leave();
os_mutex_lock(lock);
return err;
}
os_critical_leave();
}
os_mutex_lock(lock);
return err;
}
os_err_t os_condv_wait_until(os_condv_t* self, os_mutex_t* lock, os_tick_t ticks){
os_err_t err = OS_ERR_OK;
os_mutex_unlock(lock);
{
os_critical_enter();
os_task_t* p_thread = os_task_self();
os_list_insert_before(&self->wait_list, &p_thread->node);
p_thread->state = kOsTaskState_Wait;
if(ticks==0){
// TIMEOUT
p_thread->errors = OS_ERR_TIMEOUT;
os_critical_leave();
os_mutex_lock(lock);
return OS_ERR_TIMEOUT;
}else if(ticks!=OS_WAIT_INFINITY){
// 定时
p_thread->errors = OS_ERR_OK;
os_timewheel_add_until_timer((os_timer_t*)&p_thread->timer
, os_condv_ontimeout, 0
, ticks, OS_TIMER_FLAG_ONCE);
}
os_critical_leave();
}
os_sched();
{
os_critical_enter();
os_task_t* p_task = os_task_self();
err = p_task->errors;
if(err!=OS_ERR_OK){
p_task->errors = OS_ERR_OK;
os_critical_leave();
os_mutex_lock(lock);
return err;
}
os_critical_leave();
}
os_mutex_lock(lock);
return err;
}
void os_condv_notify_one_in_isr(os_condv_t* self){
os_critical_enter_in_isr();
if(os_list_is_empty(&self->wait_list)){
os_critical_leave();
return;
}
os_list_node_t* p = self->wait_list.next;
os_task_t* thread = os_list_member_of(p, os_task_t, node);
os_list_remove(&thread->node);
os_rdy_list_insert(thread);
// thread->state = OS_TASK_STATE_READY;
os_critical_leave_in_isr();
os_sched_in_isr();
}
void os_condv_notify_all_in_isr(os_condv_t* self){
os_critical_enter_in_isr();
for(os_list_node_t* p = self->wait_list.next; p!=&self->wait_list; ){
os_task_t* thread = os_list_member_of(p, os_task_t, node);
os_list_remove(&thread->node);
p = p->next;
os_rdy_list_insert(thread);
// thread->state = OS_TASK_STATE_READY;
}
os_critical_leave_in_isr();
os_sched_in_isr();
}