MEDIUM: threads/freq_ctr: Make the frequency counters thread-safe

When a frequency counter must be updated, we use the curr_sec/curr_tick fields
as a lock, by setting the MSB to 1 in a compare-and-swap to lock and by reseting
it to unlock. And when we need to read it, we loop until the counter is
unlocked. This way, the frequency counters are thread-safe without any external
lock. It is important to avoid increasing the size of many structures (global,
proxy, server, stick_table).
diff --git a/src/freq_ctr.c b/src/freq_ctr.c
index 6dec970..37fb1f3 100644
--- a/src/freq_ctr.c
+++ b/src/freq_ctr.c
@@ -31,17 +31,25 @@
 unsigned int read_freq_ctr(struct freq_ctr *ctr)
 {
 	unsigned int curr, past;
-	unsigned int age;
+	unsigned int age, curr_sec;
 
-	age = now.tv_sec - ctr->curr_sec;
+	do {
+		curr = ctr->curr_ctr;
+		past = ctr->prev_ctr;
+		curr_sec = ctr->curr_sec;
+
+	} while (curr != ctr->curr_ctr
+		 || past != ctr->prev_ctr
+		 || curr_sec !=  ctr->curr_sec
+		 || (curr_sec & 0x80000000));
+
+	age = now.tv_sec - curr_sec;
 	if (unlikely(age > 1))
 		return 0;
 
-	curr = 0;		
-	past = ctr->curr_ctr;
-	if (likely(!age)) {
-		curr = past;
-		past = ctr->prev_ctr;
+	if (unlikely(age)) {
+		past = curr;
+		curr = 0;
 	}
 
 	if (past <= 1 && !curr)
@@ -57,16 +65,25 @@
 unsigned int freq_ctr_remain(struct freq_ctr *ctr, unsigned int freq, unsigned int pend)
 {
 	unsigned int curr, past;
-	unsigned int age;
+	unsigned int age, curr_sec;
+
+	do {
+		curr = ctr->curr_ctr;
+		past = ctr->prev_ctr;
+		curr_sec = ctr->curr_sec;
 
-	curr = 0;		
-	age = now.tv_sec - ctr->curr_sec;
+	} while (curr != ctr->curr_ctr
+		 || past != ctr->prev_ctr
+		 || curr_sec !=  ctr->curr_sec
+		 || (curr_sec & 0x80000000));
 
-	if (likely(age <= 1)) {
-		past = ctr->curr_ctr;
-		if (likely(!age)) {
-			curr = past;
-			past = ctr->prev_ctr;
+	age = now.tv_sec - curr_sec;
+	if (unlikely(age > 1))
+		curr = 0;
+	else {
+		if (unlikely(age == 1)) {
+			past = curr;
+			curr = 0;
 		}
 		curr += mul32hi(past, ms_left_scaled);
 	}
@@ -86,17 +103,25 @@
 unsigned int next_event_delay(struct freq_ctr *ctr, unsigned int freq, unsigned int pend)
 {
 	unsigned int curr, past;
-	unsigned int wait, age;
+	unsigned int wait, age, curr_sec;
+
+	do {
+		curr = ctr->curr_ctr;
+		past = ctr->prev_ctr;
+		curr_sec = ctr->curr_sec;
 
-	past = 0;
-	curr = 0;		
-	age = now.tv_sec - ctr->curr_sec;
+	} while (curr != ctr->curr_ctr
+		 || past != ctr->prev_ctr
+		 || curr_sec !=  ctr->curr_sec
+		 || (curr_sec & 0x80000000));
 
-	if (likely(age <= 1)) {
-		past = ctr->curr_ctr;
-		if (likely(!age)) {
-			curr = past;
-			past = ctr->prev_ctr;
+	age = now.tv_sec - curr_sec;
+	if (unlikely(age > 1))
+		curr = 0;
+	else {
+		if (unlikely(age == 1)) {
+			past = curr;
+			curr = 0;
 		}
 		curr += mul32hi(past, ms_left_scaled);
 	}
@@ -128,12 +153,19 @@
 unsigned int read_freq_ctr_period(struct freq_ctr_period *ctr, unsigned int period)
 {
 	unsigned int curr, past;
-	unsigned int remain;
+	unsigned int remain, curr_tick;
 
-	curr = ctr->curr_ctr;
-	past = ctr->prev_ctr;
+	do {
+		curr = ctr->curr_ctr;
+		past = ctr->prev_ctr;
+		curr_tick = ctr->curr_tick;
+
+	} while (curr != ctr->curr_ctr
+		 ||  past != ctr->prev_ctr
+		 || curr_tick !=  ctr->curr_tick
+		 || (curr_tick & 0x1));
 
-	remain = ctr->curr_tick + period - now_ms;
+	remain = curr_tick + period - now_ms;
 	if (unlikely((int)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.
@@ -159,12 +191,19 @@
 				    unsigned int freq, unsigned int pend)
 {
 	unsigned int curr, past;
-	unsigned int remain;
+	unsigned int remain, curr_tick;
 
-	curr = ctr->curr_ctr;
-	past = ctr->prev_ctr;
+	do {
+		curr = ctr->curr_ctr;
+		past = ctr->prev_ctr;
+		curr_tick = ctr->curr_tick;
+
+	} while (curr != ctr->curr_ctr
+		 ||  past != ctr->prev_ctr
+		 || curr_tick !=  ctr->curr_tick
+		 || (curr_tick & 0x1));
 
-	remain = ctr->curr_tick + period - now_ms;
+	remain = curr_tick + period - now_ms;
 	if (likely((int)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.