--- numactl-0.9.8/libnuma.c.orig 2006-08-14 14:14:31.000000000 -0400 +++ numactl-0.9.8/libnuma.c 2006-08-14 14:14:37.000000000 -0400 @@ -118,58 +118,28 @@ static int maxnode = -1; static int maxcpus = -1; -static int number_of_cpus(void) +static int number_of_configured_cpus(void) { - char *line = NULL; - size_t len = 0; - char *s; - FILE *f; - int cpu; - + int len = 16; + int n; + int olde = errno; + if (maxcpus >= 0) return maxcpus + 1; - f = fopen("/proc/cpuinfo","r"); - if (!f) { - int n; - int len = 8192; - for (;;) { - unsigned long buffer[CPU_LONGS(len)]; - memset(buffer, 0, sizeof(buffer)); - n = numa_sched_getaffinity_int(0, CPU_BYTES(len), - buffer); - if (n < 0 && errno == EINVAL && len < 1024*1024) { - len *= 2; - continue; - } - if (n >= 0) { - int i, k; - for (i = 0; i < n / sizeof(long); i++) { - if (!buffer[i]) - continue; - for (k = 0; k< 8; k++) - if (buffer[i] & (1< 0) { - if (strncmp(line,"processor",9)) + do { + unsigned long buffer[CPU_LONGS(len)]; + memset(buffer, 0, sizeof(buffer)); + n = numa_sched_getaffinity_int(0, CPU_BYTES(len), buffer); + if (n < 0 && errno == EINVAL) { + if (len >= 1024*1024) + break; + len *= 2; continue; - s = line + strcspn(line, "0123456789"); - if (sscanf(s, "%d", &cpu) == 1 && cpu > maxcpus) - maxcpus = cpu; - } - free(line); - fclose(f); - return maxcpus + 1; + } + } while (n < 0); + errno = olde; + return len; } static int fallback_max_node(void) @@ -428,32 +398,67 @@ static unsigned long *node_cpu_mask[NUMA_NUM_NODES]; +static void bad_cpumap(int ncpus, unsigned long *mask) +{ + int n; + for (n = 0; n < ncpus; n++) + set_bit(n, mask); +} + +int numa_parse_bitmap(char *line, unsigned long *mask, int ncpus) +{ + int i; + char *p = strchr(line, '\n'); + if (!p) + return -1; + + for (i = 0; p > line;i++) { + char *oldp, *endp; + oldp = p; + if (*p == ',') + --p; + while (p > line && *p != ',') + --p; + /* Eat two 32bit fields at a time to get longs */ + if (sizeof(unsigned long) == 8) { + oldp--; + memmove(p, p+1, oldp-p+1); + while (p > line && *p != ',') + --p; + } + if (*p == ',') + p++; + if (i >= CPU_LONGS(ncpus)) + return -1; + mask[i] = strtoul(p, &endp, 16); + if (endp != oldp) + return -1; + p--; + } + return 0; +} + /* This would be better with some locking, but I don't want to make libnuma dependent on pthreads right now. The races are relatively harmless. */ int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { + int err = 0; char fn[64]; FILE *f; char *line = NULL; size_t len = 0; - char *s; - int n; int buflen_needed; - unsigned long *mask, prev; - int ncpus = number_of_cpus(); - int i; - int mask_words; - int bits_in_mask_0; + unsigned long *mask; + int ncpus = number_of_configured_cpus(); buflen_needed = CPU_BYTES(ncpus); if ((unsigned)node > maxnode || bufferlen < buflen_needed) { errno = ERANGE; return -1; } - + if (bufferlen > buflen_needed) + memset(buffer, 0, bufferlen); if (node_cpu_mask[node]) { - if (bufferlen > buflen_needed) - memset(buffer, 0, bufferlen); memcpy(buffer, node_cpu_mask[node], buflen_needed); return 0; } @@ -462,73 +467,43 @@ if (!mask) mask = (unsigned long *)buffer; memset(mask, 0, buflen_needed); - + sprintf(fn, "/sys/devices/system/node/node%d/cpumap", node); f = fopen(fn, "r"); if (!f || getdelim(&line, &len, '\n', f) < 1) { numa_warn(W_nosysfs2, "/sys not mounted or invalid. Assuming one node: %s", strerror(errno)); - for (n = 0; n < ncpus; n++) - set_bit(n, (unsigned long *)mask); - goto out; + bad_cpumap(ncpus, mask); + err = -1; } - mask_words = 0; - bits_in_mask_0 = 0; - n = 0; - s = line; - prev = 0; - for (i = 0; s[i]; i++) { - static const char hexdigits[] = "0123456789abcdef"; - char *w = strchr(hexdigits, tolower(s[i])); - if (!w) { - if (isspace(s[i]) || s[i] == ',') - continue; - numa_warn(W_cpumap, - "Unexpected character `%c' in sysfs cpumap", - s[i]); - set_bit(node, mask); - goto out; - } + if (f) + fclose(f); - /* if mask[0] is full shift left before adding another */ - if (bits_in_mask_0 >= sizeof(mask[0])*8) { - /* skip any leading zeros */ - if (prev || mask[0]){ - /* shift over any previously loaded masks */ - memmove(mask+mask_words+1, mask+mask_words, - sizeof(mask[0]) * mask_words); - mask_words++; - bits_in_mask_0 = 0; - mask[0] = 0; - prev = 1; - } - } - - mask[0] = (mask[0]*16) + (w - hexdigits); - bits_in_mask_0 += 4; /* 4 bits per hex char */ + if (line && numa_parse_bitmap(line, mask, ncpus) < 0) { + numa_warn(W_cpumap, "Cannot parse cpumap. Assuming one node"); + bad_cpumap(ncpus, mask); + err = -1; } - out: - free(line); - if (f) - fclose(f); + + free(line); memcpy(buffer, mask, buflen_needed); /* slightly racy, see above */ if (node_cpu_mask[node]) { - if (mask != (unsigned long *)buffer) + if (mask != buffer) free(mask); } else { - node_cpu_mask[node] = (unsigned long *)mask; + node_cpu_mask[node] = mask; } - return 0; + return err; } make_internal_alias(numa_node_to_cpus); int numa_run_on_node_mask(const nodemask_t *mask) { - int ncpus = number_of_cpus(); + int ncpus = number_of_configured_cpus(); int i, k, err; unsigned long cpus[CPU_LONGS(ncpus)], nodecpus[CPU_LONGS(ncpus)]; memset(cpus, 0, CPU_BYTES(ncpus)); @@ -582,7 +557,7 @@ nodemask_t numa_get_run_node_mask(void) { - int ncpus = number_of_cpus(); + int ncpus = number_of_configured_cpus(); nodemask_t mask; int i, k; int max = numa_max_node_int(); @@ -594,7 +569,7 @@ return numa_no_nodes; for (i = 0; i <= max; i++) { if (numa_node_to_cpus_int(i, nodecpus, CPU_BYTES(ncpus)) < 0) { - numa_warn(W_noderunmask, "Cannot read node cpumask from sysfs"); + /* It's possible for the node to not exist */ continue; } for (k = 0; k < CPU_LONGS(ncpus); k++) { @@ -612,12 +587,15 @@ int numa_run_on_node(int node) { - int ncpus = number_of_cpus(); + int ncpus = number_of_configured_cpus(); unsigned long cpus[CPU_LONGS(ncpus)]; - if (node == -1) - memset(cpus, 0xff, CPU_BYTES(ncpus)); - else if (node < NUMA_NUM_NODES) { + if (node == -1) { + int i; + memset(cpus, 0, CPU_BYTES(ncpus)); + for (i = 0; i < ncpus; i++) + cpus[i / BITS_PER_LONG] |= 1UL << (i%BITS_PER_LONG); + } else if (node < NUMA_NUM_NODES) { if (numa_node_to_cpus_int(node, cpus, CPU_BYTES(ncpus)) < 0) { numa_warn(W_noderunmask, "Cannot read node cpumask from sysfs"); return -1; @@ -649,7 +627,7 @@ void numa_set_preferred(int node) { nodemask_t n; - if (node == -1) { + if (node < 0) { nodemask_t empty; nodemask_zero(&empty); setpol(MPOL_DEFAULT, empty);