The hwloc_cpuset_next() will calculate the next cpu behind a given one.

Use hwloc_cpuset_first() and hwloc_cpuset_next() in hwloc_cpuset_foreach()
to sparsely iterate over a cpuset.

Regards,
Bert

---
 doc/Makefile.am                        |    1 +
 include/hwloc/cpuset.h                 |    9 ++++++---
 include/hwloc/rename.h                 |    1 +
 src/cpuset.c                           |   24 ++++++++++++++++++++++++
 tests/hwloc_cpuset_first_last_weight.c |   28 +++++++++++++++++++++++++++-
 5 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/doc/Makefile.am b/doc/Makefile.am
index 9c7bcf7..6fed82c 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -266,6 +266,7 @@ man3_MANS = \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_isset.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_iszero.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_last.3 \
+        $(DOX_MAN_DIR)/man3/hwloc_cpuset_next.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_notset.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_orset.3 \
         $(DOX_MAN_DIR)/man3/hwloc_cpuset_set.3 \
diff --git a/include/hwloc/cpuset.h b/include/hwloc/cpuset.h
index ad2dab4..5a629e9 100644
--- a/include/hwloc/cpuset.h
+++ b/include/hwloc/cpuset.h
@@ -156,6 +156,9 @@ HWLOC_DECLSPEC int hwloc_cpuset_first(hwloc_const_cpuset_t 
set) __hwloc_attribut
 /** \brief Compute the last CPU (most significant bit) in CPU set \p set */
 HWLOC_DECLSPEC int hwloc_cpuset_last(hwloc_const_cpuset_t set) 
__hwloc_attribute_pure;

+/** \brief Compute the next CPU in CPU set \p set which is after CPU \p 
prev_cpu */
+HWLOC_DECLSPEC int hwloc_cpuset_next(hwloc_const_cpuset_t set, unsigned 
prev_cpu) __hwloc_attribute_pure;
+
 /** \brief Keep a single CPU among those set in CPU set \p set
  *
  * Might be used before binding so that the process does not
@@ -188,13 +191,13 @@ HWLOC_DECLSPEC int 
hwloc_cpuset_weight(hwloc_const_cpuset_t set) __hwloc_attribu
  */
 #define hwloc_cpuset_foreach_begin(cpu, set) \
 do { \
-        for (cpu = 0; cpu < HWLOC_NBMAXCPUS; cpu++) { \
-                if (hwloc_cpuset_isset(set, cpu)) {
+        for (cpu = hwloc_cpuset_first(set); \
+             cpu != -1; \
+             cpu = hwloc_cpuset_next(set, cpu)) { \
 /** \brief End of loop. Needs a terminating ';'.
  *
  * \sa hwloc_cpuset_foreach_begin */
 #define hwloc_cpuset_foreach_end() \
-                } \
         } \
 } while (0)

diff --git a/include/hwloc/rename.h b/include/hwloc/rename.h
index 6ebb454..bf1b600 100644
--- a/include/hwloc/rename.h
+++ b/include/hwloc/rename.h
@@ -165,6 +165,7 @@
 #define hwloc_cpuset_notset HWLOC_NAME(cpuset_notset)
 #define hwloc_cpuset_first HWLOC_NAME(cpuset_first)
 #define hwloc_cpuset_last HWLOC_NAME(cpuset_last)
+#define hwloc_cpuset_next HWLOC_NAME(cpuset_next)
 #define hwloc_cpuset_singlify HWLOC_NAME(cpuset_singlify)
 #define hwloc_cpuset_compare_first HWLOC_NAME(cpuset_compare_first)
 #define hwloc_cpuset_compare HWLOC_NAME(cpuset_compare)
diff --git a/src/cpuset.c b/src/cpuset.c
index 1787489..e2f9b16 100644
--- a/src/cpuset.c
+++ b/src/cpuset.c
@@ -510,6 +510,30 @@ int hwloc_cpuset_last(const struct hwloc_cpuset_s * set)
        return -1;
 }

+int hwloc_cpuset_next(const struct hwloc_cpuset_s * set, unsigned prev_cpu)
+{
+       int i = HWLOC_CPUSUBSET_INDEX(prev_cpu + 1);
+
+       HWLOC__CPUSET_CHECK(set);
+
+       for(; i<HWLOC_CPUSUBSET_COUNT; i++) {
+               unsigned long w = HWLOC_CPUSUBSET_SUBSET(*set,i);
+
+               /* if the prev cpu is in the same word as the possible next one,
+                  we need to mask out previous cpus */
+               if (HWLOC_CPUSUBSET_INDEX(prev_cpu) == i) {
+                       w &= ~((HWLOC_CPUSUBSET_VAL(prev_cpu) << 1) - 1);
+               }
+
+               /* subsets are unsigned longs, use ffsl */
+               int _ffs = hwloc_ffsl(w);
+               if (_ffs>0)
+                       return _ffs - 1 + HWLOC_CPUSUBSET_SIZE*i;
+       }
+
+       return -1;
+}
+
 void hwloc_cpuset_singlify(struct hwloc_cpuset_s * set)
 {
        int i,found = 0;
diff --git a/tests/hwloc_cpuset_first_last_weight.c 
b/tests/hwloc_cpuset_first_last_weight.c
index 093aea1..8a65d8e 100644
--- a/tests/hwloc_cpuset_first_last_weight.c
+++ b/tests/hwloc_cpuset_first_last_weight.c
@@ -8,22 +8,27 @@

 #include <assert.h>

-/* check hwloc_cpuset_first(), _last() and _weight() */
+/* check hwloc_cpuset_first(), _last(), _next() and _weight() */

 int main(void)
 {
   hwloc_cpuset_t set;
+  int i, cpu, expected_cpu;

   /* empty set */
   set = hwloc_cpuset_alloc();
   assert(hwloc_cpuset_first(set) == -1);
   assert(hwloc_cpuset_last(set) == -1);
+  assert(hwloc_cpuset_next(set, 0) == -1);
   assert(hwloc_cpuset_weight(set) == 0);

   /* full set */
   hwloc_cpuset_fill(set);
   assert(hwloc_cpuset_first(set) == 0);
   assert(hwloc_cpuset_last(set) == HWLOC_NBMAXCPUS-1);
+  assert(hwloc_cpuset_next(set, 0) == 1);
+  assert(hwloc_cpuset_next(set, HWLOC_NBMAXCPUS-2) == HWLOC_NBMAXCPUS-1);
+  assert(hwloc_cpuset_next(set, HWLOC_NBMAXCPUS-1) == -1);
   assert(hwloc_cpuset_weight(set) == HWLOC_NBMAXCPUS);

   /* custom sets */
@@ -31,16 +36,37 @@ int main(void)
   hwloc_cpuset_set_range(set, 36, 59);
   assert(hwloc_cpuset_first(set) == 36);
   assert(hwloc_cpuset_last(set) == 59);
+  assert(hwloc_cpuset_next(set, 0) == 36);
+  assert(hwloc_cpuset_next(set, 36) == 37);
+  assert(hwloc_cpuset_next(set, 59) == -1);
   assert(hwloc_cpuset_weight(set) == 24);
   hwloc_cpuset_set_range(set, 136, 259);
   assert(hwloc_cpuset_first(set) == 36);
   assert(hwloc_cpuset_last(set) == 259);
+  assert(hwloc_cpuset_next(set, 59) == 136);
+  assert(hwloc_cpuset_next(set, 259) == -1);
   assert(hwloc_cpuset_weight(set) == 148);
   hwloc_cpuset_clr(set, 199);
   assert(hwloc_cpuset_first(set) == 36);
   assert(hwloc_cpuset_last(set) == 259);
+  assert(hwloc_cpuset_next(set, 198) == 200);
+  assert(hwloc_cpuset_next(set, 199) == 200);
   assert(hwloc_cpuset_weight(set) == 147);

+  i = 0;
+  hwloc_cpuset_foreach_begin(cpu, set) {
+    if (0 <= i && i < 24)
+      expected_cpu = i + 36;
+    else if (24 <= i && i < 87)
+      expected_cpu = i + 112;
+    else if (87 <= i && i < 147)
+      expected_cpu = i + 113;
+
+    assert(expected_cpu == cpu);
+
+    i++;
+  } hwloc_cpuset_foreach_end();
+
   hwloc_cpuset_free(set);

   return 0;
-- 
tg: (1926bee..) bw/sparse-cpuset-foreach (depends on: 
bw/semi-colon-safe-foreach)

Reply via email to