]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: freq_ctr: Make the sliding window sums thread-safe
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 8 Nov 2019 13:40:18 +0000 (14:40 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 15 Nov 2019 12:43:08 +0000 (13:43 +0100)
swrate_add() and swrate_add_scaled() now rely on the CAS atomic operation. So
the sliding window sums are atomically updated.

include/proto/freq_ctr.h

index da4f82fed9fb5278363b0b67390ff9b3f7fff362..184cdc63385e0edaeae45425a6424a75e94dd052 100644 (file)
@@ -248,11 +248,18 @@ unsigned int freq_ctr_remain_period(struct freq_ctr_period *ctr, unsigned int pe
  */
 
 /* Adds sample value <v> to sliding window sum <sum> configured for <n> samples.
- * The sample is returned. Better if <n> is a power of two.
+ * The sample is returned. Better if <n> is a power of two. This function is
+ * thread-safe.
  */
 static inline unsigned int swrate_add(unsigned int *sum, unsigned int n, unsigned int v)
 {
-       return *sum = *sum - (*sum + n - 1) / n + v;
+       unsigned int new_sum, old_sum;
+
+       old_sum = *sum;
+       do {
+               new_sum = old_sum - (old_sum + n - 1) / n + v;
+       } while (!_HA_ATOMIC_CAS(sum, &old_sum, new_sum));
+       return new_sum;
 }
 
 /* Adds sample value <v> spanning <s> samples to sliding window sum <sum>
@@ -275,11 +282,18 @@ static inline unsigned int swrate_add(unsigned int *sum, unsigned int n, unsigne
  * Thus the simplified function effectively replaces a part of the history with
  * a linear sum instead of applying the exponential one. But as long as s/n is
  * "small enough", the error fades away and remains small for both small and
- * large values of n and s (typically < 0.2% measured).
+ * large values of n and s (typically < 0.2% measured).  This function is
+ * thread-safe.
  */
 static inline unsigned int swrate_add_scaled(unsigned int *sum, unsigned int n, unsigned int v, unsigned int s)
 {
-       return *sum = *sum + v * s - div64_32((unsigned long long)(*sum + n) * s, n);
+       unsigned int new_sum, old_sum;
+
+       old_sum = *sum;
+       do {
+               new_sum = old_sum + v * s - div64_32((unsigned long long)(old_sum + n) * s, n);
+       } while (!_HA_ATOMIC_CAS(sum, &old_sum, new_sum));
+       return new_sum;
 }
 
 /* Returns the average sample value for the sum <sum> over a sliding window of