DragonOS/kernel/time/sleep.c

87 lines
1.9 KiB
C
Raw Normal View History

2022-07-12 04:01:51 +00:00
#include "sleep.h"
#include <common/errno.h>
#include <time/timer.h>
#include <process/process.h>
#include <sched/sched.h>
#include <mm/slab.h>
2022-07-27 13:19:59 +00:00
#include <common/cpu.h>
#include <common/glib.h>
2022-07-12 04:01:51 +00:00
/**
* @brief nanosleep定时事件到期后
*
* @param pcb pcb
*/
void nanosleep_handler(void *pcb)
{
process_wakeup((struct process_control_block *)pcb);
}
/**
* @brief
*
* @param rqtp
* @param rmtp
* @return int
*/
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
2022-07-27 13:19:59 +00:00
if (rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
2022-07-12 04:01:51 +00:00
return -EINVAL;
2022-07-27 13:19:59 +00:00
// 对于小于500us的时间使用spin/rdtsc来进行定时
if (rqtp->tv_nsec < 500000)
2022-07-27 13:19:59 +00:00
{
uint64_t expired_tsc = rdtsc() + (((uint64_t)rqtp->tv_nsec) * Cpu_tsc_freq) / 1000000000;
2022-07-27 13:19:59 +00:00
while (rdtsc() < expired_tsc)
;
2022-07-27 13:19:59 +00:00
if (rmtp != NULL)
{
rmtp->tv_nsec = 0;
rmtp->tv_sec = 0;
}
return 0;
}
2022-07-12 04:01:51 +00:00
// 增加定时任务
struct timer_func_list_t *sleep_task = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
memset(sleep_task, 0, sizeof(struct timer_func_list_t));
timer_func_init_us(sleep_task, &nanosleep_handler, (void *)current_pcb, rqtp->tv_nsec / 1000);
2022-07-27 13:19:59 +00:00
2022-07-12 04:01:51 +00:00
timer_func_add(sleep_task);
current_pcb->state = PROC_INTERRUPTIBLE;
current_pcb->flags |= PF_NEED_SCHED;
sched();
2022-07-12 04:01:51 +00:00
// todo: 增加信号唤醒的功能后设置rmtp
if (rmtp != NULL)
{
rmtp->tv_nsec = 0;
rmtp->tv_sec = 0;
}
return 0;
2022-07-18 13:19:45 +00:00
}
/**
* @brief
*
* @param usec
* @return int
*/
int usleep(useconds_t usec)
{
struct timespec ts = {
tv_sec : (long int)(usec / 1000000),
tv_nsec : (long int)(usec % 1000000) * 1000UL
};
return nanosleep(&ts, NULL);
}