#include #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(); }