From: Willy Tarreau Date: Sat, 10 Apr 2021 22:38:06 +0000 (+0200) Subject: MINOR: freq_ctr: add a generic function to report the total value X-Git-Tag: v2.4-dev17~149 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f3a9f8dc5a88837760127947a58365d489a03d54;p=thirdparty%2Fhaproxy.git MINOR: freq_ctr: add a generic function to report the total value Most of the functions designed to read a counter over a period go through the same complex loop and only differ in the way they use the returned values, so it was worth implementing all this into freq_ctr_total() which returns the total number of events over a period so that the caller can finish its operation using a divide or a remaining time calculation. As a special case, read_freq_ctr_period() doesn't take pending events but requires to enable an anti-flapping correction at very low frequencies. Thus the function implements it when pend<0. Thanks to this function it will be possible to reimplement the other ones as inline and merge the per-second ones with the arbitrary period ones without always adding the cost of a 64 bit divide. --- diff --git a/include/haproxy/freq_ctr.h b/include/haproxy/freq_ctr.h index 8792625396..e0ac709921 100644 --- a/include/haproxy/freq_ctr.h +++ b/include/haproxy/freq_ctr.h @@ -27,6 +27,8 @@ #include #include +/* exported functions from freq_ctr.c */ +ullong freq_ctr_total(struct freq_ctr_period *ctr, uint period, int pend); /* Update a frequency counter by incremental units. It is automatically * rotated if the period is over. It is important that it correctly initializes diff --git a/src/freq_ctr.c b/src/freq_ctr.c index 42fbc1cea6..76a8ec1ced 100644 --- a/src/freq_ctr.c +++ b/src/freq_ctr.c @@ -274,6 +274,67 @@ unsigned int freq_ctr_remain_period(struct freq_ctr_period *ctr, unsigned int pe return freq; } +/* Returns the total number of events over the current + last period, including + * a number of already pending events . The average frequency will be + * obtained by dividing the output by . This is essentially made to + * ease implementation of higher-level read functions. + * + * As a special case, if pend < 0, it's assumed there are no pending + * events and a flapping correction must be applied at the end. This is used by + * read_freq_ctr_period() to avoid reporting ups and downs on low-frequency + * events when the past value is <= 1. + */ +ullong freq_ctr_total(struct freq_ctr_period *ctr, uint period, int pend) +{ + ullong curr, past; + uint curr_tick; + int remain; + + for (;; __ha_cpu_relax()) { + curr = ctr->curr_ctr; + past = ctr->prev_ctr; + curr_tick = ctr->curr_tick; + + /* now let's make sure the second loads retrieve the most + * up-to-date values. If no value changed after a load barrier, + * we're certain the values we got were stable. + */ + __ha_barrier_load(); + + if (curr_tick & 0x1) + continue; + + if (curr != ctr->curr_ctr) + continue; + + if (past != ctr->prev_ctr) + continue; + + if (curr_tick != ctr->curr_tick) + continue; + break; + }; + + remain = curr_tick + period - global_now_ms; + if (unlikely(remain < 0)) { + /* We're past the first period, check if we can still report a + * part of last period or if we're too far away. + */ + remain += period; + past = (remain >= 0) ? curr : 0; + curr = 0; + } + + if (pend < 0) { + /* enable flapping correction at very low rates */ + pend = 0; + if (!curr && past <= 1) + return past * period; + } + + /* compute the total number of confirmed events over the period */ + return past * remain + (curr + pend) * period; +} /* * Local variables: