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