From: Amaury Denoyelle Date: Fri, 25 Apr 2025 09:37:07 +0000 (+0200) Subject: MINOR: thread: define cshared type X-Git-Tag: v3.2-dev13~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3891456d209febfb1eb2d1d398b5b40602616423;p=thirdparty%2Fhaproxy.git MINOR: thread: define cshared type 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(). --- diff --git a/include/haproxy/thread-t.h b/include/haproxy/thread-t.h index 8eba633d0..0d8cf3b39 100644 --- a/include/haproxy/thread-t.h +++ b/include/haproxy/thread-t.h @@ -94,6 +94,20 @@ #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. diff --git a/include/haproxy/thread.h b/include/haproxy/thread.h index 4ed2dd677..92bf6a647 100644 --- a/include/haproxy/thread.h +++ b/include/haproxy/thread.h @@ -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 which references global value . Update are + * performed each time the shared counter exceed , 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 , which may be positive or negative, to 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 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 */