Assume no timers before 'time', cascade down and update base time. */
| 291 | |
| 292 | /* Assume no timers before 'time', cascade down and update base time. */ |
| 293 | static void timer_fast_forward(struct timers *timers, uint64_t time) |
| 294 | { |
| 295 | unsigned int level, changed; |
| 296 | int need_level = -1; |
| 297 | struct list_head list; |
| 298 | struct timer *i; |
| 299 | |
| 300 | /* How many bits changed between base and time? |
| 301 | * Each time we wrap, we need to empty buckets from above. */ |
| 302 | if (time == timers->base) |
| 303 | return; |
| 304 | |
| 305 | changed = ilog64_nz(time ^ timers->base); |
| 306 | level = (changed - 1) / TIMER_LEVEL_BITS; |
| 307 | |
| 308 | /* Buckets always empty downwards, so we could cascade manually, |
| 309 | * but it's rarely very many so we just remove and re-add */ |
| 310 | list_head_init(&list); |
| 311 | |
| 312 | do { |
| 313 | if (!timers->level[level]) { |
| 314 | /* We need any which belong on this level. */ |
| 315 | timers_far_get(timers, &list, |
| 316 | timers->base |
| 317 | + (1ULL << ((level+1)*TIMER_LEVEL_BITS))-1); |
| 318 | need_level = level; |
| 319 | } else { |
| 320 | unsigned src; |
| 321 | |
| 322 | /* Get all timers from this bucket. */ |
| 323 | src = (time >> (level * TIMER_LEVEL_BITS)) % PER_LEVEL; |
| 324 | list_append_list(&list, |
| 325 | &timers->level[level]->list[src]); |
| 326 | } |
| 327 | } while (level--); |
| 328 | |
| 329 | /* Did we hit the last level? If so, add. */ |
| 330 | if (need_level != -1) |
| 331 | add_level(timers, need_level); |
| 332 | |
| 333 | /* Fast-forward the time, and re-add everyone. */ |
| 334 | timers->base = time; |
| 335 | while ((i = list_pop(&list, struct timer, list)) != NULL) |
| 336 | timer_add_raw(timers, i); |
| 337 | } |
| 338 | |
| 339 | /* Returns an expired timer. */ |
| 340 | struct timer *timers_expire(struct timers *timers, struct timemono expire) |
no test coverage detected