Re: [PATCH] cpumask 5/10 rewrite cpumask.h - single bitmap based implementation

William Lee Irwin III
2004-06-04T18:13:04Z

/* William Lee Irwin III:
>> I'm thoroughly disgusted.

On Fri, Jun 04, 2004 at 10:47:56AM -0700, Paul Jackson wrote:
> Yup ... LOL. One sick piece of code.
> I didn't return the actual return from sched_getaffinity() because (1)
> it's ok to estimate the mask size too high, and (2) given that the man
> page and kernel don't agree on the return value of sched_getaffinity(),
> I figured that the less I relied on it, the longer my user code would
> continue functioning in a useful manner. As always, the key to robust
> code (code that withstands the perils of time) is minimizing risky
> assumptions.

Even the following returns 32 on UP. _SC_NPROCESSOR_CONF is
unimplementable. NR_CPUS serves as an upper bound on the number of cpus
that may at some time be simultaneously present in the future. Without
any way to reliably determine this, luserspace is fscked.

*/

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <sys/syscall.h>

static int getaffinity(pid_t, size_t, unsigned long *);
static int detect_nr_cpus(void);

int main(void)
{
printf("%d\n", detect_nr_cpus());
return 0;
}

static int detect_nr_cpus(void)
{
unsigned long *cpus = malloc(sizeof(long));
size_t upper, middle, lower = sizeof(long);

for (upper = lower; getaffinity(0, upper, cpus) < 0; upper *= 2) {
if (!realloc(cpus, 2*upper))
return -ENOMEM;
}
while (lower < upper) {
middle = (lower + upper)/2;
if (!realloc(cpus, middle))
return -ENOMEM;
if (getaffinity(0, middle, cpus) < 0)
lower = middle;
else
upper = middle;
}
return CHAR_BIT*upper;
}

static int getaffinity(pid_t pid, size_t size, unsigned long *cpus)
{
return syscall(__NR_sched_getaffinity, pid, size, cpus);
}