MINOR: cpuset: define a platform-independent cpuset type

This module can be used to manipulate a cpu sets in a platform agnostic
way. Use the type cpu_set_t/cpuset_t if available on the platform, or
fallback to unsigned long, which limits de facto the maximum cpu index
to LONGBITS.
diff --git a/src/cpuset.c b/src/cpuset.c
new file mode 100644
index 0000000..e4310b6
--- /dev/null
+++ b/src/cpuset.c
@@ -0,0 +1,121 @@
+#define _GNU_SOURCE
+#include <sched.h>
+
+#include <haproxy/compat.h>
+#include <haproxy/cpuset.h>
+#include <haproxy/intops.h>
+
+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, const 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, const 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)
+	return CPU_SETSIZE;
+
+#elif defined(CPUSET_USE_FREEBSD_CPUSET)
+	return MAXCPU;
+
+#elif defined(CPUSET_USE_ULONG)
+	return LONGBITS;
+
+#endif
+}