REORG: cpu-topo: move bound cpu detection from cpuset to cpu-topo

The cpuset files are normally used only for cpu manipulations. It happens
that the initial CPU binding detection was initially placed there since
there was no better place, but in practice, being OS-specific, it should
really be in cpu-topo. This simplifies cpuset which doesn't need to know
about the OS anymore.
This commit is contained in:
Willy Tarreau 2025-01-22 17:17:59 +01:00
parent a6fdc3eaf0
commit 8c524c7c9d
6 changed files with 62 additions and 75 deletions

View File

@ -2,7 +2,7 @@
#define _HAPROXY_CPU_TOPO_H
#include <haproxy/api.h>
#include <haproxy/cpuset.h>
#include <haproxy/cpuset-t.h>
#include <haproxy/cpu_topo-t.h>
extern int cpu_topo_maxcpus;
@ -16,6 +16,16 @@ extern struct ha_cpu_topo *ha_cpu_topo;
*/
int cpu_detect_usable(void);
/* Detects CPUs that are bound to the current process. Returns the number of
* CPUs detected or 0 if the detection failed.
*/
int ha_cpuset_detect_bound(struct hap_cpuset *set);
/* Returns true if at least one cpu-map directive was configured, otherwise
* false.
*/
int cpu_map_configured(void);
/* Dump the CPU topology <topo> for up to cpu_topo_maxcpus CPUs for
* debugging purposes. Offline CPUs are skipped.
*/

View File

@ -48,11 +48,6 @@ void ha_cpuset_assign(struct hap_cpuset *dst, struct hap_cpuset *src);
*/
int ha_cpuset_size(void);
/* Detects CPUs that are bound to the current process. Returns the number of
* CPUs detected or 0 if the detection failed.
*/
int ha_cpuset_detect_bound(struct hap_cpuset *set);
/* Parse cpu sets. Each CPU set is either a unique number between 0 and
* ha_cpuset_size() - 1 or a range with two such numbers delimited by a dash
* ('-'). Each CPU set can be a list of unique numbers or ranges separated by
@ -68,9 +63,4 @@ int parse_cpu_set(const char **args, struct hap_cpuset *cpu_set, char **err);
*/
void parse_cpumap(char *cpumap_str, struct hap_cpuset *cpu_set);
/* Returns true if at least one cpu-map directive was configured, otherwise
* false.
*/
int cpu_map_configured(void);
#endif /* _HAPROXY_CPUSET_H */

View File

@ -51,6 +51,7 @@
#include <haproxy/clock.h>
#ifdef USE_CPU_AFFINITY
#include <haproxy/cpuset.h>
#include <haproxy/cpu_topo.h>
#endif
#include <haproxy/connection.h>
#include <haproxy/errors.h>

View File

@ -1,13 +1,18 @@
#define _GNU_SOURCE
#include <sched.h>
#include <string.h>
#include <unistd.h>
#include <haproxy/api.h>
#include <haproxy/cpuset.h>
#include <haproxy/cpu_topo.h>
/* CPU topology information, ha_cpuset_size() entries, allocated at boot */
int cpu_topo_maxcpus = -1; // max number of CPUs supported by OS/haproxy
int cpu_topo_lastcpu = -1; // last supposed online CPU (no need to look beyond)
struct ha_cpu_topo *ha_cpu_topo = NULL;
struct cpu_map *cpu_map;
/* Detects the CPUs that will be used based on the ones the process is bound to
* at boot. The principle is the following: all CPUs from the boot cpuset will
@ -34,6 +39,45 @@ int cpu_detect_usable(void)
return 0;
}
/* Detects CPUs that are bound to the current process. Returns the number of
* CPUs detected or 0 if the detection failed.
*/
int ha_cpuset_detect_bound(struct hap_cpuset *set)
{
ha_cpuset_zero(set);
/* detect bound CPUs depending on the OS's API */
if (0
#if defined(__linux__)
|| sched_getaffinity(0, sizeof(set->cpuset), &set->cpuset) != 0
#elif defined(__FreeBSD__)
|| cpuset_getaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset) != 0
#else
|| 1 // unhandled platform
#endif
) {
/* detection failed */
return 0;
}
return ha_cpuset_count(set);
}
/* Returns true if at least one cpu-map directive was configured, otherwise
* false.
*/
int cpu_map_configured(void)
{
int grp, thr;
for (grp = 0; grp < MAX_TGROUPS; grp++) {
for (thr = 0; thr < MAX_THREADS_PER_GROUP; thr++)
if (ha_cpuset_count(&cpu_map[grp].thread[thr]))
return 1;
}
return 0;
}
/* Dump the CPU topology <topo> for up to cpu_topo_maxcpus CPUs for
* debugging purposes. Offline CPUs are skipped.
*/
@ -109,6 +153,10 @@ static int cpu_topo_alloc(void)
cpu_topo_maxcpus = cpu_topo_get_maxcpus();
cpu_topo_lastcpu = cpu_topo_maxcpus - 1;
cpu_map = calloc(MAX_TGROUPS, sizeof(*cpu_map));
if (!cpu_map)
return 0;
/* allocate the structures used to store CPU topology info */
ha_cpu_topo = (struct ha_cpu_topo*)malloc(cpu_topo_maxcpus * sizeof(*ha_cpu_topo));
if (!ha_cpu_topo)
@ -129,6 +177,7 @@ static int cpu_topo_alloc(void)
static void cpu_topo_deinit(void)
{
ha_free(&ha_cpu_topo);
ha_free(&cpu_map);
}
INITCALL0(STG_ALLOC, cpu_topo_alloc);

View File

@ -1,14 +1,10 @@
#define _GNU_SOURCE
#include <sched.h>
#include <ctype.h>
#include <haproxy/compat.h>
#include <haproxy/cpuset.h>
#include <haproxy/intops.h>
#include <haproxy/tools.h>
struct cpu_map *cpu_map;
void ha_cpuset_zero(struct hap_cpuset *set)
{
#if defined(CPUSET_USE_CPUSET) || defined(CPUSET_USE_FREEBSD_CPUSET)
@ -149,30 +145,6 @@ int ha_cpuset_size()
#endif
}
/* Detects CPUs that are bound to the current process. Returns the number of
* CPUs detected or 0 if the detection failed.
*/
int ha_cpuset_detect_bound(struct hap_cpuset *set)
{
ha_cpuset_zero(set);
/* detect bound CPUs depending on the OS's API */
if (0
#if defined(__linux__)
|| sched_getaffinity(0, sizeof(set->cpuset), &set->cpuset) != 0
#elif defined(__FreeBSD__)
|| cpuset_getaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset) != 0
#else
|| 1 // unhandled platform
#endif
) {
/* detection failed */
return 0;
}
return ha_cpuset_count(set);
}
/* Parse cpu sets. Each CPU set is either a unique number between 0 and
* ha_cpuset_size() - 1 or a range with two such numbers delimited by a dash
* ('-'). Each CPU set can be a list of unique numbers or ranges separated by
@ -258,39 +230,3 @@ void parse_cpumap(char *cpumap_str, struct hap_cpuset *cpu_set)
++i;
} while (comma);
}
/* Returns true if at least one cpu-map directive was configured, otherwise
* false.
*/
int cpu_map_configured(void)
{
int grp, thr;
for (grp = 0; grp < MAX_TGROUPS; grp++) {
for (thr = 0; thr < MAX_THREADS_PER_GROUP; thr++)
if (ha_cpuset_count(&cpu_map[grp].thread[thr]))
return 1;
}
return 0;
}
/* Allocates everything needed to store CPU information at boot.
* Returns non-zero on success, zero on failure.
*/
static int cpuset_alloc(void)
{
/* allocate the structures used to store CPU topology info */
cpu_map = calloc(MAX_TGROUPS, sizeof(*cpu_map));
if (!cpu_map)
return 0;
return 1;
}
static void cpuset_deinit(void)
{
ha_free(&cpu_map);
}
INITCALL0(STG_ALLOC, cpuset_alloc);
REGISTER_POST_DEINIT(cpuset_deinit);

View File

@ -35,6 +35,7 @@
# include <mach/thread_policy.h>
# endif
# include <haproxy/cpuset.h>
# include <haproxy/cpu_topo.h>
#endif
#include <haproxy/cfgparse.h>