kern_timeout.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /* $OpenBSD: kern_timeout.c,v 1.43 2015/07/20 23:47:20 uebayasi Exp $ */
  2. /*
  3. * Copyright (c) 2001 Thomas Nordin <nordin@openbsd.org>
  4. * Copyright (c) 2000-2001 Artur Grabowski <art@openbsd.org>
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  17. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  18. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  19. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  21. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  22. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  23. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  24. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  25. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <sys/param.h>
  28. #include <sys/systm.h>
  29. #include <sys/lock.h>
  30. #include <sys/timeout.h>
  31. #include <sys/mutex.h>
  32. #include <sys/kernel.h>
  33. #include <sys/queue.h> /* _Q_INVALIDATE */
  34. #ifdef DDB
  35. #include <machine/db_machdep.h>
  36. #include <ddb/db_interface.h>
  37. #include <ddb/db_sym.h>
  38. #include <ddb/db_output.h>
  39. #endif
  40. /*
  41. * Timeouts are kept in a hierarchical timing wheel. The to_time is the value
  42. * of the global variable "ticks" when the timeout should be called. There are
  43. * four levels with 256 buckets each. See 'Scheme 7' in
  44. * "Hashed and Hierarchical Timing Wheels: Efficient Data Structures for
  45. * Implementing a Timer Facility" by George Varghese and Tony Lauck.
  46. */
  47. #define BUCKETS 1024
  48. #define WHEELSIZE 256
  49. #define WHEELMASK 255
  50. #define WHEELBITS 8
  51. struct circq timeout_wheel[BUCKETS]; /* Queues of timeouts */
  52. struct circq timeout_todo; /* Worklist */
  53. #define MASKWHEEL(wheel, time) (((time) >> ((wheel)*WHEELBITS)) & WHEELMASK)
  54. #define BUCKET(rel, abs) \
  55. (timeout_wheel[ \
  56. ((rel) <= (1 << (2*WHEELBITS))) \
  57. ? ((rel) <= (1 << WHEELBITS)) \
  58. ? MASKWHEEL(0, (abs)) \
  59. : MASKWHEEL(1, (abs)) + WHEELSIZE \
  60. : ((rel) <= (1 << (3*WHEELBITS))) \
  61. ? MASKWHEEL(2, (abs)) + 2*WHEELSIZE \
  62. : MASKWHEEL(3, (abs)) + 3*WHEELSIZE])
  63. #define MOVEBUCKET(wheel, time) \
  64. CIRCQ_APPEND(&timeout_todo, \
  65. &timeout_wheel[MASKWHEEL((wheel), (time)) + (wheel)*WHEELSIZE])
  66. /*
  67. * The first thing in a struct timeout is its struct circq, so we
  68. * can get back from a pointer to the latter to a pointer to the
  69. * whole timeout with just a cast.
  70. */
  71. static __inline struct timeout *
  72. timeout_from_circq(struct circq *p)
  73. {
  74. return ((struct timeout *)(p));
  75. }
  76. /*
  77. * All wheels are locked with the same mutex.
  78. *
  79. * We need locking since the timeouts are manipulated from hardclock that's
  80. * not behind the big lock.
  81. */
  82. struct mutex timeout_mutex = MUTEX_INITIALIZER(IPL_HIGH);
  83. /*
  84. * Circular queue definitions.
  85. */
  86. #define CIRCQ_INIT(elem) do { \
  87. (elem)->next = (elem); \
  88. (elem)->prev = (elem); \
  89. } while (0)
  90. #define CIRCQ_INSERT(elem, list) do { \
  91. (elem)->prev = (list)->prev; \
  92. (elem)->next = (list); \
  93. (list)->prev->next = (elem); \
  94. (list)->prev = (elem); \
  95. } while (0)
  96. #define CIRCQ_APPEND(fst, snd) do { \
  97. if (!CIRCQ_EMPTY(snd)) { \
  98. (fst)->prev->next = (snd)->next;\
  99. (snd)->next->prev = (fst)->prev;\
  100. (snd)->prev->next = (fst); \
  101. (fst)->prev = (snd)->prev; \
  102. CIRCQ_INIT(snd); \
  103. } \
  104. } while (0)
  105. #define CIRCQ_REMOVE(elem) do { \
  106. (elem)->next->prev = (elem)->prev; \
  107. (elem)->prev->next = (elem)->next; \
  108. _Q_INVALIDATE((elem)->prev); \
  109. _Q_INVALIDATE((elem)->next); \
  110. } while (0)
  111. #define CIRCQ_FIRST(elem) ((elem)->next)
  112. #define CIRCQ_EMPTY(elem) (CIRCQ_FIRST(elem) == (elem))
  113. /*
  114. * Some of the "math" in here is a bit tricky.
  115. *
  116. * We have to beware of wrapping ints.
  117. * We use the fact that any element added to the queue must be added with a
  118. * positive time. That means that any element `to' on the queue cannot be
  119. * scheduled to timeout further in time than INT_MAX, but to->to_time can
  120. * be positive or negative so comparing it with anything is dangerous.
  121. * The only way we can use the to->to_time value in any predictable way
  122. * is when we calculate how far in the future `to' will timeout -
  123. * "to->to_time - ticks". The result will always be positive for future
  124. * timeouts and 0 or negative for due timeouts.
  125. */
  126. void
  127. timeout_startup(void)
  128. {
  129. int b;
  130. CIRCQ_INIT(&timeout_todo);
  131. for (b = 0; b < nitems(timeout_wheel); b++)
  132. CIRCQ_INIT(&timeout_wheel[b]);
  133. }
  134. void
  135. timeout_set(struct timeout *new, void (*fn)(void *), void *arg)
  136. {
  137. new->to_func = fn;
  138. new->to_arg = arg;
  139. new->to_flags = TIMEOUT_INITIALIZED;
  140. }
  141. int
  142. timeout_add(struct timeout *new, int to_ticks)
  143. {
  144. int old_time;
  145. int ret = 1;
  146. #ifdef DIAGNOSTIC
  147. if (!(new->to_flags & TIMEOUT_INITIALIZED))
  148. panic("timeout_add: not initialized");
  149. if (to_ticks < 0)
  150. panic("timeout_add: to_ticks (%d) < 0", to_ticks);
  151. #endif
  152. mtx_enter(&timeout_mutex);
  153. /* Initialize the time here, it won't change. */
  154. old_time = new->to_time;
  155. new->to_time = to_ticks + ticks;
  156. new->to_flags &= ~TIMEOUT_TRIGGERED;
  157. /*
  158. * If this timeout already is scheduled and now is moved
  159. * earlier, reschedule it now. Otherwise leave it in place
  160. * and let it be rescheduled later.
  161. */
  162. if (new->to_flags & TIMEOUT_ONQUEUE) {
  163. if (new->to_time - ticks < old_time - ticks) {
  164. CIRCQ_REMOVE(&new->to_list);
  165. CIRCQ_INSERT(&new->to_list, &timeout_todo);
  166. }
  167. ret = 0;
  168. } else {
  169. new->to_flags |= TIMEOUT_ONQUEUE;
  170. CIRCQ_INSERT(&new->to_list, &timeout_todo);
  171. }
  172. mtx_leave(&timeout_mutex);
  173. return (ret);
  174. }
  175. int
  176. timeout_add_tv(struct timeout *to, const struct timeval *tv)
  177. {
  178. long long to_ticks;
  179. to_ticks = (long long)hz * tv->tv_sec + tv->tv_usec / tick;
  180. if (to_ticks > INT_MAX)
  181. to_ticks = INT_MAX;
  182. return (timeout_add(to, (int)to_ticks));
  183. }
  184. int
  185. timeout_add_ts(struct timeout *to, const struct timespec *ts)
  186. {
  187. long long to_ticks;
  188. to_ticks = (long long)hz * ts->tv_sec + ts->tv_nsec / (tick * 1000);
  189. if (to_ticks > INT_MAX)
  190. to_ticks = INT_MAX;
  191. return (timeout_add(to, (int)to_ticks));
  192. }
  193. int
  194. timeout_add_bt(struct timeout *to, const struct bintime *bt)
  195. {
  196. long long to_ticks;
  197. to_ticks = (long long)hz * bt->sec + (long)(((uint64_t)1000000 *
  198. (uint32_t)(bt->frac >> 32)) >> 32) / tick;
  199. if (to_ticks > INT_MAX)
  200. to_ticks = INT_MAX;
  201. return (timeout_add(to, (int)to_ticks));
  202. }
  203. int
  204. timeout_add_sec(struct timeout *to, int secs)
  205. {
  206. long long to_ticks;
  207. to_ticks = (long long)hz * secs;
  208. if (to_ticks > INT_MAX)
  209. to_ticks = INT_MAX;
  210. return (timeout_add(to, (int)to_ticks));
  211. }
  212. int
  213. timeout_add_msec(struct timeout *to, int msecs)
  214. {
  215. long long to_ticks;
  216. to_ticks = (long long)msecs * 1000 / tick;
  217. if (to_ticks > INT_MAX)
  218. to_ticks = INT_MAX;
  219. return (timeout_add(to, (int)to_ticks));
  220. }
  221. int
  222. timeout_add_usec(struct timeout *to, int usecs)
  223. {
  224. int to_ticks = usecs / tick;
  225. return (timeout_add(to, to_ticks));
  226. }
  227. int
  228. timeout_add_nsec(struct timeout *to, int nsecs)
  229. {
  230. int to_ticks = nsecs / (tick * 1000);
  231. return (timeout_add(to, to_ticks));
  232. }
  233. int
  234. timeout_del(struct timeout *to)
  235. {
  236. int ret = 0;
  237. mtx_enter(&timeout_mutex);
  238. if (to->to_flags & TIMEOUT_ONQUEUE) {
  239. CIRCQ_REMOVE(&to->to_list);
  240. to->to_flags &= ~TIMEOUT_ONQUEUE;
  241. ret = 1;
  242. }
  243. to->to_flags &= ~TIMEOUT_TRIGGERED;
  244. mtx_leave(&timeout_mutex);
  245. return (ret);
  246. }
  247. /*
  248. * This is called from hardclock() once every tick.
  249. * We return !0 if we need to schedule a softclock.
  250. */
  251. int
  252. timeout_hardclock_update(void)
  253. {
  254. int ret;
  255. mtx_enter(&timeout_mutex);
  256. ticks++;
  257. MOVEBUCKET(0, ticks);
  258. if (MASKWHEEL(0, ticks) == 0) {
  259. MOVEBUCKET(1, ticks);
  260. if (MASKWHEEL(1, ticks) == 0) {
  261. MOVEBUCKET(2, ticks);
  262. if (MASKWHEEL(2, ticks) == 0)
  263. MOVEBUCKET(3, ticks);
  264. }
  265. }
  266. ret = !CIRCQ_EMPTY(&timeout_todo);
  267. mtx_leave(&timeout_mutex);
  268. return (ret);
  269. }
  270. void
  271. softclock(void *arg)
  272. {
  273. struct timeout *to;
  274. void (*fn)(void *);
  275. mtx_enter(&timeout_mutex);
  276. while (!CIRCQ_EMPTY(&timeout_todo)) {
  277. to = timeout_from_circq(CIRCQ_FIRST(&timeout_todo));
  278. CIRCQ_REMOVE(&to->to_list);
  279. /* If due run it, otherwise insert it into the right bucket. */
  280. if (to->to_time - ticks > 0) {
  281. CIRCQ_INSERT(&to->to_list,
  282. &BUCKET((to->to_time - ticks), to->to_time));
  283. } else {
  284. #ifdef DEBUG
  285. if (to->to_time - ticks < 0)
  286. printf("timeout delayed %d\n", to->to_time -
  287. ticks);
  288. #endif
  289. to->to_flags &= ~TIMEOUT_ONQUEUE;
  290. to->to_flags |= TIMEOUT_TRIGGERED;
  291. fn = to->to_func;
  292. arg = to->to_arg;
  293. mtx_leave(&timeout_mutex);
  294. fn(arg);
  295. mtx_enter(&timeout_mutex);
  296. }
  297. }
  298. mtx_leave(&timeout_mutex);
  299. }
  300. #ifndef SMALL_KERNEL
  301. void
  302. timeout_adjust_ticks(int adj)
  303. {
  304. struct timeout *to;
  305. struct circq *p;
  306. int new_ticks, b;
  307. /* adjusting the monotonic clock backwards would be a Bad Thing */
  308. if (adj <= 0)
  309. return;
  310. mtx_enter(&timeout_mutex);
  311. new_ticks = ticks + adj;
  312. for (b = 0; b < nitems(timeout_wheel); b++) {
  313. p = CIRCQ_FIRST(&timeout_wheel[b]);
  314. while (p != &timeout_wheel[b]) {
  315. to = timeout_from_circq(p);
  316. p = CIRCQ_FIRST(p);
  317. /* when moving a timeout forward need to reinsert it */
  318. if (to->to_time - ticks < adj)
  319. to->to_time = new_ticks;
  320. CIRCQ_REMOVE(&to->to_list);
  321. CIRCQ_INSERT(&to->to_list, &timeout_todo);
  322. }
  323. }
  324. ticks = new_ticks;
  325. mtx_leave(&timeout_mutex);
  326. }
  327. #endif
  328. #ifdef DDB
  329. void db_show_callout_bucket(struct circq *);
  330. void
  331. db_show_callout_bucket(struct circq *bucket)
  332. {
  333. struct timeout *to;
  334. struct circq *p;
  335. db_expr_t offset;
  336. char *name;
  337. for (p = CIRCQ_FIRST(bucket); p != bucket; p = CIRCQ_FIRST(p)) {
  338. to = timeout_from_circq(p);
  339. db_find_sym_and_offset((db_addr_t)to->to_func, &name, &offset);
  340. name = name ? name : "?";
  341. db_printf("%9d %2td/%-4td %p %s\n", to->to_time - ticks,
  342. (bucket - timeout_wheel) / WHEELSIZE,
  343. bucket - timeout_wheel, to->to_arg, name);
  344. }
  345. }
  346. void
  347. db_show_callout(db_expr_t addr, int haddr, db_expr_t count, char *modif)
  348. {
  349. int b;
  350. db_printf("ticks now: %d\n", ticks);
  351. db_printf(" ticks wheel arg func\n");
  352. db_show_callout_bucket(&timeout_todo);
  353. for (b = 0; b < nitems(timeout_wheel); b++)
  354. db_show_callout_bucket(&timeout_wheel[b]);
  355. }
  356. #endif