From: Cliff Wickman <cpw@xxxxxxx> 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 <cpw@xxxxxxx> --- 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; -- To unsubscribe from this list: send the line "unsubscribe linux-numa" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html