Blob Blame History Raw
--- 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);