sleep.c 1.9 KB

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