mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-08 08:07:10 +02: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
|
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
|
"all", only odd numbers using "odd" or even numbers using "even", just like
|
||||||
with the "bind-process" directive. The second and forthcoming arguments are
|
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
|
CPU sets. Each CPU set is either a unique number starting at 0 for the first
|
||||||
range with two such numbers delimited by a dash ('-'). Multiple CPU numbers
|
CPU or a range with two such numbers delimited by a dash ('-'). Outside of
|
||||||
or ranges may be specified, and the processes or threads will be allowed to
|
Linux and BSDs, there may be a limitation on the maximum CPU index to either
|
||||||
bind to all of them. Obviously, multiple "cpu-map" directives may be
|
31 or 63. Multiple CPU numbers or ranges may be specified, and the processes
|
||||||
specified. Each "cpu-map" directive will replace the previous ones when they
|
or threads will be allowed to bind to all of them. Obviously, multiple
|
||||||
overlap. A thread will be bound on the intersection of its mapping and the
|
"cpu-map" directives may be specified. Each "cpu-map" directive will replace
|
||||||
one of the process on which it is attached. If the intersection is null, no
|
the previous ones when they overlap. A thread will be bound on the
|
||||||
specific binding will be set for the thread.
|
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
|
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
|
case, it is replaced by the corresponding maximum value, 32 or 64 depending
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <haproxy/api-t.h>
|
#include <haproxy/api-t.h>
|
||||||
#include <haproxy/buf-t.h>
|
#include <haproxy/buf-t.h>
|
||||||
|
#include <haproxy/cpuset-t.h>
|
||||||
#include <haproxy/freq_ctr-t.h>
|
#include <haproxy/freq_ctr-t.h>
|
||||||
#include <haproxy/vars-t.h>
|
#include <haproxy/vars-t.h>
|
||||||
|
|
||||||
@ -160,9 +161,9 @@ struct global {
|
|||||||
struct proxy *cli_fe; /* the frontend holding the stats settings */
|
struct proxy *cli_fe; /* the frontend holding the stats settings */
|
||||||
#ifdef USE_CPU_AFFINITY
|
#ifdef USE_CPU_AFFINITY
|
||||||
struct {
|
struct {
|
||||||
unsigned long proc[MAX_PROCS]; /* list of CPU masks for the 32/64 first processes */
|
struct hap_cpuset 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 */
|
struct hap_cpuset 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 thread[MAX_THREADS]; /* list of CPU masks for the 32/64 first threads of the 1st process */
|
||||||
} cpu_map;
|
} cpu_map;
|
||||||
#endif
|
#endif
|
||||||
/* The info above is config stuff, it doesn't change during the process' life */
|
/* 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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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 */
|
/* map a process list to a CPU set */
|
||||||
#ifdef USE_CPU_AFFINITY
|
#ifdef USE_CPU_AFFINITY
|
||||||
char *slash;
|
char *slash;
|
||||||
unsigned long proc = 0, thread = 0, cpus;
|
unsigned long proc = 0, thread = 0;
|
||||||
int i, j, n, k, autoinc;
|
int i, j, n, autoinc;
|
||||||
struct hap_cpuset cpuset;
|
struct hap_cpuset cpus, cpus_copy;
|
||||||
|
|
||||||
if (!*args[1] || !*args[2]) {
|
if (!*args[1] || !*args[2]) {
|
||||||
ha_alert("parsing [%s:%d] : %s expects a process number "
|
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);
|
ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
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 &&
|
if (autoinc &&
|
||||||
my_popcountl(proc) != my_popcountl(cpus) &&
|
my_popcountl(proc) != ha_cpuset_count(&cpus) &&
|
||||||
my_popcountl(thread) != my_popcountl(cpus)) {
|
my_popcountl(thread) != ha_cpuset_count(&cpus)) {
|
||||||
ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
|
ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
|
||||||
"must have the same size to be automatically bound\n",
|
"must have the same size to be automatically bound\n",
|
||||||
file, linenum, args[0]);
|
file, linenum, args[0]);
|
||||||
@ -1111,16 +1099,19 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
|||||||
*/
|
*/
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
/* mapping for whole processes. E.g. cpu-map 1-4 0-3 */
|
/* 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++) {
|
for (i = n = 0; i < MAX_PROCS; i++) {
|
||||||
/* No mapping for this process */
|
/* No mapping for this process */
|
||||||
if (!(proc & (1UL << i)))
|
if (!(proc & (1UL << i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!autoinc)
|
if (!autoinc)
|
||||||
global.cpu_map.proc[i] = cpus;
|
ha_cpuset_assign(&global.cpu_map.proc[i], &cpus);
|
||||||
else {
|
else {
|
||||||
n += my_ffsl(cpus >> n);
|
ha_cpuset_zero(&global.cpu_map.proc[i]);
|
||||||
global.cpu_map.proc[i] = (1UL << (n-1));
|
n = ha_cpuset_ffs(&cpus_copy) - 1;
|
||||||
|
ha_cpuset_clr(&cpus_copy, n);
|
||||||
|
ha_cpuset_set(&global.cpu_map.proc[i], n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1129,44 +1120,48 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
|||||||
* other combinations are silently ignored.
|
* other combinations are silently ignored.
|
||||||
*/
|
*/
|
||||||
if (thread == 0x1) {
|
if (thread == 0x1) {
|
||||||
int val;
|
|
||||||
|
|
||||||
/* first thread, iterate on processes. E.g. cpu-map 1-4/1 0-3 */
|
/* 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++) {
|
for (i = n = 0; i < MAX_PROCS; i++) {
|
||||||
/* No mapping for this process */
|
/* No mapping for this process */
|
||||||
if (!(proc & (1UL << i)))
|
if (!(proc & (1UL << i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!autoinc) {
|
|
||||||
val = cpus;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
n += my_ffsl(cpus >> n);
|
|
||||||
val = 1UL << (n - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For first process, thread[0] is used.
|
/* For first process, thread[0] is used.
|
||||||
* Use proc_t1[N] for all others
|
* Use proc_t1[N] for all others
|
||||||
*/
|
*/
|
||||||
if (!i)
|
dst = i ? &global.cpu_map.proc_t1[i] :
|
||||||
global.cpu_map.thread[0] = val;
|
&global.cpu_map.thread[0];
|
||||||
else
|
|
||||||
global.cpu_map.proc_t1[i] = val;
|
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) {
|
if (proc == 0x1) {
|
||||||
/* first process, iterate on threads. E.g. cpu-map 1/1-4 0-3 */
|
/* 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++) {
|
for (j = n = 0; j < MAX_THREADS; j++) {
|
||||||
/* No mapping for this thread */
|
/* No mapping for this thread */
|
||||||
if (!(thread & (1UL << j)))
|
if (!(thread & (1UL << j)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!autoinc)
|
if (!autoinc)
|
||||||
global.cpu_map.thread[j] = cpus;
|
ha_cpuset_assign(&global.cpu_map.thread[j], &cpus);
|
||||||
else {
|
else {
|
||||||
n += my_ffsl(cpus >> n);
|
ha_cpuset_zero(&global.cpu_map.thread[j]);
|
||||||
global.cpu_map.thread[j] = (1UL << (n-1));
|
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/chunk.h>
|
||||||
#include <haproxy/cli.h>
|
#include <haproxy/cli.h>
|
||||||
#include <haproxy/connection.h>
|
#include <haproxy/connection.h>
|
||||||
|
#include <haproxy/cpuset.h>
|
||||||
#include <haproxy/dns.h>
|
#include <haproxy/dns.h>
|
||||||
#include <haproxy/dynbuf.h>
|
#include <haproxy/dynbuf.h>
|
||||||
#include <haproxy/errors.h>
|
#include <haproxy/errors.h>
|
||||||
@ -1268,6 +1269,7 @@ static void init(int argc, char **argv)
|
|||||||
struct proxy *px;
|
struct proxy *px;
|
||||||
struct post_check_fct *pcf;
|
struct post_check_fct *pcf;
|
||||||
int ideal_maxconn;
|
int ideal_maxconn;
|
||||||
|
int i;
|
||||||
|
|
||||||
global.mode = MODE_STARTING;
|
global.mode = MODE_STARTING;
|
||||||
old_argv = copy_argv(argc, argv);
|
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 */
|
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 */
|
/* in wait mode, we don't try to read the configuration files */
|
||||||
if (!(global.mode & MODE_MWORKER_WAIT)) {
|
if (!(global.mode & MODE_MWORKER_WAIT)) {
|
||||||
char *env_cfgfiles = NULL;
|
char *env_cfgfiles = NULL;
|
||||||
@ -2925,23 +2933,15 @@ int main(int argc, char **argv)
|
|||||||
#ifdef USE_CPU_AFFINITY
|
#ifdef USE_CPU_AFFINITY
|
||||||
if (proc < global.nbproc && /* child */
|
if (proc < global.nbproc && /* child */
|
||||||
proc < MAX_PROCS && /* only the first 32/64 processes may be pinned */
|
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 */
|
ha_cpuset_count(&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];
|
|
||||||
|
|
||||||
CPU_ZERO(&cpuset);
|
struct hap_cpuset *set = &global.cpu_map.proc[proc];
|
||||||
while ((i = ffsl(cpu_map)) > 0) {
|
#ifdef __FreeBSD__
|
||||||
CPU_SET(i - 1, &cpuset);
|
ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
|
||||||
cpu_map &= ~(1UL << (i - 1));
|
|
||||||
}
|
|
||||||
ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset), &cpuset);
|
|
||||||
}
|
|
||||||
#elif defined(__linux__) || defined(__DragonFly__)
|
#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
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
/* close the pidfile both in children and father */
|
/* close the pidfile both in children and father */
|
||||||
if (pidfd >= 0) {
|
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];
|
global.cpu_map.thread[0] = global.cpu_map.proc_t1[relative_pid-1];
|
||||||
|
|
||||||
for (i = 0; i < global.nbthread; i++) {
|
for (i = 0; i < global.nbthread; i++) {
|
||||||
if (global.cpu_map.proc[relative_pid-1])
|
if (ha_cpuset_count(&global.cpu_map.proc[relative_pid-1]))
|
||||||
global.cpu_map.thread[i] &= 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 */
|
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__)
|
#if defined(__APPLE__)
|
||||||
int j;
|
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) {
|
while ((j = ffsl(cpu_map)) > 0) {
|
||||||
thread_affinity_policy_data_t cpu_set = { j - 1 };
|
thread_affinity_policy_data_t cpu_set = { j - 1 };
|
||||||
@ -3195,22 +3195,9 @@ int main(int argc, char **argv)
|
|||||||
cpu_map &= ~(1UL << (j - 1));
|
cpu_map &= ~(1UL << (j - 1));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
struct hap_cpuset *set = &global.cpu_map.thread[i];
|
||||||
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));
|
|
||||||
}
|
|
||||||
pthread_setaffinity_np(ha_thread_info[i].pthread,
|
pthread_setaffinity_np(ha_thread_info[i].pthread,
|
||||||
sizeof(cpuset), &cpuset);
|
sizeof(set->cpuset), &set->cpuset);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user