REORG: include: split hathreads into haproxy/thread.h and haproxy/thread-t.h
This splits the hathreads.h file into types+macros and functions. Given that most users of this file used to include it only to get the definition of THREAD_LOCAL and MAXTHREADS, the bare minimum was placed into thread-t.h (i.e. types and macros). All the thread management was left to haproxy/thread.h. It's worth noting the drop of the trailing "s" in the name, to remove the permanent confusion that arises between this one and the system implementation (no "s") and the makefile's option (no "s"). For consistency, src/hathreads.c was also renamed thread.c. A number of files were updated to only include thread-t which is the one they really needed. Some future improvements are possible like replacing empty inlined functions with macros for the thread-less case, as building at -O0 disables inlining and causes these ones to be emitted. But this really is cosmetic.
This commit is contained in:
parent
5775d0964a
commit
3f567e4949
@ -77,7 +77,7 @@ Files: src/flt_spoe.c, include/*/spoe.h, contrib/spoa_example, doc/SPOE.txt
|
||||
Multi-threading
|
||||
Maintainer: Christopher Faulet <cfaulet@haproxy.com>
|
||||
Maintainer: Emeric Brun <ebrun@haproxy.com>
|
||||
Files: src/hathreads.c, include/*/hathreads.h
|
||||
Files: src/thread.c, include/*/thread.h
|
||||
Note: every change around the locking or synchronization point will require
|
||||
approval from one of these maintainers. Problems which only appear when
|
||||
nbthread is greater than 1 and which disappear otherwise are also
|
||||
|
2
Makefile
2
Makefile
@ -805,7 +805,7 @@ OBJS = src/mux_h2.o src/stream.o src/mux_fcgi.o src/cfgparse-listen.o \
|
||||
src/htx.o src/memory.o src/applet.o src/channel.o src/signal.o \
|
||||
src/lb_fwrr.o src/ev_select.o src/sink.o src/http_conv.o \
|
||||
src/proto_sockpair.o src/mworker-prog.o src/activity.o src/lb_fwlc.o \
|
||||
src/http.o src/lb_fas.o src/uri_auth.o src/hathreads.o src/regex.o \
|
||||
src/http.o src/lb_fas.o src/uri_auth.o src/thread.o src/regex.o \
|
||||
src/auth.o src/buffer.o src/compression.o src/proto_udp.o src/lb_map.o \
|
||||
src/chunk.o src/wdt.o src/hpack-dec.o src/action.o src/xxhash.o \
|
||||
src/pipe.o src/shctx.o src/hpack-tbl.o src/http_acl.o src/sha1.o \
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/list.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
/* On architectures supporting threads and double-word CAS, we can implement
|
||||
* lock-less memory pools. This isn't supported for debugging modes however.
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
|
||||
#ifdef USE_PCRE
|
||||
#include <pcre.h>
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/standard.h>
|
||||
|
||||
/* eternity when exprimed in timeval */
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/list-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
/* First undefine some macros which happen to also be defined on OpenBSD,
|
||||
* in sys/queue.h, used by sys/event.h
|
||||
|
171
include/haproxy/thread-t.h
Normal file
171
include/haproxy/thread-t.h
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#ifdef USE_THREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
|
||||
/* 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 ************************/
|
||||
|
||||
#define THREAD_LOCAL /* empty */
|
||||
#define MAX_THREADS 1
|
||||
#define MAX_THREADS_MASK 1
|
||||
|
||||
/* These macros allow to make some struct fields or local variables optional */
|
||||
#define __decl_hathreads(decl)
|
||||
#define __decl_spinlock(lock)
|
||||
#define __decl_aligned_spinlock(lock)
|
||||
#define __decl_rwlock(lock)
|
||||
#define __decl_aligned_rwlock(lock)
|
||||
|
||||
#else /* !USE_THREAD */
|
||||
|
||||
/********************** THREADS ENABLED ************************/
|
||||
|
||||
#define THREAD_LOCAL __thread
|
||||
|
||||
#ifndef MAX_THREADS
|
||||
#define MAX_THREADS LONGBITS
|
||||
#endif
|
||||
|
||||
#define MAX_THREADS_MASK (~0UL >> (LONGBITS - MAX_THREADS))
|
||||
|
||||
#define __decl_hathreads(decl) decl
|
||||
|
||||
/* 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 ***/
|
||||
|
||||
/* thread info flags, for ha_thread_info[].flags */
|
||||
#define TI_FL_STUCK 0x00000001
|
||||
|
||||
/* This structure describes all the per-thread info we need. When threads are
|
||||
* disabled, it contains the same info for the single running thread (except
|
||||
* the pthread identifier which does not exist).
|
||||
*/
|
||||
struct thread_info {
|
||||
__decl_hathreads(pthread_t pthread);
|
||||
clockid_t clock_id;
|
||||
timer_t wd_timer; /* valid timer or TIMER_INVALID if not set */
|
||||
uint64_t prev_cpu_time; /* previous per thread CPU time */
|
||||
uint64_t prev_mono_time; /* previous system wide monotonic time */
|
||||
unsigned int idle_pct; /* idle to total ratio over last sample (percent) */
|
||||
unsigned int flags; /* thread info flags, TI_FL_* */
|
||||
/* pad to cache line (64B) */
|
||||
char __pad[0]; /* unused except to check remaining room */
|
||||
char __end[0] __attribute__((aligned(64)));
|
||||
};
|
||||
|
||||
/* storage types used by spinlocks and RW locks */
|
||||
#define __HA_SPINLOCK_T unsigned long
|
||||
#define __HA_RWLOCK_T unsigned long
|
||||
|
||||
|
||||
/* When thread debugging is enabled, we remap HA_SPINLOCK_T and HA_RWLOCK_T to
|
||||
* complex structures which embed debugging info.
|
||||
*/
|
||||
#if !defined(DEBUG_THREAD) && !defined(DEBUG_FULL)
|
||||
|
||||
#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 */
|
||||
|
||||
struct lock_stat {
|
||||
uint64_t nsec_wait_for_write;
|
||||
uint64_t nsec_wait_for_read;
|
||||
uint64_t num_write_locked;
|
||||
uint64_t num_write_unlocked;
|
||||
uint64_t num_read_locked;
|
||||
uint64_t num_read_unlocked;
|
||||
};
|
||||
|
||||
struct ha_spinlock {
|
||||
__HA_SPINLOCK_T lock;
|
||||
struct {
|
||||
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 {
|
||||
const char *function;
|
||||
const char *file;
|
||||
int line;
|
||||
} last_location; /* location of the last owner */
|
||||
} info;
|
||||
};
|
||||
|
||||
struct ha_rwlock {
|
||||
__HA_RWLOCK_T lock;
|
||||
struct {
|
||||
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 */
|
||||
struct {
|
||||
const char *function;
|
||||
const char *file;
|
||||
int line;
|
||||
} last_location; /* location of the last write owner */
|
||||
} info;
|
||||
};
|
||||
|
||||
#endif /* DEBUG_THREAD */
|
||||
|
||||
#endif /* _HAPROXY_THREAD_T_H */
|
@ -1,8 +1,9 @@
|
||||
/*
|
||||
* include/common/hathreads.h
|
||||
* definitions, macros and inline functions about threads.
|
||||
* include/haproxy/thread.h
|
||||
* definitions, macros and inline functions used by threads.
|
||||
*
|
||||
* Copyright (C) 2017 Christopher Fauet - cfaulet@haproxy.com
|
||||
* 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
|
||||
@ -19,79 +20,66 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_HATHREADS_H
|
||||
#define _COMMON_HATHREADS_H
|
||||
#ifndef _HAPROXY_THREAD_H
|
||||
#define _HAPROXY_THREAD_H
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#ifdef _POSIX_PRIORITY_SCHEDULING
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#include <haproxy/atomic.h>
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
|
||||
|
||||
/* Note about all_threads_mask :
|
||||
* - this variable is comprised between 1 and LONGBITS.
|
||||
* - with threads support disabled, this symbol is defined as constant 1UL.
|
||||
* - with threads enabled, it contains the mask of enabled threads. Thus if
|
||||
* only one thread is enabled, it equals 1.
|
||||
/* Note: this file mainly contains 5 sections:
|
||||
* - a small common part, which also corresponds to the common API
|
||||
* - one used solely when USE_THREAD is *not* set
|
||||
* - one used solely when USE_THREAD is set
|
||||
* - one used solely when USE_THREAD is set WITHOUT debugging
|
||||
* - one used solely when USE_THREAD is set WITH debugging
|
||||
*
|
||||
*/
|
||||
|
||||
/* thread info flags, for ha_thread_info[].flags */
|
||||
#define TI_FL_STUCK 0x00000001
|
||||
|
||||
/* Generic exports */
|
||||
int parse_nbthread(const char *arg, char **err);
|
||||
int thread_get_default_count();
|
||||
extern int thread_cpus_enabled_at_boot;
|
||||
extern struct thread_info ha_thread_info[MAX_THREADS];
|
||||
extern THREAD_LOCAL struct thread_info *ti; /* thread_info for the current thread */
|
||||
|
||||
|
||||
#ifndef USE_THREAD
|
||||
|
||||
#define THREAD_LOCAL /* empty */
|
||||
#define MAX_THREADS 1
|
||||
#define MAX_THREADS_MASK 1
|
||||
/********************** THREADS DISABLED ************************/
|
||||
|
||||
/* Only way found to replace variables with constants that are optimized away
|
||||
* at build time.
|
||||
*/
|
||||
enum { all_threads_mask = 1UL };
|
||||
enum { threads_harmless_mask = 0 };
|
||||
enum { threads_want_rdv_mask = 0 };
|
||||
enum { threads_sync_mask = 0 };
|
||||
enum { threads_want_rdv_mask = 0 };
|
||||
enum { tid_bit = 1UL };
|
||||
enum { tid = 0 };
|
||||
|
||||
extern struct thread_info {
|
||||
clockid_t clock_id;
|
||||
timer_t wd_timer; /* valid timer or TIMER_INVALID if not set */
|
||||
uint64_t prev_cpu_time; /* previous per thread CPU time */
|
||||
uint64_t prev_mono_time; /* previous system wide monotonic time */
|
||||
unsigned int idle_pct; /* idle to total ratio over last sample (percent) */
|
||||
unsigned int flags; /* thread info flags, TI_FL_* */
|
||||
/* pad to cache line (64B) */
|
||||
char __pad[0]; /* unused except to check remaining room */
|
||||
char __end[0] __attribute__((aligned(64)));
|
||||
} ha_thread_info[MAX_THREADS];
|
||||
#define HA_SPIN_INIT(l) do { /* do nothing */ } while(0)
|
||||
#define HA_SPIN_DESTROY(l) do { /* do nothing */ } while(0)
|
||||
#define HA_SPIN_LOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_SPIN_TRYLOCK(lbl, l) ({ 0; })
|
||||
#define HA_SPIN_UNLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
|
||||
extern THREAD_LOCAL struct thread_info *ti; /* thread_info for the current thread */
|
||||
|
||||
#define __decl_hathreads(decl)
|
||||
#define __decl_spinlock(lock)
|
||||
#define __decl_aligned_spinlock(lock)
|
||||
#define __decl_rwlock(lock)
|
||||
#define __decl_aligned_rwlock(lock)
|
||||
|
||||
#define HA_SPIN_INIT(l) do { /* do nothing */ } while(0)
|
||||
#define HA_SPIN_DESTROY(l) do { /* do nothing */ } while(0)
|
||||
#define HA_SPIN_LOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_SPIN_TRYLOCK(lbl, l) ({ 0; })
|
||||
#define HA_SPIN_UNLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
|
||||
#define HA_RWLOCK_INIT(l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_DESTROY(l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_WRLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_INIT(l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_DESTROY(l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_WRLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_TRYWRLOCK(lbl, l) ({ 0; })
|
||||
#define HA_RWLOCK_WRUNLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_RDLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_WRUNLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_RDLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_TRYRDLOCK(lbl, l) ({ 0; })
|
||||
#define HA_RWLOCK_RDUNLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
#define HA_RWLOCK_RDUNLOCK(lbl, l) do { /* do nothing */ } while(0)
|
||||
|
||||
#define ha_sigmask(how, set, oldset) sigprocmask(how, set, oldset)
|
||||
|
||||
@ -149,71 +137,30 @@ static inline unsigned long thread_isolated()
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* USE_THREAD */
|
||||
#else /* !USE_THREAD */
|
||||
|
||||
/********************** THREADS ENABLED ************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <import/plock.h>
|
||||
|
||||
#define THREAD_LOCAL __thread
|
||||
|
||||
#ifndef MAX_THREADS
|
||||
#define MAX_THREADS LONGBITS
|
||||
#endif
|
||||
|
||||
#define MAX_THREADS_MASK (~0UL >> (LONGBITS - MAX_THREADS))
|
||||
|
||||
#define __decl_hathreads(decl) decl
|
||||
|
||||
/* 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))
|
||||
|
||||
void thread_harmless_till_end();
|
||||
void thread_isolate();
|
||||
void thread_release();
|
||||
void thread_sync_release();
|
||||
void ha_tkill(unsigned int thr, int sig);
|
||||
void ha_tkillall(int sig);
|
||||
void ha_spin_init(HA_SPINLOCK_T *l);
|
||||
void ha_rwlock_init(HA_RWLOCK_T *l);
|
||||
|
||||
extern struct thread_info {
|
||||
pthread_t pthread;
|
||||
clockid_t clock_id;
|
||||
timer_t wd_timer; /* valid timer or TIMER_INVALID if not set */
|
||||
uint64_t prev_cpu_time; /* previous per thread CPU time */
|
||||
uint64_t prev_mono_time; /* previous system wide monotonic time */
|
||||
unsigned int idle_pct; /* idle to total ratio over last sample (percent) */
|
||||
unsigned int flags; /* thread info flags, TI_FL_* */
|
||||
/* pad to cache line (64B) */
|
||||
char __pad[0]; /* unused except to check remaining room */
|
||||
char __end[0] __attribute__((aligned(64)));
|
||||
} ha_thread_info[MAX_THREADS];
|
||||
|
||||
extern THREAD_LOCAL unsigned int tid; /* The thread id */
|
||||
extern THREAD_LOCAL unsigned long tid_bit; /* The bit corresponding to the thread id */
|
||||
extern THREAD_LOCAL struct thread_info *ti; /* thread_info for the current thread */
|
||||
extern volatile unsigned long all_threads_mask;
|
||||
extern volatile unsigned long threads_want_rdv_mask;
|
||||
extern volatile unsigned long threads_harmless_mask;
|
||||
extern volatile unsigned long threads_sync_mask;
|
||||
extern volatile unsigned long threads_want_rdv_mask;
|
||||
extern THREAD_LOCAL unsigned long tid_bit; /* The bit corresponding to the thread id */
|
||||
extern THREAD_LOCAL unsigned int tid; /* The thread id */
|
||||
|
||||
/* explanation for threads_want_rdv_mask, threads_harmless_mask, and
|
||||
* threads_sync_mask :
|
||||
@ -324,9 +271,63 @@ static inline unsigned long thread_isolated()
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
|
||||
#if !defined(DEBUG_THREAD) && !defined(DEBUG_FULL)
|
||||
|
||||
/* WARNING!!! if you update this enum, please also keep lock_label() up to date below */
|
||||
/* Thread debugging is DISABLED, these are the regular locking functions */
|
||||
|
||||
#define HA_SPIN_INIT(l) ({ (*l) = 0; })
|
||||
#define HA_SPIN_DESTROY(l) ({ (*l) = 0; })
|
||||
#define HA_SPIN_LOCK(lbl, l) pl_take_s(l)
|
||||
#define HA_SPIN_TRYLOCK(lbl, l) !pl_try_s(l)
|
||||
#define HA_SPIN_UNLOCK(lbl, l) pl_drop_s(l)
|
||||
|
||||
#define HA_RWLOCK_INIT(l) ({ (*l) = 0; })
|
||||
#define HA_RWLOCK_DESTROY(l) ({ (*l) = 0; })
|
||||
#define HA_RWLOCK_WRLOCK(lbl,l) pl_take_w(l)
|
||||
#define HA_RWLOCK_TRYWRLOCK(lbl,l) !pl_try_w(l)
|
||||
#define HA_RWLOCK_WRUNLOCK(lbl,l) pl_drop_w(l)
|
||||
#define HA_RWLOCK_RDLOCK(lbl,l) pl_take_r(l)
|
||||
#define HA_RWLOCK_TRYRDLOCK(lbl,l) !pl_try_r(l)
|
||||
#define HA_RWLOCK_RDUNLOCK(lbl,l) pl_drop_r(l)
|
||||
|
||||
#else /* !defined(DEBUG_THREAD) && !defined(DEBUG_FULL) */
|
||||
|
||||
/* Thread debugging is ENABLED, these are the instrumented functions */
|
||||
|
||||
#define __SPIN_INIT(l) ({ (*l) = 0; })
|
||||
#define __SPIN_DESTROY(l) ({ (*l) = 0; })
|
||||
#define __SPIN_LOCK(l) pl_take_s(l)
|
||||
#define __SPIN_TRYLOCK(l) !pl_try_s(l)
|
||||
#define __SPIN_UNLOCK(l) pl_drop_s(l)
|
||||
|
||||
#define __RWLOCK_INIT(l) ({ (*l) = 0; })
|
||||
#define __RWLOCK_DESTROY(l) ({ (*l) = 0; })
|
||||
#define __RWLOCK_WRLOCK(l) pl_take_w(l)
|
||||
#define __RWLOCK_TRYWRLOCK(l) !pl_try_w(l)
|
||||
#define __RWLOCK_WRUNLOCK(l) pl_drop_w(l)
|
||||
#define __RWLOCK_RDLOCK(l) pl_take_r(l)
|
||||
#define __RWLOCK_TRYRDLOCK(l) !pl_try_r(l)
|
||||
#define __RWLOCK_RDUNLOCK(l) pl_drop_r(l)
|
||||
|
||||
#define HA_SPIN_INIT(l) __spin_init(l)
|
||||
#define HA_SPIN_DESTROY(l) __spin_destroy(l)
|
||||
|
||||
#define HA_SPIN_LOCK(lbl, l) __spin_lock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_SPIN_TRYLOCK(lbl, l) __spin_trylock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_SPIN_UNLOCK(lbl, l) __spin_unlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
|
||||
#define HA_RWLOCK_INIT(l) __ha_rwlock_init((l))
|
||||
#define HA_RWLOCK_DESTROY(l) __ha_rwlock_destroy((l))
|
||||
#define HA_RWLOCK_WRLOCK(lbl,l) __ha_rwlock_wrlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_TRYWRLOCK(lbl,l) __ha_rwlock_trywrlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_WRUNLOCK(lbl,l) __ha_rwlock_wrunlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_RDLOCK(lbl,l) __ha_rwlock_rdlock(lbl, l)
|
||||
#define HA_RWLOCK_TRYRDLOCK(lbl,l) __ha_rwlock_tryrdlock(lbl, l)
|
||||
#define HA_RWLOCK_RDUNLOCK(lbl,l) __ha_rwlock_rdunlock(lbl, l)
|
||||
|
||||
/* WARNING!!! if you update this enum, please also keep lock_label() up to date
|
||||
* below.
|
||||
*/
|
||||
enum lock_label {
|
||||
TASK_RQ_LOCK,
|
||||
TASK_WQ_LOCK,
|
||||
@ -365,84 +366,9 @@ enum lock_label {
|
||||
OTHER_LOCK,
|
||||
LOCK_LABELS
|
||||
};
|
||||
struct lock_stat {
|
||||
uint64_t nsec_wait_for_write;
|
||||
uint64_t nsec_wait_for_read;
|
||||
uint64_t num_write_locked;
|
||||
uint64_t num_write_unlocked;
|
||||
uint64_t num_read_locked;
|
||||
uint64_t num_read_unlocked;
|
||||
};
|
||||
|
||||
extern struct lock_stat lock_stats[LOCK_LABELS];
|
||||
|
||||
#define __HA_SPINLOCK_T unsigned long
|
||||
|
||||
#define __SPIN_INIT(l) ({ (*l) = 0; })
|
||||
#define __SPIN_DESTROY(l) ({ (*l) = 0; })
|
||||
#define __SPIN_LOCK(l) pl_take_s(l)
|
||||
#define __SPIN_TRYLOCK(l) !pl_try_s(l)
|
||||
#define __SPIN_UNLOCK(l) pl_drop_s(l)
|
||||
|
||||
#define __HA_RWLOCK_T unsigned long
|
||||
|
||||
#define __RWLOCK_INIT(l) ({ (*l) = 0; })
|
||||
#define __RWLOCK_DESTROY(l) ({ (*l) = 0; })
|
||||
#define __RWLOCK_WRLOCK(l) pl_take_w(l)
|
||||
#define __RWLOCK_TRYWRLOCK(l) !pl_try_w(l)
|
||||
#define __RWLOCK_WRUNLOCK(l) pl_drop_w(l)
|
||||
#define __RWLOCK_RDLOCK(l) pl_take_r(l)
|
||||
#define __RWLOCK_TRYRDLOCK(l) !pl_try_r(l)
|
||||
#define __RWLOCK_RDUNLOCK(l) pl_drop_r(l)
|
||||
|
||||
#define HA_SPINLOCK_T struct ha_spinlock
|
||||
|
||||
#define HA_SPIN_INIT(l) __spin_init(l)
|
||||
#define HA_SPIN_DESTROY(l) __spin_destroy(l)
|
||||
|
||||
#define HA_SPIN_LOCK(lbl, l) __spin_lock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_SPIN_TRYLOCK(lbl, l) __spin_trylock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_SPIN_UNLOCK(lbl, l) __spin_unlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
|
||||
#define HA_RWLOCK_T struct ha_rwlock
|
||||
|
||||
#define HA_RWLOCK_INIT(l) __ha_rwlock_init((l))
|
||||
#define HA_RWLOCK_DESTROY(l) __ha_rwlock_destroy((l))
|
||||
#define HA_RWLOCK_WRLOCK(lbl,l) __ha_rwlock_wrlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_TRYWRLOCK(lbl,l) __ha_rwlock_trywrlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_WRUNLOCK(lbl,l) __ha_rwlock_wrunlock(lbl, l, __func__, __FILE__, __LINE__)
|
||||
#define HA_RWLOCK_RDLOCK(lbl,l) __ha_rwlock_rdlock(lbl, l)
|
||||
#define HA_RWLOCK_TRYRDLOCK(lbl,l) __ha_rwlock_tryrdlock(lbl, l)
|
||||
#define HA_RWLOCK_RDUNLOCK(lbl,l) __ha_rwlock_rdunlock(lbl, l)
|
||||
|
||||
struct ha_spinlock {
|
||||
__HA_SPINLOCK_T lock;
|
||||
struct {
|
||||
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 {
|
||||
const char *function;
|
||||
const char *file;
|
||||
int line;
|
||||
} last_location; /* location of the last owner */
|
||||
} info;
|
||||
};
|
||||
|
||||
struct ha_rwlock {
|
||||
__HA_RWLOCK_T lock;
|
||||
struct {
|
||||
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 */
|
||||
struct {
|
||||
const char *function;
|
||||
const char *file;
|
||||
int line;
|
||||
} last_location; /* location of the last write owner */
|
||||
} info;
|
||||
};
|
||||
|
||||
static inline const char *lock_label(enum lock_label label)
|
||||
{
|
||||
switch (label) {
|
||||
@ -519,7 +445,8 @@ static inline void show_lock_stats()
|
||||
/* Following functions are used to collect some stats about locks. We wrap
|
||||
* pthread functions to known how much time we wait in a lock. */
|
||||
|
||||
static uint64_t nsec_now(void) {
|
||||
static uint64_t nsec_now(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
@ -772,38 +699,8 @@ static inline void __spin_unlock(enum lock_label lbl, struct ha_spinlock *l,
|
||||
HA_ATOMIC_ADD(&lock_stats[lbl].num_write_unlocked, 1);
|
||||
}
|
||||
|
||||
#else /* DEBUG_THREAD */
|
||||
|
||||
#define HA_SPINLOCK_T unsigned long
|
||||
|
||||
#define HA_SPIN_INIT(l) ({ (*l) = 0; })
|
||||
#define HA_SPIN_DESTROY(l) ({ (*l) = 0; })
|
||||
#define HA_SPIN_LOCK(lbl, l) pl_take_s(l)
|
||||
#define HA_SPIN_TRYLOCK(lbl, l) !pl_try_s(l)
|
||||
#define HA_SPIN_UNLOCK(lbl, l) pl_drop_s(l)
|
||||
|
||||
#define HA_RWLOCK_T unsigned long
|
||||
|
||||
#define HA_RWLOCK_INIT(l) ({ (*l) = 0; })
|
||||
#define HA_RWLOCK_DESTROY(l) ({ (*l) = 0; })
|
||||
#define HA_RWLOCK_WRLOCK(lbl,l) pl_take_w(l)
|
||||
#define HA_RWLOCK_TRYWRLOCK(lbl,l) !pl_try_w(l)
|
||||
#define HA_RWLOCK_WRUNLOCK(lbl,l) pl_drop_w(l)
|
||||
#define HA_RWLOCK_RDLOCK(lbl,l) pl_take_r(l)
|
||||
#define HA_RWLOCK_TRYRDLOCK(lbl,l) !pl_try_r(l)
|
||||
#define HA_RWLOCK_RDUNLOCK(lbl,l) pl_drop_r(l)
|
||||
|
||||
#endif /* DEBUG_THREAD */
|
||||
|
||||
|
||||
void ha_spin_init(HA_SPINLOCK_T *l);
|
||||
void ha_rwlock_init(HA_RWLOCK_T *l);
|
||||
|
||||
#endif /* USE_THREAD */
|
||||
|
||||
extern int thread_cpus_enabled_at_boot;
|
||||
|
||||
int parse_nbthread(const char *arg, char **err);
|
||||
int thread_get_default_count();
|
||||
|
||||
#endif /* _COMMON_HATHREADS_H */
|
||||
#endif /* _HAPROXY_THREAD_H */
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/memory.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
|
||||
#include <types/log.h>
|
||||
#include <types/proxy.h>
|
||||
|
@ -23,7 +23,7 @@
|
||||
#define _PROTO_PROTOCOL_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <types/protocol.h>
|
||||
|
||||
extern struct protocol *__protocol_by_family[AF_CUST_MAX];
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <signal.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/signal.h>
|
||||
#include <types/task.h>
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <haproxy/list.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/ticks.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <import/eb32sctree.h>
|
||||
#include <import/eb32tree.h>
|
||||
|
@ -23,7 +23,7 @@
|
||||
#define _TYPES_BACKEND_H
|
||||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/lb_chash.h>
|
||||
#include <types/lb_fas.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _TYPES_DICT_H
|
||||
#define _TYPES_DICT_H
|
||||
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <import/ebpttree.h>
|
||||
|
||||
struct dict_entry {
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <import/eb32tree.h>
|
||||
|
||||
#include <haproxy/list-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/connection.h>
|
||||
#include <types/obj_type.h>
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/freq_ctr.h>
|
||||
#include <types/listener.h>
|
||||
|
@ -31,7 +31,7 @@
|
||||
#endif
|
||||
|
||||
#include <haproxy/list-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/obj_type.h>
|
||||
#include <import/eb32tree.h>
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <haproxy/api-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <haproxy/list-t.h>
|
||||
#include <types/ring.h>
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <common/http.h>
|
||||
#include <haproxy/list-t.h>
|
||||
#include <common/regex.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <import/eb32tree.h>
|
||||
#include <import/ebistree.h>
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/list-t.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <haproxy/openssl-compat.h>
|
||||
|
||||
#include <import/eb32tree.h>
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <common/buffer.h>
|
||||
#include <haproxy/list-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/filters.h>
|
||||
#include <types/freq_ctr.h>
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <types/ssl_crtlist.h>
|
||||
|
||||
#include <common/buffer.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <haproxy/list-t.h>
|
||||
#include <haproxy/openssl-compat.h>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define _TYPES_VARS_H
|
||||
|
||||
#include <haproxy/list-t.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/sample.h>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <common/chunk.h>
|
||||
#include <common/buffer.h>
|
||||
#include <haproxy/errors.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <types/global.h>
|
||||
#include <proto/arg.h>
|
||||
#include <proto/http_fetch.h>
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <haproxy/api.h>
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
#include <types/activity.h>
|
||||
#include <proto/channel.h>
|
||||
#include <proto/cli.h>
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <haproxy/api.h>
|
||||
#include <types/global.h>
|
||||
#include <haproxy/errors.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <proto/acl.h>
|
||||
#include <proto/log.h>
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include <common/time.h>
|
||||
#include <common/uri_auth.h>
|
||||
#include <common/namespace.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/capture.h>
|
||||
#include <types/filters.h>
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include <haproxy/list.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/time.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/http.h>
|
||||
#include <common/h1.h>
|
||||
#include <common/htx.h>
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/memory.h>
|
||||
|
||||
#include <types/global.h>
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/buf.h>
|
||||
#include <haproxy/debug.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <import/ist.h>
|
||||
#include <common/net_helper.h>
|
||||
#include <common/standard.h>
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/ticks.h>
|
||||
#include <common/time.h>
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <syslog.h>
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
#include <common/ticks.h>
|
||||
#include <common/time.h>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
#include <common/ticks.h>
|
||||
#include <common/time.h>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
#include <common/ticks.h>
|
||||
#include <common/time.h>
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
#include <common/ticks.h>
|
||||
#include <common/time.h>
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/memory.h>
|
||||
#include <common/time.h>
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
||||
#include <common/time.h>
|
||||
#include <common/uri_auth.h>
|
||||
#include <haproxy/version.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/capture.h>
|
||||
#include <types/cli.h>
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <import/ebpttree.h>
|
||||
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/xref.h>
|
||||
#include <common/h1.h>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <types/stats.h>
|
||||
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/memory.h>
|
||||
#include <haproxy/list.h>
|
||||
#include <common/standard.h>
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <common/net_helper.h>
|
||||
#include <common/time.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
|
||||
#include <types/global.h>
|
||||
#include <types/listener.h>
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <haproxy/api.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/memory.h>
|
||||
|
||||
#include <types/global.h>
|
||||
|
@ -72,7 +72,7 @@
|
||||
#include <haproxy/api.h>
|
||||
#include <common/memory.h>
|
||||
#include <common/time.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <import/eb32tree.h>
|
||||
|
||||
#include <proto/http_rules.h>
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/buf.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <types/applet.h>
|
||||
#include <proto/cli.h>
|
||||
#include <proto/ring.h>
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <haproxy/api.h>
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/buffer.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/htx.h>
|
||||
#include <common/memory.h>
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#endif
|
||||
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread.h>
|
||||
#include <common/standard.h>
|
||||
#include <types/global.h>
|
||||
#include <proto/fd.h>
|
||||
@ -190,7 +190,7 @@ static int thread_cpus_enabled()
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
static void __hathreads_init(void)
|
||||
static void __thread_init(void)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <haproxy/api.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/time.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <haproxy/thread-t.h>
|
||||
|
||||
THREAD_LOCAL unsigned int ms_left_scaled; /* milliseconds left for current second (0..2^32-1) */
|
||||
THREAD_LOCAL unsigned int now_ms; /* internal date in milliseconds (may wrap) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user