[PATCH] libnuma:

Cliff Wickman <[email protected]>
Newsgroups org.kernel.vger.linux-numa
Message-ID <[email protected]>
From: Cliff Wickman <[email protected]>

The numa_num_task_cpus() function should return the number of cpu's
available to the caller.  It was returning his highest available cpu
number (+1).
That was an erroneous assumption when the caller is in a cpuset where
available cpu's are not numbered 0..N.

Likewise, numa_num_task_nodes() was doing the same thing.

This patch adds a numa_bitmask_weight() function to count set bits in the map
and makes it available for user convenience as well.
    
Signed-off-by: Cliff Wickman <[email protected]>

---
 libnuma.c         |   55 ++++++++++++++++++++++++++++--------------------------
 numa.3            |    8 +++++++
 versions.ldscript |    1 
 3 files changed, 38 insertions(+), 26 deletions(-)

Index: numactl-dev/libnuma.c
===================================================================
--- numactl-dev.orig/libnuma.c
+++ numactl-dev/libnuma.c
@@ -67,8 +67,8 @@ static __thread unsigned int mbind_flags
 static int sizes_set=0;
 static int maxconfigurednode = -1;
 static int maxconfiguredcpu = -1;
-static int maxprocnode = -1;
-static int maxproccpu = -1;
+static int numprocnode = -1;
+static int numproccpu = -1;
 static int nodemask_sz = 0;
 static int cpumask_sz = 0;
 
@@ -230,6 +230,18 @@ numa_bitmask_equal(const struct bitmask
 			return 0;
 	return 1;
 }
+
+/* Hamming Weight: number of set bits */
+unsigned int numa_bitmask_weight(const struct bitmask *bmp)
+{
+	unsigned int i;
+	unsigned int w = 0;
+	for (i = 0; i < bmp->size; i++)
+		if (_getbit(bmp, i))
+			w++;
+	return w;
+}
+
 /* *****end of bitmask_  routines ************ */
 
 /* Next two can be overwritten by the application for different error handling */
@@ -386,8 +398,7 @@ done:
 
 /*
  * Read a mask consisting of a sequence of hexadecimal longs separated by
- * commas. Order them correctly and return the number of the last bit
- * set.
+ * commas. Order them correctly and return the number of bits set.
  */
 static int
 read_mask(char *s, struct bitmask *bmp)
@@ -436,17 +447,10 @@ read_mask(char *s, struct bitmask *bmp)
 
 		bmp->maskp[m++] = x;
 	}
-	m--;
-
-	/* Poor mans fls() */
-	for(i = bitsperlong - 1; i >= 0; i--)
-		if (test_bit(i, bmp->maskp + m))
-			break;
-
 	/*
-	 * Return the last bit set
+	 * Return the number of bits set
 	 */
-	return bitsperlong * m + i;
+	return numa_bitmask_weight(bmp);
 }
 
 /*
@@ -477,11 +481,10 @@ set_task_constraints(void)
 		char  *mask = strrchr(buffer,'\t') + 1;
 
 		if (strncmp(buffer,"Cpus_allowed:",13) == 0)
-			maxproccpu = read_mask(mask, numa_all_cpus_ptr);
+			numproccpu = read_mask(mask, numa_all_cpus_ptr);
 
 		if (strncmp(buffer,"Mems_allowed:",13) == 0) {
-			maxprocnode =
-				read_mask(mask, numa_all_nodes_ptr);
+			numprocnode = read_mask(mask, numa_all_nodes_ptr);
 		}
 	}
 	fclose(f);
@@ -490,26 +493,26 @@ set_task_constraints(void)
 	/*
 	 * Cpus_allowed in the kernel can be defined to all f's
 	 * i.e. it may be a superset of the actual available processors.
-	 * As such let's reduce maxproccpu to the number of actual
-	 * available cpus - 1.
+	 * As such let's reduce numproccpu to the number of actual
+	 * available cpus.
 	 */
-	if (maxproccpu <= 0) {
+	if (numproccpu <= 0) {
 		for (i = 0; i <= hicpu; i++)
 			numa_bitmask_setbit(numa_all_cpus_ptr, i);
-		maxproccpu = hicpu;
+		numproccpu = hicpu+1;
 	}
 
-	if (maxproccpu > hicpu) {
-		maxproccpu = hicpu;
+	if (numproccpu > hicpu+1) {
+		numproccpu = hicpu+1;
 		for (i=hicpu+1; i<numa_all_cpus_ptr->size; i++) {
 			numa_bitmask_clearbit(numa_all_cpus_ptr, i);
 		}
 	}
 
-	if (maxprocnode <= 0) {
+	if (numprocnode <= 0) {
 		for (i = 0; i <= maxconfigurednode; i++)
 			numa_bitmask_setbit(numa_all_nodes_ptr, i);
-		maxprocnode = maxconfigurednode;
+		numprocnode = maxconfigurednode + 1;
 	}
 
 	return;
@@ -632,7 +635,7 @@ numa_num_possible_cpus(void)
 int
 numa_num_task_nodes(void)
 {
-	return maxprocnode+1;
+	return numprocnode;
 }
 
 /*
@@ -647,7 +650,7 @@ numa_num_thread_nodes(void)
 int
 numa_num_task_cpus(void)
 {
-	return maxproccpu+1;
+	return numproccpu;
 }
 
 /*
Index: numactl-dev/numa.3
===================================================================
--- numactl-dev.orig/numa.3
+++ numactl-dev/numa.3
@@ -149,6 +149,8 @@ numa \- NUMA policy library
 .BI "void copy_nodemask_to_bitmask(nodemask_t *" nodemask ", struct bitmask *" bmp )
 .br
 .BI "void copy_bitmask_to_bitmask(struct bitmask *" bmpfrom ", struct bitmask *" bmpto )
+.br
+.BI "unsigned int numa_bitmask_weight(const struct bitmask *bmp )
 .sp
 .BI "int numa_move_pages(int " pid ", unsigned long " count ", void **" pages ", const int *" nodes ", int *" status ", int " flags );
 .br
@@ -860,6 +862,12 @@ pointer to the body of the bitmask struc
 pointer. If the two areas differ in size, the copy is truncated to the size
 of the receiving field or zero-filled.
 
+.BR numa_bitmask_weight()
+returns a count of the bits that are set in the body of the bitmask pointed
+to by the
+.I bmp
+argument.
+
 .br
 .BR numa_move_pages()
 moves a list of pages in the address space of the currently
Index: numactl-dev/versions.ldscript
===================================================================
--- numactl-dev.orig/versions.ldscript
+++ numactl-dev/versions.ldscript
@@ -100,6 +100,7 @@ libnuma_1.2 {
     numa_bitmask_nbytes;
     numa_bitmask_setall;
     numa_bitmask_setbit;
+    numa_bitmask_weight;
     numa_distance;
     numa_error;
     numa_exit_on_error;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.