sdk-hwV1.3/lichee/melis-v3.0/source/ekernel/components/aw/waitqueue/waitqueue.c

89 lines
1.9 KiB
C

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <aw_list.h>
#include <hal_interrupt.h>
#include <hal_thread.h>
#include "./include/aw_waitqueue.h"
static int default_wake_function(wait_queue_t *curr, void *key)
{
(void)key;
return rt_sem_release(&curr->sem);
}
int autoremove_wake_function(wait_queue_t *wait, void *key)
{
int ret = default_wake_function(wait, key);
if (!ret)
list_del_init(&wait->task_list);
/* return 0 if wake up successed */
return ret;
}
void init_wait_entry(wait_queue_t *wait, unsigned int flags)
{
wait->flags = flags;
wait->priv = kthread_self();;
wait->func = autoremove_wake_function;
INIT_LIST_HEAD(&wait->task_list);
rt_sem_init(&wait->sem, "wq", 0, RT_IPC_FLAG_FIFO);
}
long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait)
{
unsigned long flags;
long ret = 0;
flags = hal_spin_lock_irqsave(&q->lock);
if (list_empty(&wait->task_list)) {
if (wait->flags & WQ_FLAG_EXCLUSIVE)
__add_wait_queue_tail(q, wait);
else
__add_wait_queue(q, wait);
}
else {
ret = -EALREADY;
}
hal_spin_unlock_irqrestore(&q->lock, flags);
return ret;
}
void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
{
unsigned long flags;
if (!list_empty_careful(&wait->task_list)) {
flags = hal_spin_lock_irqsave(&q->lock);
list_del_init(&wait->task_list);
hal_spin_unlock_irqrestore(&q->lock, flags);
}
rt_sem_detach(&wait->sem);
}
static void __wake_up_common(wait_queue_head_t *q, int nr_exclusive,
void *key)
{
wait_queue_t *curr, *next;
list_for_each_entry_safe(curr, next, &q->head, task_list) {
unsigned flags = curr->flags;
if (!curr->func(curr, key) &&
(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
break;
}
}
void __wake_up(wait_queue_head_t *q, int nr_exclusive, void *key)
{
unsigned long flags;
flags = hal_spin_lock_irqsave(&q->lock);
__wake_up_common(q, nr_exclusive, key);
hal_spin_unlock_irqrestore(&q->lock, flags);
}