mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 23:56:57 +02:00
We're currently having a problem with the porting from cpu_map from processes to thread-groups as it happened in 2.7 with commit5b09341c0
("MEDIUM: cpu-map: replace the process number with the thread group number"), though it seems that it has deeper roots even in 2.0 and that it was progressively made worng over time. The issue stems in the way the per-process and per-thread cpu-sets were employed over time. Originally only processes were supported. Then threads were added after an optional "/" and it was documented that "cpu-map 1" is exactly equivalent to "cpu-map 1/all" (this was clarified in 2.5 by commit317804d28
("DOC: update references to process numbers in cpu-map and bind-process"). The reality is different: when processes were still supported, setting "cpu-map 1" would apply the mask to the process itself (and only when run in the background, which is not documented either and is also a bug for another fix), and would be combined with any possible per-thread mask when calculating the threads' affinity, possibly resulting in empty sets. However, "cpu-map 1/all" would only set the mask for the threads and not the process. As such the following: cpu-map 1 odd cpu-map 1/1-8 even would leave no CPU while doing: cpu-map 1/all odd cpu-map 1/1-8 even would allow all CPUs. While such configs are very unlikely to ever be met (which is why this bug is tagged minor), this is becoming quite more visible while testing automatic CPU binding during 2.9 development because due to this bug it's much more common to end up with incorrect bindings. This patch fixes it by simply removing the .proc entry from cpu_map and always setting all threads' maps. The process is no longer arbitrarily bound to the group 1's mask, but in case threads are disabled, we'll use thread 1's mask since it contains the configured CPUs. This fix should be backported at least to 2.6, but no need to insist if it resists as it's easier to break cpu-map than to fix an unlikely issue.
136 lines
2.6 KiB
C
136 lines
2.6 KiB
C
#define _GNU_SOURCE
|
|
#include <sched.h>
|
|
|
|
#include <haproxy/compat.h>
|
|
#include <haproxy/cpuset.h>
|
|
#include <haproxy/intops.h>
|
|
|
|
struct cpu_map cpu_map[MAX_TGROUPS];
|
|
|
|
void ha_cpuset_zero(struct hap_cpuset *set)
|
|
{
|
|
#if defined(CPUSET_USE_CPUSET) || defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
CPU_ZERO(&set->cpuset);
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
set->cpuset = 0;
|
|
#endif
|
|
}
|
|
|
|
int ha_cpuset_set(struct hap_cpuset *set, int cpu)
|
|
{
|
|
if (cpu >= ha_cpuset_size())
|
|
return 1;
|
|
|
|
#if defined(CPUSET_USE_CPUSET) || defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
CPU_SET(cpu, &set->cpuset);
|
|
return 0;
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
set->cpuset |= (0x1 << cpu);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int ha_cpuset_clr(struct hap_cpuset *set, int cpu)
|
|
{
|
|
if (cpu >= ha_cpuset_size())
|
|
return 1;
|
|
|
|
#if defined(CPUSET_USE_CPUSET) || defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
CPU_CLR(cpu, &set->cpuset);
|
|
return 0;
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
set->cpuset &= ~(0x1 << cpu);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
void ha_cpuset_and(struct hap_cpuset *dst, struct hap_cpuset *src)
|
|
{
|
|
#if defined(CPUSET_USE_CPUSET)
|
|
CPU_AND(&dst->cpuset, &dst->cpuset, &src->cpuset);
|
|
|
|
#elif defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
CPU_AND(&dst->cpuset, &src->cpuset);
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
dst->cpuset &= src->cpuset;
|
|
#endif
|
|
}
|
|
|
|
int ha_cpuset_count(const struct hap_cpuset *set)
|
|
{
|
|
#if defined(CPUSET_USE_CPUSET) || defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
return CPU_COUNT(&set->cpuset);
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
return my_popcountl(set->cpuset);
|
|
#endif
|
|
}
|
|
|
|
int ha_cpuset_ffs(const struct hap_cpuset *set)
|
|
{
|
|
#if defined(CPUSET_USE_CPUSET)
|
|
int n;
|
|
|
|
if (!CPU_COUNT(&set->cpuset))
|
|
return 0;
|
|
|
|
for (n = 0; !CPU_ISSET(n, &set->cpuset); ++n)
|
|
;
|
|
|
|
return n + 1;
|
|
|
|
#elif defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
return CPU_FFS(&set->cpuset);
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
if (!set->cpuset)
|
|
return 0;
|
|
|
|
return my_ffsl(set->cpuset);
|
|
#endif
|
|
}
|
|
|
|
void ha_cpuset_assign(struct hap_cpuset *dst, struct hap_cpuset *src)
|
|
{
|
|
#if defined(CPUSET_USE_CPUSET)
|
|
CPU_ZERO(&dst->cpuset);
|
|
CPU_OR(&dst->cpuset, &dst->cpuset, &src->cpuset);
|
|
|
|
#elif defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
CPU_COPY(&src->cpuset, &dst->cpuset);
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
dst->cpuset = src->cpuset;
|
|
#endif
|
|
}
|
|
|
|
int ha_cpuset_size()
|
|
{
|
|
#if defined(CPUSET_USE_CPUSET) || defined(CPUSET_USE_FREEBSD_CPUSET)
|
|
return CPU_SETSIZE;
|
|
|
|
#elif defined(CPUSET_USE_ULONG)
|
|
return LONGBITS;
|
|
|
|
#endif
|
|
}
|
|
|
|
/* 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;
|
|
}
|