diff --git a/include/haproxy/clock.h b/include/haproxy/clock.h index 9d5cdca74..fa392adca 100644 --- a/include/haproxy/clock.h +++ b/include/haproxy/clock.h @@ -36,6 +36,7 @@ uint64_t now_cpu_time_thread(int thr); uint64_t now_mono_time(void); uint64_t now_mono_time_fast(void); uint64_t now_cpu_time(void); +uint64_t now_cpu_time_fast(void); void clock_set_local_source(void); void clock_update_local_date(int max_wait, int interrupted); void clock_update_global_date(); diff --git a/src/clock.c b/src/clock.c index d4ed2d54a..f250feab6 100644 --- a/src/clock.c +++ b/src/clock.c @@ -93,6 +93,32 @@ uint64_t now_cpu_time(void) return ret; } +/* Returns the current thread's cumulated CPU time in nanoseconds. + * + * thread_local timer is cached so that call is less precise but also less + * expensive if heavily used. + * We use the mono time as a cache expiration hint since now_cpu_time() is + * known to be much more expensive than now_mono_time_fast() on systems + * supporting the COARSE clock source. + * + * Returns 0 if either now_mono_time_fast() or now_cpu_time() are not + * supported. + */ +uint64_t now_cpu_time_fast(void) +{ + static THREAD_LOCAL uint64_t mono_cache = 0; + static THREAD_LOCAL uint64_t cpu_cache = 0; + uint64_t mono_cur; + + mono_cur = now_mono_time_fast(); + if (unlikely(mono_cur != mono_cache)) { + /* global mono clock was updated: local cache is outdated */ + cpu_cache = now_cpu_time(); + mono_cache = mono_cur; + } + return cpu_cache; +} + /* returns another thread's cumulated CPU time in nanoseconds if supported, otherwise zero */ uint64_t now_cpu_time_thread(int thr) {