time.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
  4. * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  5. * Copyright (C) 2012-2014 Cisco Systems
  6. * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com)
  7. */
  8. #include <stddef.h>
  9. #include <errno.h>
  10. #include <signal.h>
  11. #include <time.h>
  12. #include <sys/time.h>
  13. #include <kern_util.h>
  14. #include <os.h>
  15. #include <string.h>
  16. static timer_t event_high_res_timer = 0;
  17. static inline long long timeval_to_ns(const struct timeval *tv)
  18. {
  19. return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) +
  20. tv->tv_usec * UM_NSEC_PER_USEC;
  21. }
  22. static inline long long timespec_to_ns(const struct timespec *ts)
  23. {
  24. return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec;
  25. }
  26. long long os_persistent_clock_emulation(void)
  27. {
  28. struct timespec realtime_tp;
  29. clock_gettime(CLOCK_REALTIME, &realtime_tp);
  30. return timespec_to_ns(&realtime_tp);
  31. }
  32. /**
  33. * os_timer_create() - create an new posix (interval) timer
  34. */
  35. int os_timer_create(void)
  36. {
  37. timer_t *t = &event_high_res_timer;
  38. if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1)
  39. return -1;
  40. return 0;
  41. }
  42. int os_timer_set_interval(unsigned long long nsecs)
  43. {
  44. struct itimerspec its;
  45. its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC;
  46. its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC;
  47. its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC;
  48. its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC;
  49. if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1)
  50. return -errno;
  51. return 0;
  52. }
  53. int os_timer_one_shot(unsigned long long nsecs)
  54. {
  55. struct itimerspec its = {
  56. .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC,
  57. .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC,
  58. .it_interval.tv_sec = 0,
  59. .it_interval.tv_nsec = 0, // we cheat here
  60. };
  61. timer_settime(event_high_res_timer, 0, &its, NULL);
  62. return 0;
  63. }
  64. /**
  65. * os_timer_disable() - disable the posix (interval) timer
  66. */
  67. void os_timer_disable(void)
  68. {
  69. struct itimerspec its;
  70. memset(&its, 0, sizeof(struct itimerspec));
  71. timer_settime(event_high_res_timer, 0, &its, NULL);
  72. }
  73. long long os_nsecs(void)
  74. {
  75. struct timespec ts;
  76. clock_gettime(CLOCK_MONOTONIC,&ts);
  77. return timespec_to_ns(&ts);
  78. }
  79. /**
  80. * os_idle_sleep() - sleep for a given time of nsecs
  81. * @nsecs: nanoseconds to sleep
  82. */
  83. void os_idle_sleep(unsigned long long nsecs)
  84. {
  85. struct timespec ts = {
  86. .tv_sec = nsecs / UM_NSEC_PER_SEC,
  87. .tv_nsec = nsecs % UM_NSEC_PER_SEC
  88. };
  89. /*
  90. * Relay the signal if clock_nanosleep is interrupted.
  91. */
  92. if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL))
  93. deliver_alarm();
  94. }