]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: time: change the global timeval and the the global tick at once
authorWilly Tarreau <w@1wt.eu>
Sun, 11 Apr 2021 13:34:25 +0000 (15:34 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 11 Apr 2021 21:47:54 +0000 (23:47 +0200)
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.

src/time.c

index c550b570686cbb288e8101087d29a4c1bcbb0d16..5054982dbc85053f771e6e046f8d238d672f94bd 100644 (file)
@@ -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 <global_now> 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 <now> or loop again */
-       } while (!_HA_ATOMIC_CAS(&global_now, &old_now, new_now));
+               /* let's try to update the global <now> (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;
 }