diff options
Diffstat (limited to 'contrib/timer-wheel/timer-wheel.c')
| -rw-r--r-- | contrib/timer-wheel/timer-wheel.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/contrib/timer-wheel/timer-wheel.c b/contrib/timer-wheel/timer-wheel.c index 013c0f278a1..58e0607bf0c 100644 --- a/contrib/timer-wheel/timer-wheel.c +++ b/contrib/timer-wheel/timer-wheel.c @@ -1,4 +1,12 @@ /* + * linux/kernel/timer.c + * + * Kernel internal timers + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + */ +/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -57,9 +65,17 @@ __gf_tw_add_timer (struct tvec_base *base, struct gf_tw_timer_list *timer) list_add_tail (&timer->entry, vec); } -/* optimized find_last_bit() */ unsigned long gf_tw_find_last_bit(const unsigned long *, unsigned long); +#if defined(__GNUC__) || defined(__clang__) +static inline unsigned long gf_tw_fls (unsigned long word) +{ + return BITS_PER_LONG - __builtin_clzl(word); +} +#else +extern unsigned long gf_tw_fls (unsigned long); +#endif + static inline unsigned long apply_slack(struct tvec_base *base, struct gf_tw_timer_list *timer) { @@ -77,7 +93,7 @@ apply_slack(struct tvec_base *base, struct gf_tw_timer_list *timer) if (mask == 0) return expires; - int bit = gf_tw_find_last_bit (&mask, BITS_PER_LONG); + int bit = gf_tw_fls (mask); mask = (1UL << bit) - 1; expires_limit = expires_limit & ~(mask); @@ -143,7 +159,14 @@ run_timers (struct tvec_base *base) data = timer->data; __gf_tw_detach_timer (timer); - fn (timer, data, call_time); + pthread_spin_unlock(&base->lock); + { + /* It is required to run the actual function outside + of the locked zone, so we don't bother about + locked operations inside that function */ + fn(timer, data, call_time); + } + pthread_spin_lock(&base->lock); } } pthread_spin_unlock (&base->lock); |
