293 lines
7.2 KiB
Diff
293 lines
7.2 KiB
Diff
--- 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<<k))
|
|
- maxcpus = i*sizeof(long)+k;
|
|
- }
|
|
- return maxcpus;
|
|
- }
|
|
- break;
|
|
- }
|
|
- numa_warn(W_noproc, "/proc not mounted. Assuming zero nodes: %s",
|
|
- strerror(errno));
|
|
- return 0;
|
|
- }
|
|
- maxcpus = 0;
|
|
- while (getdelim(&line, &len, '\n', f) > 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);
|