2020-05-28 09:29:19 -04:00
|
|
|
/*
|
|
|
|
|
* include/haproxy/thread-t.h
|
|
|
|
|
* Definitions and types for thread support.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2017 Christopher Faulet - cfaulet@haproxy.com
|
|
|
|
|
* Copyright (C) 2020 Willy Tarreau - w@1wt.eu
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
|
|
|
* exclusively.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef _HAPROXY_THREAD_T_H
|
|
|
|
|
#define _HAPROXY_THREAD_T_H
|
|
|
|
|
|
2020-06-11 02:14:01 -04:00
|
|
|
#include <haproxy/defaults.h>
|
2020-05-28 09:29:19 -04:00
|
|
|
|
|
|
|
|
/* Note: this file mainly contains 3 sections:
|
|
|
|
|
* - one used solely when USE_THREAD is *not* set
|
|
|
|
|
* - one used solely when USE_THREAD is set
|
|
|
|
|
* - a common one.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef USE_THREAD
|
|
|
|
|
|
|
|
|
|
/********************** THREADS DISABLED ************************/
|
|
|
|
|
|
|
|
|
|
/* These macros allow to make some struct fields or local variables optional */
|
|
|
|
|
#define __decl_spinlock(lock)
|
|
|
|
|
#define __decl_aligned_spinlock(lock)
|
|
|
|
|
#define __decl_rwlock(lock)
|
|
|
|
|
#define __decl_aligned_rwlock(lock)
|
|
|
|
|
|
2025-04-28 03:00:00 -04:00
|
|
|
#elif (DEBUG_THREAD < 1) && !defined(DEBUG_FULL)
|
2020-10-18 04:20:59 -04:00
|
|
|
|
|
|
|
|
/************** THREADS ENABLED WITHOUT DEBUGGING **************/
|
|
|
|
|
|
|
|
|
|
/* declare a self-initializing spinlock */
|
|
|
|
|
#define __decl_spinlock(lock) \
|
|
|
|
|
HA_SPINLOCK_T (lock) = 0;
|
|
|
|
|
|
|
|
|
|
/* declare a self-initializing spinlock, aligned on a cache line */
|
|
|
|
|
#define __decl_aligned_spinlock(lock) \
|
|
|
|
|
HA_SPINLOCK_T (lock) __attribute__((aligned(64))) = 0;
|
|
|
|
|
|
|
|
|
|
/* declare a self-initializing rwlock */
|
|
|
|
|
#define __decl_rwlock(lock) \
|
|
|
|
|
HA_RWLOCK_T (lock) = 0;
|
|
|
|
|
|
|
|
|
|
/* declare a self-initializing rwlock, aligned on a cache line */
|
|
|
|
|
#define __decl_aligned_rwlock(lock) \
|
|
|
|
|
HA_RWLOCK_T (lock) __attribute__((aligned(64))) = 0;
|
|
|
|
|
|
2020-05-28 09:29:19 -04:00
|
|
|
#else /* !USE_THREAD */
|
|
|
|
|
|
2020-10-18 04:20:59 -04:00
|
|
|
/**************** THREADS ENABLED WITH DEBUGGING ***************/
|
2020-05-28 09:29:19 -04:00
|
|
|
|
|
|
|
|
/* declare a self-initializing spinlock */
|
|
|
|
|
#define __decl_spinlock(lock) \
|
|
|
|
|
HA_SPINLOCK_T (lock); \
|
|
|
|
|
INITCALL1(STG_LOCK, ha_spin_init, &(lock))
|
|
|
|
|
|
|
|
|
|
/* declare a self-initializing spinlock, aligned on a cache line */
|
|
|
|
|
#define __decl_aligned_spinlock(lock) \
|
|
|
|
|
HA_SPINLOCK_T (lock) __attribute__((aligned(64))); \
|
|
|
|
|
INITCALL1(STG_LOCK, ha_spin_init, &(lock))
|
|
|
|
|
|
|
|
|
|
/* declare a self-initializing rwlock */
|
|
|
|
|
#define __decl_rwlock(lock) \
|
|
|
|
|
HA_RWLOCK_T (lock); \
|
|
|
|
|
INITCALL1(STG_LOCK, ha_rwlock_init, &(lock))
|
|
|
|
|
|
|
|
|
|
/* declare a self-initializing rwlock, aligned on a cache line */
|
|
|
|
|
#define __decl_aligned_rwlock(lock) \
|
|
|
|
|
HA_RWLOCK_T (lock) __attribute__((aligned(64))); \
|
|
|
|
|
INITCALL1(STG_LOCK, ha_rwlock_init, &(lock))
|
|
|
|
|
|
|
|
|
|
#endif /* USE_THREAD */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*** Common parts below ***/
|
|
|
|
|
|
|
|
|
|
/* storage types used by spinlocks and RW locks */
|
2021-02-17 09:45:01 -05:00
|
|
|
#define __HA_SPINLOCK_T unsigned long
|
|
|
|
|
#define __HA_RWLOCK_T unsigned long
|
2020-05-28 09:29:19 -04:00
|
|
|
|
2025-04-25 05:37:07 -04:00
|
|
|
/* 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;
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-28 09:29:19 -04:00
|
|
|
|
|
|
|
|
/* When thread debugging is enabled, we remap HA_SPINLOCK_T and HA_RWLOCK_T to
|
|
|
|
|
* complex structures which embed debugging info.
|
|
|
|
|
*/
|
2025-04-28 03:05:02 -04:00
|
|
|
#if (DEBUG_THREAD < 2) && !defined(DEBUG_FULL)
|
2020-05-28 09:29:19 -04:00
|
|
|
|
|
|
|
|
#define HA_SPINLOCK_T __HA_SPINLOCK_T
|
|
|
|
|
#define HA_RWLOCK_T __HA_RWLOCK_T
|
|
|
|
|
|
|
|
|
|
#else /* !DEBUG_THREAD */
|
|
|
|
|
|
|
|
|
|
#define HA_SPINLOCK_T struct ha_spinlock
|
|
|
|
|
#define HA_RWLOCK_T struct ha_rwlock
|
|
|
|
|
|
|
|
|
|
/* Debugging information that is only used when thread debugging is enabled */
|
|
|
|
|
|
2025-02-10 05:15:44 -05:00
|
|
|
/* This is aligned as it's already 256B per lock label, so better simplify the
|
2025-02-10 04:41:35 -05:00
|
|
|
* address calculations in the fast path than save a few bytes in BSS.
|
|
|
|
|
*/
|
2020-05-28 09:29:19 -04:00
|
|
|
struct lock_stat {
|
2025-02-10 05:08:45 -05:00
|
|
|
uint64_t nsec_wait;
|
|
|
|
|
uint64_t num_unlocked;
|
2025-02-10 05:15:44 -05:00
|
|
|
uint64_t buckets[30]; // operations per time buckets (1-2ns to 0.5-1s)
|
2025-02-10 04:41:35 -05:00
|
|
|
} ALIGNED(256);
|
2020-05-28 09:29:19 -04:00
|
|
|
|
2022-07-15 11:53:10 -04:00
|
|
|
struct ha_spinlock_state {
|
|
|
|
|
unsigned long owner; /* a bit is set to 1 << tid for the lock owner */
|
|
|
|
|
unsigned long waiters; /* a bit is set to 1 << tid for waiting threads */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ha_rwlock_state {
|
|
|
|
|
unsigned long cur_writer; /* a bit is set to 1 << tid for the lock owner */
|
|
|
|
|
unsigned long wait_writers; /* a bit is set to 1 << tid for waiting writers */
|
|
|
|
|
unsigned long cur_readers; /* a bit is set to 1 << tid for current readers */
|
|
|
|
|
unsigned long wait_readers; /* a bit is set to 1 << tid for waiting waiters */
|
|
|
|
|
unsigned long cur_seeker; /* a bit is set to 1 << tid for the lock seekers */
|
|
|
|
|
unsigned long wait_seekers; /* a bit is set to 1 << tid for waiting seekers */
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-28 09:29:19 -04:00
|
|
|
struct ha_spinlock {
|
|
|
|
|
__HA_SPINLOCK_T lock;
|
|
|
|
|
struct {
|
2022-07-15 11:53:10 -04:00
|
|
|
struct ha_spinlock_state st[MAX_TGROUPS];
|
2020-05-28 09:29:19 -04:00
|
|
|
struct {
|
|
|
|
|
const char *function;
|
|
|
|
|
const char *file;
|
|
|
|
|
int line;
|
|
|
|
|
} last_location; /* location of the last owner */
|
|
|
|
|
} info;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ha_rwlock {
|
|
|
|
|
__HA_RWLOCK_T lock;
|
|
|
|
|
struct {
|
2022-07-15 11:53:10 -04:00
|
|
|
struct ha_rwlock_state st[MAX_TGROUPS];
|
2020-05-28 09:29:19 -04:00
|
|
|
struct {
|
|
|
|
|
const char *function;
|
|
|
|
|
const char *file;
|
|
|
|
|
int line;
|
|
|
|
|
} last_location; /* location of the last write owner */
|
|
|
|
|
} info;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif /* DEBUG_THREAD */
|
|
|
|
|
|
2024-02-14 02:39:57 -05:00
|
|
|
/* WARNING!!! if you update this enum, please also keep lock_label() up to date
|
|
|
|
|
* below.
|
|
|
|
|
*/
|
|
|
|
|
enum lock_label {
|
|
|
|
|
TASK_RQ_LOCK,
|
|
|
|
|
TASK_WQ_LOCK,
|
|
|
|
|
LISTENER_LOCK,
|
|
|
|
|
PROXY_LOCK,
|
|
|
|
|
SERVER_LOCK,
|
|
|
|
|
LBPRM_LOCK,
|
|
|
|
|
SIGNALS_LOCK,
|
|
|
|
|
STK_TABLE_LOCK,
|
2025-04-24 08:01:13 -04:00
|
|
|
STK_TABLE_UPDT_LOCK,
|
2024-02-14 02:39:57 -05:00
|
|
|
STK_SESS_LOCK,
|
|
|
|
|
APPLETS_LOCK,
|
|
|
|
|
PEER_LOCK,
|
|
|
|
|
SHCTX_LOCK,
|
|
|
|
|
SSL_LOCK,
|
|
|
|
|
SSL_GEN_CERTS_LOCK,
|
|
|
|
|
PATREF_LOCK,
|
|
|
|
|
PATEXP_LOCK,
|
|
|
|
|
VARS_LOCK,
|
|
|
|
|
COMP_POOL_LOCK,
|
|
|
|
|
LUA_LOCK,
|
|
|
|
|
NOTIF_LOCK,
|
|
|
|
|
SPOE_APPLET_LOCK,
|
|
|
|
|
DNS_LOCK,
|
|
|
|
|
PID_LIST_LOCK,
|
|
|
|
|
PIPES_LOCK,
|
|
|
|
|
TLSKEYS_REF_LOCK,
|
|
|
|
|
AUTH_LOCK,
|
|
|
|
|
RING_LOCK,
|
|
|
|
|
DICT_LOCK,
|
|
|
|
|
PROTO_LOCK,
|
|
|
|
|
QUEUE_LOCK,
|
|
|
|
|
CKCH_LOCK,
|
|
|
|
|
SNI_LOCK,
|
|
|
|
|
SSL_SERVER_LOCK,
|
|
|
|
|
SFT_LOCK, /* sink forward target */
|
|
|
|
|
IDLE_CONNS_LOCK,
|
|
|
|
|
OCSP_LOCK,
|
|
|
|
|
QC_CID_LOCK,
|
|
|
|
|
CACHE_LOCK,
|
BUG/MINOR: guid/server: ensure thread-safety on GUID insert/delete
Since 3.0, it is possible to assign a GUID to proxies, listeners and
servers. These objects are stored in a global tree guid_tree.
Proxies and listeners are static. However, servers may be added or
deleted at runtime, which imply that guid_tree must be protected. Fix
this by declaring a read-write lock to protect tree access.
For now, only guid_insert() and guid_remove() are protected using a
write lock. Outside of these, GUID tree is not accessed at runtime. If
server CLI commands are extended to support GUID as server identifier,
lookup operation should be extended with a read lock protection.
Note that during stat-file preloading, GUID tree is accessed for lookup.
However, as it is performed on startup which is single threaded, there
is no need for lock here. A BUG_ON() has been added to ensure this
precondition remains true.
This bug could caused a segfault when using dynamic servers with GUID.
However, it was never reproduced for now.
This must be backported up to 3.0. To avoid a conflict issue, the
previous cleanup patch can be merged before it.
2024-11-07 05:08:40 -05:00
|
|
|
GUID_LOCK,
|
2025-06-30 10:56:26 -04:00
|
|
|
JWT_LOCK,
|
2024-02-14 02:39:57 -05:00
|
|
|
OTHER_LOCK,
|
|
|
|
|
/* WT: make sure never to use these ones outside of development,
|
|
|
|
|
* we need them for lock profiling!
|
|
|
|
|
*/
|
|
|
|
|
DEBUG1_LOCK,
|
|
|
|
|
DEBUG2_LOCK,
|
|
|
|
|
DEBUG3_LOCK,
|
|
|
|
|
DEBUG4_LOCK,
|
|
|
|
|
DEBUG5_LOCK,
|
|
|
|
|
LOCK_LABELS
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-28 09:29:19 -04:00
|
|
|
#endif /* _HAPROXY_THREAD_T_H */
|