xref: /llvm-project/openmp/runtime/test/worksharing/for/omp_monotonic_schedule_set_get.c (revision 71abe28e8152239e4e2be443497845eeb523139a)
1 // RUN: %libomp-compile-and-run
2 
3 // The test checks OMP 5.0 monotonic/nonmonotonic scheduling API
4 //   1. initial schedule should be (static,0)
5 //   2. omp_get_schedule() should return the schedule set by omp_set_schedule()
6 //   3. schedules set inside parallel should not impact outer tasks' schedules
7 
8 #include <stdio.h>
9 #ifndef __INTEL_COMPILER
10 #define _OMPIMP
11 #endif
12 
13 #define NO_MODIFIERS ((omp_sched_t)0)
14 
15 #include "omp.h"
16 
17 int global = 0;
18 int err = 0;
19 
sched_append_modifiers(omp_sched_t sched,omp_sched_t modifiers)20 omp_sched_t sched_append_modifiers(omp_sched_t sched, omp_sched_t modifiers) {
21   return (omp_sched_t)((int)sched | (int)modifiers);
22 }
23 
sched_without_modifiers(omp_sched_t sched)24 omp_sched_t sched_without_modifiers(omp_sched_t sched) {
25   return (omp_sched_t)((int)sched & ~((int)omp_sched_monotonic));
26 }
27 
sched_has_modifiers(omp_sched_t sched,omp_sched_t modifiers)28 int sched_has_modifiers(omp_sched_t sched, omp_sched_t modifiers) {
29   return (((int)sched & ((int)omp_sched_monotonic)) > 0);
30 }
31 
32 // check that sched = hope | modifiers
check_schedule(const char * extra,const omp_sched_t sched,int chunk,omp_sched_t hope_sched,int hope_chunk)33 void check_schedule(const char *extra, const omp_sched_t sched, int chunk,
34                     omp_sched_t hope_sched, int hope_chunk) {
35 
36   if (sched != hope_sched || chunk != hope_chunk) {
37 #pragma omp atomic
38     ++err;
39     printf("Error: %s: schedule: (%d, %d) is not equal to (%d, %d)\n", extra,
40            (int)hope_sched, hope_chunk, (int)sched, chunk);
41   }
42 }
43 
main()44 int main() {
45   int i;
46   int chunk;
47   omp_sched_t sched0;
48 
49   omp_set_dynamic(0);
50   omp_set_nested(1);
51 
52   // check serial region
53   omp_get_schedule(&sched0, &chunk);
54 #ifdef DEBUG
55   printf("initial: (%d, %d)\n", sched0, chunk);
56 #endif
57   check_schedule("initial", omp_sched_static, 0, sched0, chunk);
58   // set schedule before the parallel, check it after the parallel
59   omp_set_schedule(
60       sched_append_modifiers(omp_sched_dynamic, omp_sched_monotonic), 3);
61 
62 #pragma omp parallel num_threads(3) private(i)
63   {
64     omp_sched_t n_outer_set, n_outer_get;
65     int c_outer;
66     int tid = omp_get_thread_num();
67 
68     n_outer_set = sched_append_modifiers((omp_sched_t)(tid + 1),
69                                          omp_sched_monotonic); // 1, 2, 3
70 
71     // check outer parallel region
72     // master sets (static, unchunked), others - (dynamic, 1), (guided, 2)
73     // set schedule before inner parallel, check it after the parallel
74     omp_set_schedule(n_outer_set, tid);
75 
76 // Make sure this schedule doesn't crash the runtime
77 #pragma omp for
78     for (i = 0; i < 100; ++i) {
79 #pragma omp atomic
80       global++;
81     }
82 
83 #pragma omp parallel num_threads(3) private(i) shared(n_outer_set)
84     {
85       omp_sched_t n_inner_set, n_inner_get;
86       int c_inner_set, c_inner_get;
87       int tid = omp_get_thread_num();
88 
89       n_inner_set = (omp_sched_t)(tid + 1); // 1, 2, 3
90       c_inner_set = (int)(n_outer_set)*10 +
91                     (int)n_inner_set; // 11, 12, 13, 21, 22, 23, 31, 32, 33
92       n_inner_set = sched_append_modifiers(n_inner_set, omp_sched_monotonic);
93       // schedules set inside parallel should not impact outer schedules
94       omp_set_schedule(n_inner_set, c_inner_set);
95 
96 // Make sure this schedule doesn't crash the runtime
97 #pragma omp for
98       for (i = 0; i < 100; ++i) {
99 #pragma omp atomic
100         global++;
101       }
102 
103 #pragma omp barrier
104       omp_get_schedule(&n_inner_get, &c_inner_get);
105 #ifdef DEBUG
106       printf("inner parallel: o_th %d, i_th %d, (%d, %d)\n", n_outer_set - 1,
107              tid, n_inner_get, c_inner_get);
108 #endif
109       check_schedule("inner", n_inner_set, c_inner_set, n_inner_get,
110                      c_inner_get);
111     }
112 
113     omp_get_schedule(&n_outer_get, &c_outer);
114 #ifdef DEBUG
115     printf("outer parallel: thread %d, (%d, %d)\n", tid, n_outer_get, c_outer);
116 #endif
117     check_schedule("outer", n_outer_set, tid, n_outer_get, c_outer);
118   }
119 
120   omp_get_schedule(&sched0, &chunk);
121 #ifdef DEBUG
122   printf("after parallels: (%d, %d)\n", sched0, chunk);
123 #endif
124   check_schedule("after parallels",
125                  sched_append_modifiers(omp_sched_dynamic, omp_sched_monotonic),
126                  3, sched0, chunk);
127 
128   if (err > 0) {
129     printf("Failed\n");
130     return 1;
131   }
132   printf("Passed\n");
133   return 0;
134 }
135