deadline.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* Computing deadlines for timeouts.
  2. Copyright (C) 2017-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <net-internal.h>
  16. #include <assert.h>
  17. #include <limits.h>
  18. #include <stdio.h>
  19. #include <stdint.h>
  20. #include <time.h>
  21. struct deadline_current_time
  22. __deadline_current_time (void)
  23. {
  24. struct deadline_current_time result;
  25. if (__clock_gettime (CLOCK_MONOTONIC, &result.current) != 0)
  26. {
  27. struct timeval current_tv;
  28. if (__gettimeofday (&current_tv, NULL) == 0)
  29. __libc_fatal ("Fatal error: gettimeofday system call failed\n");
  30. result.current.tv_sec = current_tv.tv_sec;
  31. result.current.tv_nsec = current_tv.tv_usec * 1000;
  32. }
  33. assert (result.current.tv_sec >= 0);
  34. return result;
  35. }
  36. /* A special deadline value for which __deadline_is_infinite is
  37. true. */
  38. static inline struct deadline
  39. infinite_deadline (void)
  40. {
  41. return (struct deadline) { { -1, -1 } };
  42. }
  43. struct deadline
  44. __deadline_from_timeval (struct deadline_current_time current,
  45. struct timeval tv)
  46. {
  47. assert (__is_timeval_valid_timeout (tv));
  48. /* Compute second-based deadline. Perform the addition in
  49. uintmax_t, which is unsigned, to simply overflow detection. */
  50. uintmax_t sec = current.current.tv_sec;
  51. sec += tv.tv_sec;
  52. if (sec < (uintmax_t) tv.tv_sec)
  53. return infinite_deadline ();
  54. /* Compute nanosecond deadline. */
  55. int nsec = current.current.tv_nsec + tv.tv_usec * 1000;
  56. if (nsec >= 1000 * 1000 * 1000)
  57. {
  58. /* Carry nanosecond overflow to seconds. */
  59. nsec -= 1000 * 1000 * 1000;
  60. if (sec + 1 < sec)
  61. return infinite_deadline ();
  62. ++sec;
  63. }
  64. /* This uses a GCC extension, otherwise these casts for detecting
  65. overflow would not be defined. */
  66. if ((time_t) sec < 0 || sec != (uintmax_t) (time_t) sec)
  67. return infinite_deadline ();
  68. return (struct deadline) { { sec, nsec } };
  69. }
  70. int
  71. __deadline_to_ms (struct deadline_current_time current,
  72. struct deadline deadline)
  73. {
  74. if (__deadline_is_infinite (deadline))
  75. return INT_MAX;
  76. if (current.current.tv_sec > deadline.absolute.tv_sec
  77. || (current.current.tv_sec == deadline.absolute.tv_sec
  78. && current.current.tv_nsec >= deadline.absolute.tv_nsec))
  79. return 0;
  80. time_t sec = deadline.absolute.tv_sec - current.current.tv_sec;
  81. if (sec >= INT_MAX)
  82. /* This value will overflow below. */
  83. return INT_MAX;
  84. int nsec = deadline.absolute.tv_nsec - current.current.tv_nsec;
  85. if (nsec < 0)
  86. {
  87. /* Borrow from the seconds field. */
  88. assert (sec > 0);
  89. --sec;
  90. nsec += 1000 * 1000 * 1000;
  91. }
  92. /* Prepare for rounding up to milliseconds. */
  93. nsec += 999999;
  94. if (nsec > 1000 * 1000 * 1000)
  95. {
  96. assert (sec < INT_MAX);
  97. ++sec;
  98. nsec -= 1000 * 1000 * 1000;
  99. }
  100. unsigned int msec = nsec / (1000 * 1000);
  101. if (sec > INT_MAX / 1000)
  102. return INT_MAX;
  103. msec += sec * 1000;
  104. if (msec > INT_MAX)
  105. return INT_MAX;
  106. return msec;
  107. }