X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/43c43c058ededea929645fef68d15820eed1f5e9..0fd474df7001837bde53da0e42e83081827c9641:/lunaix-os/kernel/ds/waitq.c diff --git a/lunaix-os/kernel/ds/waitq.c b/lunaix-os/kernel/ds/waitq.c index 7045e36..e67c44d 100644 --- a/lunaix-os/kernel/ds/waitq.c +++ b/lunaix-os/kernel/ds/waitq.c @@ -1,54 +1,112 @@ #include #include +#include #include +#include -void -pwait(waitq_t* queue) +static inline void must_inline +__try_wait(bool check_stall) +{ + unsigned int nstall; + waitq_t* current_wq = ¤t_thread->waitqueue; + if (waitq_empty(current_wq)) { + return; + } + + block_current_thread(); + + if (!check_stall) { + // if we are not checking stall, we give up voluntarily + yield_current(); + } else { + // otherwise, treat it as being preempted by kernel + preempt_current(); + } + + // In case of SIGINT-forced awaken + llist_delete(¤t_wq->waiters); +} + +static inline void must_inline +__pwait(waitq_t* queue, bool check_stall) { // prevent race condition. - cpu_disable_interrupt(); + no_preemption(); - waitq_t* current_wq = &__current->waitqueue; - assert(llist_empty(¤t_wq->waiters)); + prepare_to_wait(queue); + __try_wait(check_stall); - llist_append(&queue->waiters, ¤t_wq->waiters); + set_preemption(); +} - block_current(); - sched_yieldk(); +void +pwait(waitq_t* queue) +{ + __pwait(queue, false); +} - cpu_enable_interrupt(); +void +pwait_check_stall(waitq_t* queue) +{ + __pwait(queue, true); } void pwake_one(waitq_t* queue) { - if (llist_empty(&queue->waiters)) { + if (waitq_empty(queue)) { return; } waitq_t* wq = list_entry(queue->waiters.next, waitq_t, waiters); - struct proc_info* proc = container_of(wq, struct proc_info, waitqueue); + struct thread* thread = container_of(wq, struct thread, waitqueue); - assert(proc->state == PS_BLOCKED); - proc->state = PS_READY; + assert(thread->state == PS_BLOCKED); + thread->state = PS_READY; llist_delete(&wq->waiters); } void pwake_all(waitq_t* queue) { - if (llist_empty(&queue->waiters)) { + if (waitq_empty(queue)) { return; } - struct proc_info* proc; + struct thread* thread; waitq_t *pos, *n; llist_for_each(pos, n, &queue->waiters, waiters) { - proc = container_of(pos, struct proc_info, waitqueue); + thread = container_of(pos, struct thread, waitqueue); - assert(proc->state == PS_BLOCKED); - proc->state = PS_READY; + if (thread->state == PS_BLOCKED) { + thread->state = PS_READY; + } + + // already awaken or killed by other event, just remove it llist_delete(&pos->waiters); } -} \ No newline at end of file +} + +void +prepare_to_wait(waitq_t* queue) +{ + assert(current_thread); + + waitq_t* current_wq = ¤t_thread->waitqueue; + assert(llist_empty(¤t_wq->waiters)); + + llist_append(&queue->waiters, ¤t_wq->waiters); +} + +void +try_wait() +{ + __try_wait(false); +} + +void +try_wait_check_stall() +{ + __try_wait(true); +}