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 */