From: Willy Tarreau Date: Sun, 11 Apr 2021 13:34:25 +0000 (+0200) Subject: MINOR: time: change the global timeval and the the global tick at once X-Git-Tag: v2.4-dev17~138 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e4a557f6;p=thirdparty%2Fhaproxy.git MINOR: time: change the global timeval and the the global tick at once Instead of using two CAS loops, better compute the two units simultaneously and update them at once. There is no guarantee that the update will be synchronous, but we don't care, what matters is that both are monotonically updated and that global_now_ms always follows the last known value of global_now. --- diff --git a/src/time.c b/src/time.c index c550b57068..5054982dbc 100644 --- a/src/time.c +++ b/src/time.c @@ -178,7 +178,7 @@ int _tv_isgt(const struct timeval *tv1, const struct timeval *tv2) void tv_update_date(int max_wait, int interrupted) { struct timeval adjusted, deadline, tmp_now; - unsigned int old_now_ms, new_now_ms; + unsigned int old_now_ms; unsigned long long old_now; unsigned long long new_now; @@ -206,10 +206,12 @@ void tv_update_date(int max_wait, int interrupted) * otherwise catch up. */ old_now = global_now; + old_now_ms = global_now_ms; do { tmp_now.tv_sec = (unsigned int)(old_now >> 32); tmp_now.tv_usec = old_now & 0xFFFFFFFFU; + old_now_ms = tmp_now.tv_sec * 1000 + tmp_now.tv_usec / 1000; if (__tv_islt(&now, &tmp_now)) now = tmp_now; @@ -218,9 +220,15 @@ void tv_update_date(int max_wait, int interrupted) * equal to or newer. */ new_now = ((ullong)now.tv_sec << 32) + (uint)now.tv_usec; + now_ms = now.tv_sec * 1000 + now.tv_usec / 1000; + if (tick_is_lt(now_ms, old_now_ms)) + now_ms = old_now_ms; - /* let's try to update the global or loop again */ - } while (!_HA_ATOMIC_CAS(&global_now, &old_now, new_now)); + /* let's try to update the global (both in timeval + * and ms forms) or loop again. + */ + } while (!_HA_ATOMIC_CAS(&global_now, &old_now, new_now) || + !_HA_ATOMIC_CAS(&global_now_ms, &old_now_ms, now_ms)); /* the new global date when we looked was old_now, and the new one is * new_now == now. We can recompute our local offset. @@ -232,16 +240,6 @@ void tv_update_date(int max_wait, int interrupted) tv_offset.tv_sec--; } - now_ms = now.tv_sec * 1000 + now.tv_usec / 1000; - - /* update the global current millisecond */ - old_now_ms = global_now_ms; - do { - new_now_ms = old_now_ms; - if (tick_is_lt(new_now_ms, now_ms)) - new_now_ms = now_ms; - } while (!_HA_ATOMIC_CAS(&global_now_ms, &old_now_ms, new_now_ms)); - return; }