REORG: thread: move the thread init/affinity/stop to thread.c

haproxy.c still has to deal with pthread-specific low-level stuff that
is OS-dependent. We should not have to deal with this there, and we do
not need to access pthread anywhere else.

Let's move these 3 functions to thread.c and keep empty inline ones for
when threads are disabled.
This commit is contained in:
Willy Tarreau 2021-10-06 22:22:40 +02:00
parent 19b18ad552
commit d10385ac4b
3 changed files with 105 additions and 90 deletions

View File

@ -151,6 +151,18 @@ static inline unsigned long thread_isolated()
return 1;
}
static inline void setup_extra_threads(void *(*handler)(void *))
{
}
static inline void wait_for_threads_completion()
{
}
static inline void set_thread_cpu_affinity()
{
}
#else /* !USE_THREAD */
/********************** THREADS ENABLED ************************/
@ -166,6 +178,9 @@ 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);
void setup_extra_threads(void *(*handler)(void *));
void wait_for_threads_completion();
void set_thread_cpu_affinity();
extern volatile unsigned long all_threads_mask;
extern volatile unsigned long threads_harmless_mask;

View File

@ -50,6 +50,7 @@
#include <time.h>
#include <syslog.h>
#include <grp.h>
#ifdef USE_CPU_AFFINITY
#include <sched.h>
#if defined(__FreeBSD__) || defined(__DragonFly__)
@ -57,12 +58,6 @@
#ifdef __FreeBSD__
#include <sys/cpuset.h>
#endif
#include <pthread_np.h>
#endif
#ifdef __APPLE__
#include <mach/mach_types.h>
#include <mach/thread_act.h>
#include <mach/thread_policy.h>
#endif
#endif
@ -2611,41 +2606,6 @@ __attribute__((noreturn)) void deinit_and_exit(int status)
exit(status);
}
/* Tries to set the current thread's CPU affinity according to the cpu_map */
static void set_thread_cpu_affinity()
{
#if defined(USE_THREAD) && defined(USE_CPU_AFFINITY)
/* no affinity setting for the master process */
if (master)
return;
/* Now the CPU affinity for all threads */
if (ha_cpuset_count(&cpu_map.proc))
ha_cpuset_and(&cpu_map.thread[tid], &cpu_map.proc);
if (ha_cpuset_count(&cpu_map.thread[tid])) {/* only do this if the thread has a THREAD map */
# if defined(__APPLE__)
/* Note: this API is limited to the first 32/64 CPUs */
unsigned long set = cpu_map.thread[tid].cpuset;
int j;
while ((j = ffsl(set)) > 0) {
thread_affinity_policy_data_t cpu_set = { j - 1 };
thread_port_t mthread;
mthread = pthread_mach_thread_np(ha_thread_info[tid].pthread);
thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
set &= ~(1UL << (j - 1));
}
# else
struct hap_cpuset *set = &cpu_map.thread[tid];
pthread_setaffinity_np(ha_thread_info[tid].pthread, sizeof(set->cpuset), &set->cpuset);
# endif
}
#endif /* USE_THREAD && USE_CPU_AFFINITY */
}
/* Runs the polling loop */
void run_poll_loop()
{
@ -2857,49 +2817,6 @@ static void *run_thread_poll_loop(void *data)
return NULL;
}
/* Sets up threads, signals and masks, and starts threads 2 and above.
* Does nothing when threads are disabled.
*/
static void setup_extra_threads()
{
#ifdef USE_THREAD
sigset_t blocked_sig, old_sig;
int i;
/* ensure the signals will be blocked in every thread */
sigfillset(&blocked_sig);
sigdelset(&blocked_sig, SIGPROF);
sigdelset(&blocked_sig, SIGBUS);
sigdelset(&blocked_sig, SIGFPE);
sigdelset(&blocked_sig, SIGILL);
sigdelset(&blocked_sig, SIGSEGV);
pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
/* Create nbthread-1 thread. The first thread is the current process */
ha_thread_info[0].pthread = pthread_self();
for (i = 1; i < global.nbthread; i++)
pthread_create(&ha_thread_info[i].pthread, NULL, &run_thread_poll_loop, (void *)(long)i);
#endif
}
/* waits for all threads to terminate. Does nothing when threads are
* disabled.
*/
static void wait_for_threads_completion()
{
#ifdef USE_THREAD
int i;
/* Wait the end of other threads */
for (i = 1; i < global.nbthread; i++)
pthread_join(ha_thread_info[i].pthread, NULL);
# if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
show_lock_stats();
# endif
#endif
}
/* set uid/gid depending on global settings */
static void set_identity(const char *program_name)
{
@ -3474,7 +3391,7 @@ int main(int argc, char **argv)
reset_usermsgs_ctx();
/* start threads 2 and above */
setup_extra_threads();
setup_extra_threads(&run_thread_poll_loop);
/* when multithreading we need to let only the thread 0 handle the signals */
haproxy_unblock_signals();

View File

@ -16,11 +16,20 @@
#include <fcntl.h>
#ifdef USE_CPU_AFFINITY
#include <sched.h>
#endif
#ifdef __FreeBSD__
#include <sys/cpuset.h>
# include <sched.h>
# if defined(__FreeBSD__) || defined(__DragonFly__)
# include <sys/param.h>
# ifdef __FreeBSD__
# include <sys/cpuset.h>
# endif
# include <pthread_np.h>
# endif
# ifdef __APPLE__
# include <mach/mach_types.h>
# include <mach/thread_act.h>
# include <mach/thread_policy.h>
# endif
# include <haproxy/cpuset.h>
#endif
#include <haproxy/cfgparse.h>
@ -171,6 +180,80 @@ void thread_sync_release()
ha_thread_relax();
}
/* Sets up threads, signals and masks, and starts threads 2 and above.
* Does nothing when threads are disabled.
*/
void setup_extra_threads(void *(*handler)(void *))
{
sigset_t blocked_sig, old_sig;
int i;
/* ensure the signals will be blocked in every thread */
sigfillset(&blocked_sig);
sigdelset(&blocked_sig, SIGPROF);
sigdelset(&blocked_sig, SIGBUS);
sigdelset(&blocked_sig, SIGFPE);
sigdelset(&blocked_sig, SIGILL);
sigdelset(&blocked_sig, SIGSEGV);
pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
/* Create nbthread-1 thread. The first thread is the current process */
ha_thread_info[0].pthread = pthread_self();
for (i = 1; i < global.nbthread; i++)
pthread_create(&ha_thread_info[i].pthread, NULL, handler, (void *)(long)i);
}
/* waits for all threads to terminate. Does nothing when threads are
* disabled.
*/
void wait_for_threads_completion()
{
int i;
/* Wait the end of other threads */
for (i = 1; i < global.nbthread; i++)
pthread_join(ha_thread_info[i].pthread, NULL);
#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
show_lock_stats();
#endif
}
/* Tries to set the current thread's CPU affinity according to the cpu_map */
void set_thread_cpu_affinity()
{
#if defined(USE_CPU_AFFINITY)
/* no affinity setting for the master process */
if (master)
return;
/* Now the CPU affinity for all threads */
if (ha_cpuset_count(&cpu_map.proc))
ha_cpuset_and(&cpu_map.thread[tid], &cpu_map.proc);
if (ha_cpuset_count(&cpu_map.thread[tid])) {/* only do this if the thread has a THREAD map */
# if defined(__APPLE__)
/* Note: this API is limited to the first 32/64 CPUs */
unsigned long set = cpu_map.thread[tid].cpuset;
int j;
while ((j = ffsl(set)) > 0) {
thread_affinity_policy_data_t cpu_set = { j - 1 };
thread_port_t mthread;
mthread = pthread_mach_thread_np(ha_thread_info[tid].pthread);
thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
set &= ~(1UL << (j - 1));
}
# else
struct hap_cpuset *set = &cpu_map.thread[tid];
pthread_setaffinity_np(ha_thread_info[tid].pthread, sizeof(set->cpuset), &set->cpuset);
# endif
}
#endif /* USE_CPU_AFFINITY */
}
/* send signal <sig> to thread <thr> */
void ha_tkill(unsigned int thr, int sig)
{