mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-14 01:30:54 +00:00
MEDIUM: config: use platform independent type hap_cpuset for cpu-map
Use the platform independent type hap_cpuset for the cpu-map statement parsing. This allow to address CPU index greater than LONGBITS. Update the documentation to reflect the removal of this limit except for platforms without cpu_set_t type or equivalent.
This commit is contained in:
parent
c90932bc8e
commit
982fb53390
@ -1063,14 +1063,16 @@ cpu-map [auto:]<process-set>[/<thread-set>] <cpu-set>...
|
||||
a dash ('-'). It also is possible to specify all processes at once using
|
||||
"all", only odd numbers using "odd" or even numbers using "even", just like
|
||||
with the "bind-process" directive. The second and forthcoming arguments are
|
||||
CPU sets. Each CPU set is either a unique number between 0 and 31 or 63 or a
|
||||
range with two such numbers delimited by a dash ('-'). Multiple CPU numbers
|
||||
or ranges may be specified, and the processes or threads will be allowed to
|
||||
bind to all of them. Obviously, multiple "cpu-map" directives may be
|
||||
specified. Each "cpu-map" directive will replace the previous ones when they
|
||||
overlap. A thread will be bound on the intersection of its mapping and the
|
||||
one of the process on which it is attached. If the intersection is null, no
|
||||
specific binding will be set for the thread.
|
||||
CPU sets. Each CPU set is either a unique number starting at 0 for the first
|
||||
CPU or a range with two such numbers delimited by a dash ('-'). Outside of
|
||||
Linux and BSDs, there may be a limitation on the maximum CPU index to either
|
||||
31 or 63. Multiple CPU numbers or ranges may be specified, and the processes
|
||||
or threads will be allowed to bind to all of them. Obviously, multiple
|
||||
"cpu-map" directives may be specified. Each "cpu-map" directive will replace
|
||||
the previous ones when they overlap. A thread will be bound on the
|
||||
intersection of its mapping and the one of the process on which it is
|
||||
attached. If the intersection is null, no specific binding will be set for
|
||||
the thread.
|
||||
|
||||
Ranges can be partially defined. The higher bound can be omitted. In such
|
||||
case, it is replaced by the corresponding maximum value, 32 or 64 depending
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <haproxy/api-t.h>
|
||||
#include <haproxy/buf-t.h>
|
||||
#include <haproxy/cpuset-t.h>
|
||||
#include <haproxy/freq_ctr-t.h>
|
||||
#include <haproxy/vars-t.h>
|
||||
|
||||
@ -160,9 +161,9 @@ struct global {
|
||||
struct proxy *cli_fe; /* the frontend holding the stats settings */
|
||||
#ifdef USE_CPU_AFFINITY
|
||||
struct {
|
||||
unsigned long proc[MAX_PROCS]; /* list of CPU masks for the 32/64 first processes */
|
||||
unsigned long proc_t1[MAX_PROCS]; /* list of CPU masks for the 1st thread of each process */
|
||||
unsigned long thread[MAX_THREADS]; /* list of CPU masks for the 32/64 first threads of the 1st process */
|
||||
struct hap_cpuset proc[MAX_PROCS]; /* list of CPU masks for the 32/64 first processes */
|
||||
struct hap_cpuset proc_t1[MAX_PROCS]; /* list of CPU masks for the 1st thread of each process */
|
||||
struct hap_cpuset thread[MAX_THREADS]; /* list of CPU masks for the 32/64 first threads of the 1st process */
|
||||
} cpu_map;
|
||||
#endif
|
||||
/* The info above is config stuff, it doesn't change during the process' life */
|
||||
|
@ -1,4 +1,3 @@
|
||||
#define _GNU_SOURCE /* for CPU_* from cpuset.h */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -1028,9 +1027,9 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
/* map a process list to a CPU set */
|
||||
#ifdef USE_CPU_AFFINITY
|
||||
char *slash;
|
||||
unsigned long proc = 0, thread = 0, cpus;
|
||||
int i, j, n, k, autoinc;
|
||||
struct hap_cpuset cpuset;
|
||||
unsigned long proc = 0, thread = 0;
|
||||
int i, j, n, autoinc;
|
||||
struct hap_cpuset cpus, cpus_copy;
|
||||
|
||||
if (!*args[1] || !*args[2]) {
|
||||
ha_alert("parsing [%s:%d] : %s expects a process number "
|
||||
@ -1071,26 +1070,15 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_cpu_set((const char **)args+2, &cpuset, &errmsg)) {
|
||||
if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
|
||||
ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
#if defined(CPUSET_USE_CPUSET)
|
||||
k = 0;
|
||||
while (CPU_COUNT(&cpuset.cpuset)) {
|
||||
while (!CPU_ISSET(k, &cpuset.cpuset))
|
||||
++k;
|
||||
cpus |= 1 << k;
|
||||
CPU_CLR(k, &cpuset.cpuset);
|
||||
++k;
|
||||
}
|
||||
#elif defined(CPUSET_USE_ULONG)
|
||||
cpus = cpuset.cpuset;
|
||||
#endif
|
||||
|
||||
if (autoinc &&
|
||||
my_popcountl(proc) != my_popcountl(cpus) &&
|
||||
my_popcountl(thread) != my_popcountl(cpus)) {
|
||||
my_popcountl(proc) != ha_cpuset_count(&cpus) &&
|
||||
my_popcountl(thread) != ha_cpuset_count(&cpus)) {
|
||||
ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
|
||||
"must have the same size to be automatically bound\n",
|
||||
file, linenum, args[0]);
|
||||
@ -1111,16 +1099,19 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
*/
|
||||
if (!thread) {
|
||||
/* mapping for whole processes. E.g. cpu-map 1-4 0-3 */
|
||||
ha_cpuset_assign(&cpus_copy, &cpus);
|
||||
for (i = n = 0; i < MAX_PROCS; i++) {
|
||||
/* No mapping for this process */
|
||||
if (!(proc & (1UL << i)))
|
||||
continue;
|
||||
|
||||
if (!autoinc)
|
||||
global.cpu_map.proc[i] = cpus;
|
||||
ha_cpuset_assign(&global.cpu_map.proc[i], &cpus);
|
||||
else {
|
||||
n += my_ffsl(cpus >> n);
|
||||
global.cpu_map.proc[i] = (1UL << (n-1));
|
||||
ha_cpuset_zero(&global.cpu_map.proc[i]);
|
||||
n = ha_cpuset_ffs(&cpus_copy) - 1;
|
||||
ha_cpuset_clr(&cpus_copy, n);
|
||||
ha_cpuset_set(&global.cpu_map.proc[i], n);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1129,44 +1120,48 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
* other combinations are silently ignored.
|
||||
*/
|
||||
if (thread == 0x1) {
|
||||
int val;
|
||||
|
||||
/* first thread, iterate on processes. E.g. cpu-map 1-4/1 0-3 */
|
||||
struct hap_cpuset *dst;
|
||||
|
||||
ha_cpuset_assign(&cpus_copy, &cpus);
|
||||
for (i = n = 0; i < MAX_PROCS; i++) {
|
||||
/* No mapping for this process */
|
||||
if (!(proc & (1UL << i)))
|
||||
continue;
|
||||
|
||||
if (!autoinc) {
|
||||
val = cpus;
|
||||
}
|
||||
else {
|
||||
n += my_ffsl(cpus >> n);
|
||||
val = 1UL << (n - 1);
|
||||
}
|
||||
|
||||
/* For first process, thread[0] is used.
|
||||
* Use proc_t1[N] for all others
|
||||
*/
|
||||
if (!i)
|
||||
global.cpu_map.thread[0] = val;
|
||||
else
|
||||
global.cpu_map.proc_t1[i] = val;
|
||||
dst = i ? &global.cpu_map.proc_t1[i] :
|
||||
&global.cpu_map.thread[0];
|
||||
|
||||
if (!autoinc) {
|
||||
ha_cpuset_assign(dst, &cpus);
|
||||
}
|
||||
else {
|
||||
ha_cpuset_zero(dst);
|
||||
n = ha_cpuset_ffs(&cpus_copy) - 1;
|
||||
ha_cpuset_clr(&cpus_copy, n);
|
||||
ha_cpuset_set(dst, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (proc == 0x1) {
|
||||
/* first process, iterate on threads. E.g. cpu-map 1/1-4 0-3 */
|
||||
ha_cpuset_assign(&cpus_copy, &cpus);
|
||||
for (j = n = 0; j < MAX_THREADS; j++) {
|
||||
/* No mapping for this thread */
|
||||
if (!(thread & (1UL << j)))
|
||||
continue;
|
||||
|
||||
if (!autoinc)
|
||||
global.cpu_map.thread[j] = cpus;
|
||||
ha_cpuset_assign(&global.cpu_map.thread[j], &cpus);
|
||||
else {
|
||||
n += my_ffsl(cpus >> n);
|
||||
global.cpu_map.thread[j] = (1UL << (n-1));
|
||||
ha_cpuset_zero(&global.cpu_map.thread[j]);
|
||||
n = ha_cpuset_ffs(&cpus_copy) - 1;
|
||||
ha_cpuset_clr(&cpus_copy, n);
|
||||
ha_cpuset_set(&global.cpu_map.thread[j], n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +92,7 @@
|
||||
#include <haproxy/chunk.h>
|
||||
#include <haproxy/cli.h>
|
||||
#include <haproxy/connection.h>
|
||||
#include <haproxy/cpuset.h>
|
||||
#include <haproxy/dns.h>
|
||||
#include <haproxy/dynbuf.h>
|
||||
#include <haproxy/errors.h>
|
||||
@ -1268,6 +1269,7 @@ static void init(int argc, char **argv)
|
||||
struct proxy *px;
|
||||
struct post_check_fct *pcf;
|
||||
int ideal_maxconn;
|
||||
int i;
|
||||
|
||||
global.mode = MODE_STARTING;
|
||||
old_argv = copy_argv(argc, argv);
|
||||
@ -1576,6 +1578,12 @@ static void init(int argc, char **argv)
|
||||
|
||||
global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
|
||||
|
||||
for (i = 0; i < MAX_PROCS; ++i) {
|
||||
ha_cpuset_zero(&global.cpu_map.proc[i]);
|
||||
ha_cpuset_zero(&global.cpu_map.proc_t1[i]);
|
||||
ha_cpuset_zero(&global.cpu_map.thread[i]);
|
||||
}
|
||||
|
||||
/* in wait mode, we don't try to read the configuration files */
|
||||
if (!(global.mode & MODE_MWORKER_WAIT)) {
|
||||
char *env_cfgfiles = NULL;
|
||||
@ -2925,23 +2933,15 @@ int main(int argc, char **argv)
|
||||
#ifdef USE_CPU_AFFINITY
|
||||
if (proc < global.nbproc && /* child */
|
||||
proc < MAX_PROCS && /* only the first 32/64 processes may be pinned */
|
||||
global.cpu_map.proc[proc]) /* only do this if the process has a CPU map */
|
||||
#ifdef __FreeBSD__
|
||||
{
|
||||
cpuset_t cpuset;
|
||||
int i;
|
||||
unsigned long cpu_map = global.cpu_map.proc[proc];
|
||||
ha_cpuset_count(&global.cpu_map.proc[proc])) { /* only do this if the process has a CPU map */
|
||||
|
||||
CPU_ZERO(&cpuset);
|
||||
while ((i = ffsl(cpu_map)) > 0) {
|
||||
CPU_SET(i - 1, &cpuset);
|
||||
cpu_map &= ~(1UL << (i - 1));
|
||||
}
|
||||
ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset), &cpuset);
|
||||
}
|
||||
struct hap_cpuset *set = &global.cpu_map.proc[proc];
|
||||
#ifdef __FreeBSD__
|
||||
ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
|
||||
#elif defined(__linux__) || defined(__DragonFly__)
|
||||
sched_setaffinity(0, sizeof(unsigned long), (void *)&global.cpu_map.proc[proc]);
|
||||
sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* close the pidfile both in children and father */
|
||||
if (pidfd >= 0) {
|
||||
@ -3179,14 +3179,14 @@ int main(int argc, char **argv)
|
||||
global.cpu_map.thread[0] = global.cpu_map.proc_t1[relative_pid-1];
|
||||
|
||||
for (i = 0; i < global.nbthread; i++) {
|
||||
if (global.cpu_map.proc[relative_pid-1])
|
||||
global.cpu_map.thread[i] &= global.cpu_map.proc[relative_pid-1];
|
||||
if (ha_cpuset_count(&global.cpu_map.proc[relative_pid-1]))
|
||||
ha_cpuset_and(&global.cpu_map.thread[i], &global.cpu_map.proc[relative_pid-1]);
|
||||
|
||||
if (i < MAX_THREADS && /* only the first 32/64 threads may be pinned */
|
||||
global.cpu_map.thread[i]) {/* only do this if the thread has a THREAD map */
|
||||
ha_cpuset_count(&global.cpu_map.thread[i])) {/* only do this if the thread has a THREAD map */
|
||||
#if defined(__APPLE__)
|
||||
int j;
|
||||
unsigned long cpu_map = global.cpu_map.thread[i];
|
||||
unsigned long cpu_map = global.cpu_map.thread[i].cpuset;
|
||||
|
||||
while ((j = ffsl(cpu_map)) > 0) {
|
||||
thread_affinity_policy_data_t cpu_set = { j - 1 };
|
||||
@ -3195,22 +3195,9 @@ int main(int argc, char **argv)
|
||||
cpu_map &= ~(1UL << (j - 1));
|
||||
}
|
||||
#else
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
cpuset_t cpuset;
|
||||
#else
|
||||
cpu_set_t cpuset;
|
||||
#endif
|
||||
int j;
|
||||
unsigned long cpu_map = global.cpu_map.thread[i];
|
||||
|
||||
CPU_ZERO(&cpuset);
|
||||
|
||||
while ((j = ffsl(cpu_map)) > 0) {
|
||||
CPU_SET(j - 1, &cpuset);
|
||||
cpu_map &= ~(1UL << (j - 1));
|
||||
}
|
||||
struct hap_cpuset *set = &global.cpu_map.thread[i];
|
||||
pthread_setaffinity_np(ha_thread_info[i].pthread,
|
||||
sizeof(cpuset), &cpuset);
|
||||
sizeof(set->cpuset), &set->cpuset);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user