sleep.c 1.7 KB

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