time.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com)
  3. * Licensed under the GPL
  4. */
  5. #include <stddef.h>
  6. #include <errno.h>
  7. #include <signal.h>
  8. #include <time.h>
  9. #include <sys/time.h>
  10. #include "kern_constants.h"
  11. #include "os.h"
  12. #include "user.h"
  13. int set_interval(void)
  14. {
  15. int usec = UM_USEC_PER_SEC / UM_HZ;
  16. struct itimerval interval = ((struct itimerval) { { 0, usec },
  17. { 0, usec } });
  18. if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1)
  19. return -errno;
  20. return 0;
  21. }
  22. int timer_one_shot(int ticks)
  23. {
  24. unsigned long usec = ticks * UM_USEC_PER_SEC / UM_HZ;
  25. unsigned long sec = usec / UM_USEC_PER_SEC;
  26. struct itimerval interval;
  27. usec %= UM_USEC_PER_SEC;
  28. interval = ((struct itimerval) { { 0, 0 }, { sec, usec } });
  29. if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1)
  30. return -errno;
  31. return 0;
  32. }
  33. /**
  34. * timeval_to_ns - Convert timeval to nanoseconds
  35. * @ts: pointer to the timeval variable to be converted
  36. *
  37. * Returns the scalar nanosecond representation of the timeval
  38. * parameter.
  39. *
  40. * Ripped from linux/time.h because it's a kernel header, and thus
  41. * unusable from here.
  42. */
  43. static inline long long timeval_to_ns(const struct timeval *tv)
  44. {
  45. return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) +
  46. tv->tv_usec * UM_NSEC_PER_USEC;
  47. }
  48. long long disable_timer(void)
  49. {
  50. struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
  51. if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
  52. printk(UM_KERN_ERR "disable_timer - setitimer failed, "
  53. "errno = %d\n", errno);
  54. return timeval_to_ns(&time.it_value);
  55. }
  56. long long os_nsecs(void)
  57. {
  58. struct timeval tv;
  59. gettimeofday(&tv, NULL);
  60. return timeval_to_ns(&tv);
  61. }
  62. #ifdef UML_CONFIG_NO_HZ
  63. static int after_sleep_interval(struct timespec *ts)
  64. {
  65. return 0;
  66. }
  67. #else
  68. static inline long long timespec_to_us(const struct timespec *ts)
  69. {
  70. return ((long long) ts->tv_sec * UM_USEC_PER_SEC) +
  71. ts->tv_nsec / UM_NSEC_PER_USEC;
  72. }
  73. static int after_sleep_interval(struct timespec *ts)
  74. {
  75. int usec = UM_USEC_PER_SEC / UM_HZ;
  76. long long start_usecs = timespec_to_us(ts);
  77. struct timeval tv;
  78. struct itimerval interval;
  79. /*
  80. * It seems that rounding can increase the value returned from
  81. * setitimer to larger than the one passed in. Over time,
  82. * this will cause the remaining time to be greater than the
  83. * tick interval. If this happens, then just reduce the first
  84. * tick to the interval value.
  85. */
  86. if (start_usecs > usec)
  87. start_usecs = usec;
  88. tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC,
  89. .tv_usec = start_usecs % UM_USEC_PER_SEC });
  90. interval = ((struct itimerval) { { 0, usec }, tv });
  91. if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1)
  92. return -errno;
  93. return 0;
  94. }
  95. #endif
  96. extern void alarm_handler(int sig, struct sigcontext *sc);
  97. void idle_sleep(unsigned long long nsecs)
  98. {
  99. struct timespec ts;
  100. /*
  101. * nsecs can come in as zero, in which case, this starts a
  102. * busy loop. To prevent this, reset nsecs to the tick
  103. * interval if it is zero.
  104. */
  105. if (nsecs == 0)
  106. nsecs = UM_NSEC_PER_SEC / UM_HZ;
  107. ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC,
  108. .tv_nsec = nsecs % UM_NSEC_PER_SEC });
  109. if (nanosleep(&ts, &ts) == 0)
  110. alarm_handler(SIGVTALRM, NULL);
  111. after_sleep_interval(&ts);
  112. }