Files
mkrtos-real/mkrtos_knl/knl/sleep.c

127 lines
2.7 KiB
C

/**
* @file sleep.c
* @author your name (1358745329@qq.com)
* @brief 线程休眠支持
* @version 0.1
* @date 2025-02-12
*
* @copyright Copyright (c) 2025
*
*/
#include <thread.h>
#include <types.h>
#include <spinlock.h>
#include <slist.h>
#include <init.h>
#include "sleep.h"
#include "arch.h"
static slist_head_t wait_list;
static spinlock_t lock;
static inline void thread_wait_entry_init(thread_wait_entry_t *entry,
thread_t *th, mword_t times)
{
slist_init(&entry->node);
entry->th = th;
entry->times = times;
// entry->times_debug = 0;
}
static void thread_timeout_init(void)
{
slist_init(&wait_list);
spinlock_init(&lock);
}
INIT_KOBJ(thread_timeout_init);
/**
* @brief 必须在中断中调用
*
*/
void thread_check_timeout(void)
{
thread_wait_entry_t *pos;
slist_foreach_not_next(
pos, (slist_head_t *)&wait_list,
node)
{
thread_wait_entry_t *next = slist_next_entry(
pos, (slist_head_t *)wait_list,
node);
if (pos->times != 0)
{
pos->times--;
if (pos->times == 0)
{
assert(pos->th->status == THREAD_SUSPEND);
slist_del(&pos->node);
if (thread_get_ipc_state(pos->th) != THREAD_IPC_ABORT)
{
thread_ready(pos->th, TRUE);
}
}
}
pos = next;
}
}
/**
* @brief 从休眠队列中删除
*
* @param th
*/
thread_wait_entry_t *thread_sleep_del(thread_t *th)
{
assert(cpulock_get_status());
thread_wait_entry_t *pos = NULL;
slist_foreach_not_next(
pos, (slist_head_t *)&wait_list,
node)
{
// assert(pos->th->status == THREAD_SUSPEND);
thread_wait_entry_t *next = slist_next_entry(
pos, (slist_head_t *)wait_list,
node);
if (pos->th == th)
{
slist_del(&pos->node);
return pos;
}
pos = next;
}
return NULL;
}
void thread_sleep_del_and_wakeup(thread_t *th)
{
assert(cpulock_get_status());
thread_wait_entry_t *wait;
wait = thread_sleep_del(th);
if (wait == NULL)
{
return;
}
thread_ready(wait->th, TRUE);
}
/**
* @brief 放到休眠队列中
*
* @param tick
* @return umword_t 返回剩余的休眠时间
*/
umword_t thread_sleep(umword_t tick)
{
assert(cpulock_get_status());
thread_wait_entry_t entry;
thread_t *cur_th = thread_get_current();
umword_t status;
thread_wait_entry_init(&entry, cur_th, tick);
status = spinlock_lock(&lock);
slist_add(&wait_list, &entry.node);
thread_suspend(cur_th);
spinlock_set(&lock, status);
preemption();
return entry.times;
}