1 #include "sleep.h"
2 #include <common/errno.h>
3 #include <time/timer.h>
4 #include <process/process.h>
5 #include <sched/sched.h>
6 #include <mm/slab.h>
7 #include <common/cpu.h>
8 #include <common/glib.h>
9
10 /**
11 * @brief nanosleep定时事件到期后,唤醒指定的进程
12 *
13 * @param pcb 待唤醒的进程的pcb
14 */
nanosleep_handler(void * pcb)15 void nanosleep_handler(void *pcb)
16 {
17 process_wakeup((struct process_control_block *)pcb);
18 }
19
20 /**
21 * @brief 休眠指定时间
22 *
23 * @param rqtp 指定休眠的时间
24 * @param rmtp 返回的剩余休眠时间
25 * @return int
26 */
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)27 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
28 {
29
30 if (rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
31 return -EINVAL;
32
33
34 // 对于小于500us的时间,使用spin/rdtsc来进行定时
35 if (rqtp->tv_nsec < 500000)
36 {
37 uint64_t expired_tsc = rdtsc() + (((uint64_t)rqtp->tv_nsec) * Cpu_tsc_freq) / 1000000000;
38 while (rdtsc() < expired_tsc)
39 ;
40
41 if (rmtp != NULL)
42 {
43 rmtp->tv_nsec = 0;
44 rmtp->tv_sec = 0;
45 }
46 return 0;
47 }
48
49 // 增加定时任务
50 struct timer_func_list_t *sleep_task = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
51 memset(sleep_task, 0, sizeof(struct timer_func_list_t));
52
53 timer_func_init_us(sleep_task, &nanosleep_handler, (void *)current_pcb, rqtp->tv_nsec / 1000);
54
55 timer_func_add(sleep_task);
56
57 current_pcb->state = PROC_INTERRUPTIBLE;
58 current_pcb->flags |= PF_NEED_SCHED;
59 sched();
60
61 // todo: 增加信号唤醒的功能后,设置rmtp
62
63 if (rmtp != NULL)
64 {
65 rmtp->tv_nsec = 0;
66 rmtp->tv_sec = 0;
67 }
68
69 return 0;
70 }
71
72 /**
73 * @brief 睡眠指定时间
74 *
75 * @param usec 微秒
76 * @return int
77 */
usleep(useconds_t usec)78 int usleep(useconds_t usec)
79 {
80 struct timespec ts = {
81 tv_sec : (long int)(usec / 1000000),
82 tv_nsec : (long int)(usec % 1000000) * 1000UL
83 };
84
85 return nanosleep(&ts, NULL);
86 }
87