]> git.ozlabs.org Git - ccan/blob - ccan/timer/timer.c
timer: remove unnecessary dependency on likely
[ccan] / ccan / timer / timer.c
1 /* LGPL (v2.1 or any later version) - see LICENSE file for details */
2 #include <ccan/timer/timer.h>
3 #include <ccan/array_size/array_size.h>
4 #include <ccan/ilog/ilog.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7
8 #define PER_LEVEL (1ULL << TIMER_LEVEL_BITS)
9
10 struct timer_level {
11         struct list_head list[PER_LEVEL];
12 };
13
14 static uint64_t time_to_grains(struct timemono t)
15 {
16         return t.ts.tv_sec * ((uint64_t)1000000000 / TIMER_GRANULARITY)
17                 + (t.ts.tv_nsec / TIMER_GRANULARITY);
18 }
19
20 static struct timemono grains_to_time(uint64_t grains)
21 {
22         struct timemono t;
23
24         t.ts.tv_sec = grains / (1000000000 / TIMER_GRANULARITY);
25         t.ts.tv_nsec = (grains % (1000000000 / TIMER_GRANULARITY))
26                 * TIMER_GRANULARITY;
27         return t;
28 }
29
30 void timers_init(struct timers *timers, struct timemono start)
31 {
32         unsigned int i;
33
34         list_head_init(&timers->far);
35         timers->base = time_to_grains(start);
36         timers->first = -1ULL;
37         memset(timers->firsts, 0xFF, sizeof(timers->firsts));
38         for (i = 0; i < ARRAY_SIZE(timers->level); i++)
39                 timers->level[i] = NULL;
40 }
41
42 static unsigned int level_of(const struct timers *timers, uint64_t time)
43 {
44         uint64_t diff;
45
46         /* Level depends how far away it is. */
47         diff = time - timers->base;
48         return ilog64(diff / 2) / TIMER_LEVEL_BITS;
49 }
50
51 static void timer_add_raw(struct timers *timers, struct timer *t)
52 {
53         struct list_head *l;
54         unsigned int level = level_of(timers, t->time);
55         uint64_t *first;
56
57         if (!timers->level[level]) {
58                 l = &timers->far;
59                 first = &timers->firsts[ARRAY_SIZE(timers->level)];
60         } else {
61                 int off = (t->time >> (level*TIMER_LEVEL_BITS)) & (PER_LEVEL-1);
62                 l = &timers->level[level]->list[off];
63                 first = &timers->firsts[level];
64         }
65
66         list_add_tail(l, &t->list);
67         if (t->time < *first)
68                 *first = t->time;
69 }
70
71 void timer_init(struct timer *t)
72 {
73         list_node_init(&t->list);
74 }
75
76 static bool list_node_initted(const struct list_node *n)
77 {
78         return n->prev == n;
79 }
80
81 void timer_addrel(struct timers *timers, struct timer *t, struct timerel rel)
82 {
83         assert(list_node_initted(&t->list));
84
85         t->time = time_to_grains(timemono_add(time_mono(), rel));
86
87 #if TIME_HAVE_MONOTONIC
88         assert(t->time >= timers->base);
89 #else
90         /* Added in the past?  Treat it as imminent. */
91         if (t->time < timers->base)
92                 t->time = timers->base;
93 #endif
94         if (t->time < timers->first)
95                 timers->first = t->time;
96
97         timer_add_raw(timers, t);
98 }
99
100 void timer_addmono(struct timers *timers, struct timer *t, struct timemono when)
101 {
102         assert(list_node_initted(&t->list));
103
104         t->time = time_to_grains(when);
105
106         /* Added in the past?  Treat it as imminent. */
107         if (t->time < timers->base)
108                 t->time = timers->base;
109         if (t->time < timers->first)
110                 timers->first = t->time;
111
112         timer_add_raw(timers, t);
113 }
114
115 /* FIXME: inline */
116 void timer_del(struct timers *timers UNNEEDED, struct timer *t)
117 {
118         list_del_init(&t->list);
119 }
120
121 static void timers_far_get(struct timers *timers,
122                            struct list_head *list,
123                            uint64_t when)
124 {
125         struct timer *i, *next;
126
127         list_for_each_safe(&timers->far, i, next, list) {
128                 if (i->time <= when) {
129                         list_del_from(&timers->far, &i->list);
130                         list_add_tail(list, &i->list);
131                 }
132         }
133 }
134
135 static void add_level(struct timers *timers, unsigned int level)
136 {
137         struct timer_level *l;
138         struct timer *t;
139         unsigned int i;
140         struct list_head from_far;
141
142         l = malloc(sizeof(*l));
143         if (!l)
144                 return;
145
146         for (i = 0; i < ARRAY_SIZE(l->list); i++)
147                 list_head_init(&l->list[i]);
148         timers->level[level] = l;
149
150         list_head_init(&from_far);
151         timers_far_get(timers, &from_far,
152                        timers->base + (1ULL << ((level+1)*TIMER_LEVEL_BITS)) - 1);
153
154         while ((t = list_pop(&from_far, struct timer, list)) != NULL)
155                 timer_add_raw(timers, t);
156 }
157
158 /* We don't need to search past the first at level 0, since the
159  * bucket range is 1; they're all the same. */
160 static const struct timer *find_first(const struct list_head *list,
161                                       unsigned int level,
162                                       const struct timer *prev)
163 {
164         struct timer *t;
165
166         list_for_each(list, t, list) {
167                 if (!prev || t->time < prev->time)
168                         prev = t;
169                 if (level == 0)
170                         break;
171         }
172         return prev;
173 }
174
175 /* Update level's first watermark, and return overall first. */
176 static const struct timer *first_for_level(struct timers *timers,
177                                            size_t level,
178                                            const struct timer *level_first,
179                                            const struct timer *first)
180 {
181         if (level_first) {
182                 timers->firsts[level] = level_first->time;
183                 if (!first || level_first->time < first->time)
184                         first = level_first;
185         } else {
186                 timers->firsts[level] = -1ULL;
187         }
188         return first;
189 }
190
191 static bool level_may_beat(const struct timers *timers, size_t level,
192                            const struct timer *first)
193 {
194         return !first || timers->firsts[level] < first->time;
195 }
196
197 /* FIXME: Suboptimal */
198 static const struct timer *brute_force_first(struct timers *timers)
199 {
200         unsigned int l, i;
201         const struct timer *found = NULL;
202
203         for (l = 0; l < ARRAY_SIZE(timers->level) && timers->level[l]; l++) {
204                 const struct timer *t = NULL;
205
206                 /* Do we know they don't have a better one? */
207                 if (!level_may_beat(timers, l, found))
208                         continue;
209
210                 /* Find first timer on this level. */
211                 for (i = 0; i < PER_LEVEL; i++)
212                         t = find_first(&timers->level[l]->list[i], l, t);
213
214                 found = first_for_level(timers, l, t, found);
215         }
216
217         /* Check (and update) far list if there's a chance. */
218         l = ARRAY_SIZE(timers->level);
219         if (level_may_beat(timers, l, found)) {
220                 const struct timer *t = find_first(&timers->far, l, NULL);
221                 found = first_for_level(timers, l, t, found);
222         }
223
224         return found;
225 }
226
227 static const struct timer *get_first(struct timers *timers)
228 {
229         /* We can have just far timers, for example. */
230         if (timers->level[0]) {
231                 /* First search rest of lower buckets; we've already spilled
232                  * so if we find one there we don't need to search further. */
233                 unsigned int i, off = timers->base % PER_LEVEL;
234
235                 for (i = off; i < PER_LEVEL; i++) {
236                         struct list_head *h = &timers->level[0]->list[i];
237                         if (!list_empty(h))
238                                 return find_first(h, 0, NULL);
239                 }
240         }
241
242         /* From here on, we're searching non-normalized parts of the
243          * data structure, which is much subtler.
244          *
245          * So we brute force. */
246         return brute_force_first(timers);
247 }
248
249 static bool update_first(struct timers *timers)
250 {
251         const struct timer *found = get_first(timers);
252
253         if (!found) {
254                 timers->first = -1ULL;
255                 return false;
256         }
257
258         timers->first = found->time;
259         return true;
260 }
261
262 bool timer_earliest(struct timers *timers, struct timemono *first)
263 {
264         if (!update_first(timers))
265                 return false;
266
267         *first = grains_to_time(timers->first);
268         return true;
269 }
270
271 /* Assume no timers before 'time', cascade down and update base time. */
272 static void timer_fast_forward(struct timers *timers, uint64_t time)
273 {
274         unsigned int level, changed;
275         int need_level = -1;
276         struct list_head list;
277         struct timer *i;
278
279         /* How many bits changed between base and time?
280          * Each time we wrap, we need to empty buckets from above. */
281         if (time == timers->base)
282                 return;
283
284         changed = ilog64_nz(time ^ timers->base);
285         level = (changed - 1) / TIMER_LEVEL_BITS;
286
287         /* Buckets always empty downwards, so we could cascade manually,
288          * but it's rarely very many so we just remove and re-add */
289         list_head_init(&list);
290
291         do {
292                 if (!timers->level[level]) {
293                         /* We need any which belong on this level. */
294                         timers_far_get(timers, &list,
295                                        timers->base
296                                        + (1ULL << ((level+1)*TIMER_LEVEL_BITS))-1);
297                         need_level = level;
298                 } else {
299                         unsigned src;
300
301                         /* Get all timers from this bucket. */
302                         src = (time >> (level * TIMER_LEVEL_BITS)) % PER_LEVEL;
303                         list_append_list(&list,
304                                          &timers->level[level]->list[src]);
305                 }
306         } while (level--);
307
308         /* Did we hit the last level?  If so, add. */
309         if (need_level != -1)
310                 add_level(timers, need_level);
311
312         /* Fast-forward the time, and re-add everyone. */
313         timers->base = time;
314         while ((i = list_pop(&list, struct timer, list)) != NULL)
315                 timer_add_raw(timers, i);
316 }
317
318 /* Returns an expired timer. */
319 struct timer *timers_expire(struct timers *timers, struct timemono expire)
320 {
321         uint64_t now = time_to_grains(expire);
322         unsigned int off;
323         struct timer *t;
324
325         assert(now >= timers->base);
326
327         if (!timers->level[0]) {
328                 if (list_empty(&timers->far))
329                         return NULL;
330                 add_level(timers, 0);
331         }
332
333         do {
334                 if (timers->first > now) {
335                         timer_fast_forward(timers, now);
336                         return NULL;
337                 }
338
339                 timer_fast_forward(timers, timers->first);
340                 off = timers->base % PER_LEVEL;
341
342                 /* This *may* be NULL, if we deleted the first timer */
343                 t = list_pop(&timers->level[0]->list[off], struct timer, list);
344                 if (t)
345                         list_node_init(&t->list);
346         } while (!t && update_first(timers));
347
348         return t;
349 }
350
351 static bool timer_list_check(const struct list_head *l,
352                              uint64_t min, uint64_t max, uint64_t first,
353                              const char *abortstr)
354 {
355         const struct timer *t;
356
357         if (!list_check(l, abortstr))
358                 return false;
359
360         list_for_each(l, t, list) {
361                 if (t->time < min || t->time > max) {
362                         if (abortstr) {
363                                 fprintf(stderr,
364                                         "%s: timer %p %llu not %llu-%llu\n",
365                                         abortstr, t, (long long)t->time,
366                                         (long long)min, (long long)max);
367                                 abort();
368                         }
369                         return false;
370                 }
371                 if (t->time < first) {
372                         if (abortstr) {
373                                 fprintf(stderr,
374                                         "%s: timer %p %llu < minimum %llu\n",
375                                         abortstr, t, (long long)t->time,
376                                         (long long)first);
377                                 abort();
378                         }
379                         return false;
380                 }
381         }
382         return true;
383 }
384
385 struct timers *timers_check(const struct timers *timers, const char *abortstr)
386 {
387         unsigned int l, i, off;
388         uint64_t base;
389
390         l = 0;
391         if (!timers->level[0])
392                 goto past_levels;
393
394         /* First level is simple. */
395         off = timers->base % PER_LEVEL;
396         for (i = 0; i < PER_LEVEL; i++) {
397                 struct list_head *h;
398
399                 h = &timers->level[l]->list[(i+off) % PER_LEVEL];
400                 if (!timer_list_check(h, timers->base + i, timers->base + i,
401                                       timers->firsts[l], abortstr))
402                         return NULL;
403         }
404
405         /* For other levels, "current" bucket has been emptied, and may contain
406          * entries for the current + level_size bucket. */
407         for (l = 1; l < ARRAY_SIZE(timers->level) && timers->level[l]; l++) {
408                 uint64_t per_bucket = 1ULL << (TIMER_LEVEL_BITS * l);
409
410                 off = ((timers->base >> (l*TIMER_LEVEL_BITS)) % PER_LEVEL);
411                 /* We start at *next* bucket. */
412                 base = (timers->base & ~(per_bucket - 1)) + per_bucket;
413
414                 for (i = 1; i <= PER_LEVEL; i++) {
415                         struct list_head *h;
416
417                         h = &timers->level[l]->list[(i+off) % PER_LEVEL];
418                         if (!timer_list_check(h, base, base + per_bucket - 1,
419                                               timers->firsts[l], abortstr))
420                                 return NULL;
421                         base += per_bucket;
422                 }
423         }
424
425 past_levels:
426         base = (timers->base & ~((1ULL << (TIMER_LEVEL_BITS * l)) - 1))
427                 + (1ULL << (TIMER_LEVEL_BITS * l)) - 1;
428         if (!timer_list_check(&timers->far, base, -1ULL,
429                               timers->firsts[ARRAY_SIZE(timers->level)],
430                               abortstr))
431                 return NULL;
432
433         return (struct timers *)timers;
434 }
435
436 #ifdef CCAN_TIMER_DEBUG
437 static void dump_bucket_stats(FILE *fp, const struct list_head *h)
438 {
439         unsigned long long min, max, num;
440         struct timer *t;
441
442         if (list_empty(h)) {
443                 printf("\n");
444                 return;
445         }
446
447         min = -1ULL;
448         max = 0;
449         num = 0;
450         list_for_each(h, t, list) {
451                 if (t->time < min)
452                         min = t->time;
453                 if (t->time > max)
454                         max = t->time;
455                 num++;
456         }
457         fprintf(fp, " %llu (%llu-%llu)\n",
458                 num, min, max);
459 }
460
461 void timers_dump(const struct timers *timers, FILE *fp)
462 {
463         unsigned int l, i, off;
464         unsigned long long base;
465
466         if (!fp)
467                 fp = stderr;
468
469         fprintf(fp, "Base: %llu\n", (unsigned long long)timers->base);
470
471         if (!timers->level[0])
472                 goto past_levels;
473
474         fprintf(fp, "Level 0:\n");
475
476         /* First level is simple. */
477         off = timers->base % PER_LEVEL;
478         for (i = 0; i < PER_LEVEL; i++) {
479                 const struct list_head *h;
480
481                 fprintf(fp, "  Bucket %llu (%lu):",
482                         (i+off) % PER_LEVEL, timers->base + i);
483                 h = &timers->level[0]->list[(i+off) % PER_LEVEL];
484                 dump_bucket_stats(fp, h);
485         }
486
487         /* For other levels, "current" bucket has been emptied, and may contain
488          * entries for the current + level_size bucket. */
489         for (l = 1; l < ARRAY_SIZE(timers->level) && timers->level[l]; l++) {
490                 uint64_t per_bucket = 1ULL << (TIMER_LEVEL_BITS * l);
491
492                 off = ((timers->base >> (l*TIMER_LEVEL_BITS)) % PER_LEVEL);
493                 /* We start at *next* bucket. */
494                 base = (timers->base & ~(per_bucket - 1)) + per_bucket;
495
496                 fprintf(fp, "Level %u:\n", l);
497                 for (i = 1; i <= PER_LEVEL; i++) {
498                         const struct list_head *h;
499
500                         fprintf(fp, "  Bucket %llu (%llu - %llu):",
501                                 (i+off) % PER_LEVEL,
502                                 base, base + per_bucket - 1);
503
504                         h = &timers->level[l]->list[(i+off) % PER_LEVEL];
505                         dump_bucket_stats(fp, h);
506                         base += per_bucket;
507                 }
508         }
509
510 past_levels:
511         if (!list_empty(&timers->far)) {
512                 fprintf(fp, "Far timers:");
513                 dump_bucket_stats(fp, &timers->far);
514         }
515 }
516 #endif
517
518 void timers_cleanup(struct timers *timers)
519 {
520         unsigned int l;
521
522         for (l = 0; l < ARRAY_SIZE(timers->level); l++)
523                 free(timers->level[l]);
524 }