From e2e8c6779e54ab86edd80697fe1e5c80633eaca6 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 8 Nov 2019 14:40:18 +0100 Subject: [PATCH] MINOR: freq_ctr: Make the sliding window sums thread-safe 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 | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/include/proto/freq_ctr.h b/include/proto/freq_ctr.h index da4f82fed9..184cdc6338 100644 --- a/include/proto/freq_ctr.h +++ b/include/proto/freq_ctr.h @@ -248,11 +248,18 @@ unsigned int freq_ctr_remain_period(struct freq_ctr_period *ctr, unsigned int pe */ /* Adds sample value to sliding window sum configured for samples. - * The sample is returned. Better if is a power of two. + * The sample is returned. Better if 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 spanning samples to sliding window 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 over a sliding window of