MINOR: config: make MAX_PROCS configurable at build time
For some embedded systems, it's pointless to have 32- or even 64- large
arrays of processes when it's known that much fewer processes will be
used in the worst case. Let's introduce this MAX_PROCS define which
contains the highest number of processes allowed to run at once. It
still defaults to LONGBITS but may be lowered.
diff --git a/include/common/defaults.h b/include/common/defaults.h
index b2c2583..cdc6665 100644
--- a/include/common/defaults.h
+++ b/include/common/defaults.h
@@ -22,6 +22,14 @@
#ifndef _COMMON_DEFAULTS_H
#define _COMMON_DEFAULTS_H
+/* MAX_PROCS defines the highest limit for the global "nbproc" value. It
+ * defaults to the number of bits in a long integer but may be lowered to save
+ * resources on embedded systems.
+ */
+#ifndef MAX_PROCS
+#define MAX_PROCS LONGBITS
+#endif
+
/*
* BUFSIZE defines the size of a read and write buffer. It is the maximum
* amount of bytes which can be stored by the proxy for each stream. However,
diff --git a/include/types/global.h b/include/types/global.h
index 178b2c1..b26553b 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -173,8 +173,8 @@
struct vars vars; /* list of variables for the process scope. */
#ifdef USE_CPU_AFFINITY
struct {
- unsigned long proc[LONGBITS]; /* list of CPU masks for the 32/64 first processes */
- unsigned long thread[LONGBITS][MAX_THREADS]; /* list of CPU masks for the 32/64 first threads per process */
+ unsigned long proc[MAX_PROCS]; /* list of CPU masks for the 32/64 first processes */
+ unsigned long thread[MAX_PROCS][MAX_THREADS]; /* list of CPU masks for the 32/64 first threads per process */
} cpu_map;
#endif
};
diff --git a/include/types/listener.h b/include/types/listener.h
index df0dd36..9c0ebde 100644
--- a/include/types/listener.h
+++ b/include/types/listener.h
@@ -166,7 +166,7 @@
int is_ssl; /* SSL is required for these listeners */
int generate_certs; /* 1 if generate-certificates option is set, else 0 */
unsigned long bind_proc; /* bitmask of processes allowed to use these listeners */
- unsigned long bind_thread[LONGBITS]; /* bitmask of threads (per processes) allowed to use these listeners */
+ unsigned long bind_thread[MAX_PROCS]; /* bitmask of threads (per processes) allowed to use these listeners */
struct { /* UNIX socket permissions */
uid_t uid; /* -1 to leave unchanged */
gid_t gid; /* -1 to leave unchanged */
diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c
index 820c7b6..e1835e7 100644
--- a/src/cfgparse-global.c
+++ b/src/cfgparse-global.c
@@ -490,9 +490,9 @@
}
global.nbproc = atol(args[1]);
all_proc_mask = nbits(global.nbproc);
- if (global.nbproc < 1 || global.nbproc > LONGBITS) {
+ if (global.nbproc < 1 || global.nbproc > MAX_PROCS) {
ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
- file, linenum, args[0], LONGBITS, global.nbproc);
+ file, linenum, args[0], MAX_PROCS, global.nbproc);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
@@ -942,7 +942,7 @@
ha_alert("parsing [%s:%d] : %s expects a process number "
" ('all', 'odd', 'even', a number from 1 to %d or a range), "
" followed by a list of CPU ranges with numbers from 0 to %d.\n",
- file, linenum, args[0], LONGBITS, LONGBITS - 1);
+ file, linenum, args[0], MAX_PROCS, LONGBITS - 1);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
@@ -950,7 +950,7 @@
if ((slash = strchr(args[1], '/')) != NULL)
*slash = 0;
- if (parse_process_number(args[1], &proc, LONGBITS, &autoinc, &errmsg)) {
+ if (parse_process_number(args[1], &proc, MAX_PROCS, &autoinc, &errmsg)) {
ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
@@ -989,7 +989,7 @@
goto out;
}
- for (i = n = 0; i < LONGBITS; i++) {
+ for (i = n = 0; i < MAX_PROCS; i++) {
/* No mapping for this process */
if (!(proc & (1UL << i)))
continue;
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index 74218b5..5f44cfd 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -922,7 +922,7 @@
set = 0;
break;
}
- if (parse_process_number(args[cur_arg], &set, LONGBITS, NULL, &errmsg)) {
+ if (parse_process_number(args[cur_arg], &set, MAX_PROCS, NULL, &errmsg)) {
ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 1afb49c..d7d18c6 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2296,7 +2296,7 @@
mask >>= global.nbthread;
}
- for (nbproc = 0; nbproc < LONGBITS; nbproc++) {
+ for (nbproc = 0; nbproc < MAX_PROCS; nbproc++) {
if (!bind_conf->bind_proc || (bind_conf->bind_proc & (1UL << nbproc)))
bind_conf->bind_thread[nbproc] = new_mask;
}
diff --git a/src/cli.c b/src/cli.c
index d1d1e96..3c2a55d 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -359,7 +359,7 @@
set = 0;
break;
}
- if (parse_process_number(args[cur_arg], &set, LONGBITS, NULL, err)) {
+ if (parse_process_number(args[cur_arg], &set, MAX_PROCS, NULL, err)) {
memprintf(err, "'%s %s' : %s", args[0], args[1], *err);
return -1;
}
diff --git a/src/haproxy.c b/src/haproxy.c
index ce4cde3..7c434b3 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2739,6 +2739,16 @@
setvbuf(stdout, NULL, _IONBF, 0);
+ /* this can only safely be done here, though it's optimized away by
+ * the compiler.
+ */
+ if (MAX_PROCS < 1 || MAX_PROCS > LONGBITS) {
+ ha_alert("MAX_PROCS value must be between 1 and %d inclusive; "
+ "HAProxy was built with value %d, please fix it and rebuild.\n",
+ LONGBITS, MAX_PROCS);
+ exit(1);
+ }
+
/* process all initcalls in order of potential dependency */
RUN_INITCALLS(STG_PREPARE);
RUN_INITCALLS(STG_LOCK);
@@ -3059,7 +3069,7 @@
#ifdef USE_CPU_AFFINITY
if (proc < global.nbproc && /* child */
- proc < LONGBITS && /* 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 */
#ifdef __FreeBSD__
{
diff --git a/src/listener.c b/src/listener.c
index cb8cbda..e9ace41 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -962,7 +962,7 @@
if ((slash = strchr(args[cur_arg + 1], '/')) != NULL)
*slash = 0;
- if (parse_process_number(args[cur_arg + 1], &proc, LONGBITS, NULL, err)) {
+ if (parse_process_number(args[cur_arg + 1], &proc, MAX_PROCS, NULL, err)) {
memprintf(err, "'%s' : %s", args[cur_arg], *err);
return ERR_ALERT | ERR_FATAL;
}
@@ -977,7 +977,7 @@
conf->bind_proc |= proc;
if (thread) {
- for (i = 0; i < LONGBITS; i++)
+ for (i = 0; i < MAX_PROCS; i++)
if (!proc || (proc & (1UL << i)))
conf->bind_thread[i] |= thread;
}