time.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* Licensed under BSD-MIT - see LICENSE file for details */
  2. #include <ccan/time/time.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #ifdef DEBUG
  6. #include <ccan/str/str.h>
  7. #define TIME_CHECK(t) time_check((t), __FILE__ ":" stringify(__LINE__))
  8. #else
  9. #define TIME_CHECK(t) (t)
  10. #endif
  11. #if !HAVE_CLOCK_GETTIME && !HAVE_CLOCK_GETTIME_IN_LIBRT
  12. #include <sys/time.h>
  13. struct timespec time_now(void)
  14. {
  15. struct timeval now;
  16. struct timespec ret;
  17. gettimeofday(&now, NULL);
  18. ret.tv_sec = now.tv_sec;
  19. ret.tv_nsec = now.tv_usec * 1000;
  20. return TIME_CHECK(ret);
  21. }
  22. #else
  23. #include <time.h>
  24. struct timespec time_now(void)
  25. {
  26. struct timespec ret;
  27. clock_gettime(CLOCK_REALTIME, &ret);
  28. return TIME_CHECK(ret);
  29. }
  30. #endif /* HAVE_CLOCK_GETTIME || HAVE_CLOCK_GETTIME_IN_LIBRT */
  31. bool time_greater(struct timespec a, struct timespec b)
  32. {
  33. if (TIME_CHECK(a).tv_sec > TIME_CHECK(b).tv_sec)
  34. return true;
  35. else if (a.tv_sec < b.tv_sec)
  36. return false;
  37. return a.tv_nsec > b.tv_nsec;
  38. }
  39. bool time_less(struct timespec a, struct timespec b)
  40. {
  41. if (TIME_CHECK(a).tv_sec < TIME_CHECK(b).tv_sec)
  42. return true;
  43. else if (a.tv_sec > b.tv_sec)
  44. return false;
  45. return a.tv_nsec < b.tv_nsec;
  46. }
  47. bool time_eq(struct timespec a, struct timespec b)
  48. {
  49. return TIME_CHECK(a).tv_sec == TIME_CHECK(b).tv_sec && a.tv_nsec == b.tv_nsec;
  50. }
  51. struct timespec time_sub(struct timespec recent, struct timespec old)
  52. {
  53. struct timespec diff;
  54. diff.tv_sec = TIME_CHECK(recent).tv_sec - TIME_CHECK(old).tv_sec;
  55. if (old.tv_nsec > recent.tv_nsec) {
  56. diff.tv_sec--;
  57. diff.tv_nsec = 1000000000 + recent.tv_nsec - old.tv_nsec;
  58. } else
  59. diff.tv_nsec = recent.tv_nsec - old.tv_nsec;
  60. return TIME_CHECK(diff);
  61. }
  62. struct timespec time_add(struct timespec a, struct timespec b)
  63. {
  64. struct timespec sum;
  65. sum.tv_sec = TIME_CHECK(a).tv_sec + TIME_CHECK(b).tv_sec;
  66. sum.tv_nsec = a.tv_nsec + b.tv_nsec;
  67. if (sum.tv_nsec >= 1000000000) {
  68. sum.tv_sec++;
  69. sum.tv_nsec -= 1000000000;
  70. }
  71. return TIME_CHECK(sum);
  72. }
  73. struct timespec time_divide(struct timespec t, unsigned long div)
  74. {
  75. struct timespec res;
  76. uint64_t rem, ns;
  77. /* Dividing seconds is simple. */
  78. res.tv_sec = TIME_CHECK(t).tv_sec / div;
  79. rem = t.tv_sec % div;
  80. /* If we can't fit remainder * 1,000,000,000 in 64 bits? */
  81. #if 0 /* ilog is great, but we use fp for multiply anyway. */
  82. bits = ilog64(rem);
  83. if (bits + 30 >= 64) {
  84. /* Reduce accuracy slightly */
  85. rem >>= (bits - (64 - 30));
  86. div >>= (bits - (64 - 30));
  87. }
  88. #endif
  89. if (rem & ~(((uint64_t)1 << 30) - 1)) {
  90. /* FIXME: fp is cheating! */
  91. double nsec = rem * 1000000000.0 + t.tv_nsec;
  92. res.tv_nsec = nsec / div;
  93. } else {
  94. ns = rem * 1000000000 + t.tv_nsec;
  95. res.tv_nsec = ns / div;
  96. }
  97. return TIME_CHECK(res);
  98. }
  99. struct timespec time_multiply(struct timespec t, unsigned long mult)
  100. {
  101. struct timespec res;
  102. /* Are we going to overflow if we multiply nsec? */
  103. if (mult & ~((1UL << 30) - 1)) {
  104. /* FIXME: fp is cheating! */
  105. double nsec = (double)t.tv_nsec * mult;
  106. res.tv_sec = nsec / 1000000000.0;
  107. res.tv_nsec = nsec - (res.tv_sec * 1000000000.0);
  108. } else {
  109. uint64_t nsec = t.tv_nsec * mult;
  110. res.tv_nsec = nsec % 1000000000;
  111. res.tv_sec = nsec / 1000000000;
  112. }
  113. res.tv_sec += TIME_CHECK(t).tv_sec * mult;
  114. return TIME_CHECK(res);
  115. }
  116. uint64_t time_to_msec(struct timespec t)
  117. {
  118. uint64_t msec;
  119. msec = TIME_CHECK(t).tv_nsec / 1000000 + (uint64_t)t.tv_sec * 1000;
  120. return msec;
  121. }
  122. uint64_t time_to_usec(struct timespec t)
  123. {
  124. uint64_t usec;
  125. usec = TIME_CHECK(t).tv_nsec / 1000 + (uint64_t)t.tv_sec * 1000000;
  126. return usec;
  127. }
  128. uint64_t time_to_nsec(struct timespec t)
  129. {
  130. uint64_t nsec;
  131. nsec = TIME_CHECK(t).tv_nsec + (uint64_t)t.tv_sec * 1000000000;
  132. return nsec;
  133. }
  134. struct timespec time_from_msec(uint64_t msec)
  135. {
  136. struct timespec t;
  137. t.tv_nsec = (msec % 1000) * 1000000;
  138. t.tv_sec = msec / 1000;
  139. return TIME_CHECK(t);
  140. }
  141. struct timespec time_from_usec(uint64_t usec)
  142. {
  143. struct timespec t;
  144. t.tv_nsec = (usec % 1000000) * 1000;
  145. t.tv_sec = usec / 1000000;
  146. return TIME_CHECK(t);
  147. }
  148. struct timespec time_from_nsec(uint64_t nsec)
  149. {
  150. struct timespec t;
  151. t.tv_nsec = nsec % 1000000000;
  152. t.tv_sec = nsec / 1000000000;
  153. return TIME_CHECK(t);
  154. }
  155. struct timespec time_check(struct timespec t, const char *abortstr)
  156. {
  157. if (t.tv_sec < 0 || t.tv_nsec >= 1000000000) {
  158. if (abortstr) {
  159. fprintf(stderr, "%s: malformed time %li.%09li\n",
  160. abortstr,
  161. (long)t.tv_sec, (long)t.tv_nsec);
  162. abort();
  163. } else {
  164. struct timespec old = t;
  165. if (t.tv_nsec >= 1000000000) {
  166. t.tv_sec += t.tv_nsec / 1000000000;
  167. t.tv_nsec %= 1000000000;
  168. }
  169. if (t.tv_sec < 0)
  170. t.tv_sec = 0;
  171. fprintf(stderr, "WARNING: malformed time"
  172. " %li seconds %li ns converted to %li.%09li.\n",
  173. (long)old.tv_sec, (long)old.tv_nsec,
  174. (long)t.tv_sec, (long)t.tv_nsec);
  175. }
  176. }
  177. return t;
  178. }