]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: thread: define cshared type
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 25 Apr 2025 09:37:07 +0000 (11:37 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 29 Apr 2025 13:10:06 +0000 (15:10 +0200)
Define a new type "struct cshared". This can be used as a tool to
manipulate a global counter with thread-safety ensured. Each thread
would declare its thread-local cshared type, which would point to a
global counter.

Each thread can then add/substract value to their owned thread-local
cshared instance via cshared_add(). If the difference exceed a
configured limit, either positively or negatively, the global counter is
updated and thread-local instance is reset to 0. Each thread can safely
read the global counter value using cshared_read().

include/haproxy/thread-t.h
include/haproxy/thread.h

index 8eba633d0aa0ac1d305262beda91b87c7a9cf9a4..0d8cf3b39adf89b36360c58e7db867ee77e9ca59 100644 (file)
 #define __HA_SPINLOCK_T     unsigned long
 #define __HA_RWLOCK_T       unsigned long
 
+/* Type used as a shared value from a global counter. Manipulation to the
+ * global value is thread-safe. Share counter can be increased/decreased
+ * without modifying the global value to reduce contention. The global value is
+ * modified only when the configured limit is reached.
+ *
+ * Typically a cshared is declared as a thread-local variable, with a reference
+ * to a process global value.
+ */
+struct cshared {
+       uint64_t *global;
+       int diff;
+       int lim;
+};
+
 
 /* When thread debugging is enabled, we remap HA_SPINLOCK_T and HA_RWLOCK_T to
  * complex structures which embed debugging info.
index 4ed2dd677086a4a72e9eaa91874685a7915f9d6d..92bf6a647e8cc4b873a68b503e86b0feeea615ac 100644 (file)
@@ -173,6 +173,23 @@ static inline unsigned long long ha_get_pthread_id(unsigned int thr)
        return 0;
 }
 
+static inline void cshared_init(struct cshared *ctr, uint64_t *var, int lim)
+{
+       ctr->global = var;
+       ctr->diff = 0;
+       ctr->lim = 0;
+}
+
+static inline void cshared_add(struct cshared *ctr, int diff)
+{
+       ctr->global += diff;
+}
+
+static inline uint64_t cshared_read(struct cshared *ctr)
+{
+       return *ctr->global;
+}
+
 #else /* !USE_THREAD */
 
 /********************** THREADS ENABLED ************************/
@@ -332,6 +349,33 @@ static inline unsigned long thread_isolated()
 
 #endif
 
+/* Init a shared counter <ctr> which references global value <var>. Update are
+ * performed each time the shared counter exceed <lim>, either on the positive
+ * or negative value.
+ */
+static inline void cshared_init(struct cshared *ctr, uint64_t *var, int lim)
+{
+       ctr->global = var;
+       ctr->diff = 0;
+       ctr->lim = lim;
+}
+
+/* Add <diff>, which may be positive or negative, to <ctr> shared counter. */
+static inline void cshared_add(struct cshared *ctr, int diff)
+{
+       ctr->diff += diff;
+       if (ctr->diff <= -(ctr->lim) || ctr->diff >= ctr->lim) {
+               HA_ATOMIC_ADD(ctr->global, ctr->diff);
+               ctr->diff = 0;
+       }
+}
+
+/* Atomically get current global value from <ctr> shared counter. */
+static inline uint64_t cshared_read(struct cshared *ctr)
+{
+       return HA_ATOMIC_LOAD(ctr->global);
+}
+
 #if (DEBUG_THREAD < 2) && !defined(DEBUG_FULL)
 
 /* Thread debugging is DISABLED, these are the regular locking functions */