[Openmp-commits] [openmp] 1f48c2f - [OpenMP] Corrects the setting of the Static_Steal schedule with `omp_set_schedule` (#227236)

via Openmp-commits openmp-commits at lists.llvm.org
Fri Oct 2 03:23:37 PDT 2026


Author: Samuel Newcome
Date: 2026-10-02T10:23:29Z
New Revision: 1f48c2f8f4021f016a62fe0cebf877c4c8f5dffd

URL: https://github.com/llvm/llvm-project/commit/1f48c2f8f4021f016a62fe0cebf877c4c8f5dffd
DIFF: https://github.com/llvm/llvm-project/commit/1f48c2f8f4021f016a62fe0cebf877c4c8f5dffd.diff

LOG: [OpenMP] Corrects the setting of the Static_Steal schedule with `omp_set_schedule` (#227236)

Static-steal is considered a valid OMP scheduler by `kmp_runtime.cpp`'s
`__kmp_set_schedule` function. But when trying pass it to the setter, we
end up with a failure because it was not added to the `__kmp_sch_map` in
`kmp_global.cpp`.

This PR adds a test that each schedule in `kmp.h` can be set and gotten
by `omp_set_schedule` and `omp_get_schedule`, which fails with static
steal and a fix for `__kmp_sch_map`. To deal with static-steal set this
way with `ordered` loops, I added similar handling as with setting
static steal as an environment variable: gets converted to dynamic,
nonmonotonic when initialising the loop, so when combined with `ordered`
simply dynamic scheduling is used. A test that static-steal with
`ordered` works was added, which used to hang before adding this
handling.

This PR was made with AI assitance. All code was reviewed and where
necessary modified by myself.

Added: 
    openmp/runtime/test/worksharing/for/kmp_sched_set_get.c
    openmp/runtime/test/worksharing/for/kmp_sched_static_steal_ordered.c

Modified: 
    openmp/runtime/src/kmp_dispatch.cpp
    openmp/runtime/src/kmp_global.cpp

Removed: 
    


################################################################################
diff  --git a/openmp/runtime/src/kmp_dispatch.cpp b/openmp/runtime/src/kmp_dispatch.cpp
index 3b4a1f34df040..57e4bcb83f60f 100644
--- a/openmp/runtime/src/kmp_dispatch.cpp
+++ b/openmp/runtime/src/kmp_dispatch.cpp
@@ -265,6 +265,13 @@ void __kmp_dispatch_init_algorithm(ident_t *loc, int gtid,
       // Use the scheduling specified by OMP_SCHEDULE (or __kmp_sch_default if
       // not specified)
       schedule = team->t.t_sched.r_sched_type;
+#if KMP_STATIC_STEAL_ENABLED
+      // Treat static_steal set by omp_set_schedule() like
+      // OMP_SCHEDULE=static_steal, i.e. as nonmonotonic dynamic
+      if (SCHEDULE_WITHOUT_MODIFIERS(schedule) == kmp_sch_static_steal)
+        schedule = (enum sched_type)(kmp_sch_dynamic_chunked |
+                                     kmp_sch_modifier_nonmonotonic);
+#endif
       monotonicity = __kmp_get_monotonicity(loc, schedule, use_hier);
       schedule = SCHEDULE_WITHOUT_MODIFIERS(schedule);
       if (pr->flags.ordered) // correct monotonicity for ordered loop if needed

diff  --git a/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp
index 15b9babfaf0ba..78ae429e3d465 100644
--- a/openmp/runtime/src/kmp_global.cpp
+++ b/openmp/runtime/src/kmp_global.cpp
@@ -235,9 +235,10 @@ enum sched_type __kmp_sch_map[kmp_sched_upper - kmp_sched_lower_ext +
     kmp_sch_dynamic_chunked, // ==> kmp_sched_dynamic           = 2
     kmp_sch_guided_chunked, // ==> kmp_sched_guided            = 3
     kmp_sch_auto, // ==> kmp_sched_auto              = 4
-    kmp_sch_trapezoidal // ==> kmp_sched_trapezoidal       = 101
-    // will likely not be used, introduced here just to debug the code
-    // of public intel extension schedules
+    kmp_sch_trapezoidal, // ==> kmp_sched_trapezoidal       = 101
+#if KMP_STATIC_STEAL_ENABLED
+    kmp_sch_static_steal // ==> kmp_sched_static_steal      = 102
+#endif
 };
 
 #if KMP_MIC_SUPPORTED

diff  --git a/openmp/runtime/test/worksharing/for/kmp_sched_set_get.c b/openmp/runtime/test/worksharing/for/kmp_sched_set_get.c
new file mode 100644
index 0000000000000..f1f1ae3102243
--- /dev/null
+++ b/openmp/runtime/test/worksharing/for/kmp_sched_set_get.c
@@ -0,0 +1,81 @@
+// RUN: %libomp-compile-and-run
+
+// The test checks that every schedule kind accepted by omp_set_schedule(),
+// i.e. that is not considered out of range in __kmp_set_schedule in
+// kmp_runtime.cpp, can be set, and we can afterwards get the schedule back with
+// omp_get_schedule
+
+#include <omp.h>
+#include <stdio.h>
+
+// ---------------------------------------------------------------------------
+// As with kmp.h, static steal is by default enabled, but can be manually
+// disabled. If libomp is built with -DKMP_STATIC_STEAL_ENABLED=0, pass the
+// same flag to the tests (for example through OPENMP_TEST_FLAGS).
+#ifndef KMP_STATIC_STEAL_ENABLED
+#define KMP_STATIC_STEAL_ENABLED 1
+#endif
+
+// These definitions need to match kmp_sched_t in kmp.h.
+#ifndef KMP_SCHED_TYPE_DEFINED
+#define KMP_SCHED_TYPE_DEFINED
+typedef enum kmp_sched {
+  kmp_sched_lower = 0,
+  kmp_sched_static = 1,
+  kmp_sched_dynamic = 2,
+  kmp_sched_guided = 3,
+  kmp_sched_auto = 4,
+  kmp_sched_upper_std = 5,
+  kmp_sched_lower_ext = 100,
+  kmp_sched_trapezoidal = 101,
+#if KMP_STATIC_STEAL_ENABLED
+  kmp_sched_static_steal = 102,
+#endif
+  kmp_sched_upper,
+  kmp_sched_default = kmp_sched_static,
+  kmp_sched_monotonic = 0x80000000
+} kmp_sched_t;
+#endif
+
+// ---------------------------------------------------------------------------
+
+int main() {
+  const int chunk = 5;
+  int err = 0;
+  unsigned k;
+
+  // Visit every kind that __kmp_set_schedule() accepts: the standard kinds
+  // between lower and upper_std, and the extension kinds between lower_ext
+  // and upper.
+  for (k = kmp_sched_lower + 1; k < kmp_sched_upper; ++k) {
+    omp_sched_t kind_get;
+    int chunk_get;
+
+    if (k >= kmp_sched_upper_std && k <= kmp_sched_lower_ext) {
+      continue;
+    }
+
+#ifdef DEBUG
+    printf("checking kind %u\n", k);
+#endif
+
+    omp_set_schedule((omp_sched_t)k, chunk);
+    omp_get_schedule(&kind_get, &chunk_get);
+
+    // Check kind and chunk match.
+    // The chunk size is ignored for auto, so allow a mismatched chunk size.
+    if (kind_get != (omp_sched_t)k ||
+        (k != kmp_sched_auto && chunk_get != chunk)) {
+      printf("Error: kind %u: schedule: (%d, %d) is not equal to (%u, %d)\n", k,
+             (int)kind_get, chunk_get, k, chunk);
+      ++err;
+    }
+  }
+
+  if (err > 0) {
+    printf("Failed\n");
+    return 1;
+  }
+  printf("Passed\n");
+  return 0;
+}

diff  --git a/openmp/runtime/test/worksharing/for/kmp_sched_static_steal_ordered.c b/openmp/runtime/test/worksharing/for/kmp_sched_static_steal_ordered.c
new file mode 100644
index 0000000000000..d92d1101c7f41
--- /dev/null
+++ b/openmp/runtime/test/worksharing/for/kmp_sched_static_steal_ordered.c
@@ -0,0 +1,63 @@
+// RUN: %libomp-compile-and-run
+
+// Tests that an ordered loop with schedule(runtime) when the run-time
+// schedule is set to static_steal with omp_set_schedule(), does not
+// use the unordered static-steal scheduling nor hang.
+// Such loops must fall back to dynamic, as they do with the environment
+// variable OMP_SCHEDULE=static_steal.
+
+#include <omp.h>
+#include "omp_testsuite.h"
+
+// ---------------------------------------------------------------------------
+// Definition copied from OpenMP RTL (kmp_sched_t in kmp.h).
+enum { kmp_sched_static_steal = 102 };
+// End of definition copied from OpenMP RTL.
+// ---------------------------------------------------------------------------
+
+static int last_i = 0;
+
+/* Utility function to check that i is increasing monotonically
+   with each call */
+static int check_i_islarger(int i) {
+  int islarger;
+  islarger = (i > last_i);
+  last_i = i;
+  return (islarger);
+}
+
+int test_static_steal_ordered() {
+  int sum;
+  int is_larger = 1;
+  int known_sum;
+  int i;
+
+  last_i = 0;
+  sum = 0;
+  omp_set_schedule((omp_sched_t)kmp_sched_static_steal, 4);
+
+  // num_threads(4): static_steal needs more than one thread.
+#pragma omp parallel for schedule(runtime) ordered num_threads(4)
+  for (i = 1; i <= LOOPCOUNT; i++) {
+#pragma omp ordered
+    {
+      is_larger = check_i_islarger(i) && is_larger;
+      sum = sum + i;
+    }
+  }
+
+  known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
+  return (known_sum == sum) && is_larger;
+}
+
+int main() {
+  int i;
+  int num_failed = 0;
+
+  for (i = 0; i < REPETITIONS; i++) {
+    if (!test_static_steal_ordered()) {
+      num_failed++;
+    }
+  }
+  return num_failed;
+}
\ No newline at end of file


        


More information about the Openmp-commits mailing list