xref: /llvm-project/openmp/runtime/test/tasking/kmp_taskloop_5.c (revision 540007b42701b5ac9adba076824bfd648a265413)
1 // RUN: %libomp-compile-and-run
2 // RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run
3 
4 #include <stdio.h>
5 #include <omp.h>
6 #include "omp_my_sleep.h"
7 
8 #define N 4
9 #define ST 3
10 #define UB 118
11 #define LB 0
12 
13 // globals
14 int counter;
15 int task_count;
16 
17 // Compiler-generated code (emulation)
18 typedef struct ident {
19   void* dummy;
20 } ident_t;
21 
22 typedef struct shar {
23   int *pcounter;
24   int *pj;
25   int *ptask_count;
26 } *pshareds;
27 
28 typedef struct task {
29   pshareds shareds;
30   int(* routine)(int,struct task*);
31   int part_id;
32   unsigned long long lb; // library always uses ULONG
33   unsigned long long ub;
34   int st;
35   int last;
36   int i;
37   int j;
38   int th;
39 } *ptask, kmp_task_t;
40 
41 typedef int(* task_entry_t)( int, ptask );
42 
43 void
__task_dup_entry(ptask task_dst,ptask task_src,int lastpriv)44 __task_dup_entry(ptask task_dst, ptask task_src, int lastpriv)
45 {
46 // setup lastprivate flag
47   task_dst->last = lastpriv;
48 // could be constructor calls here...
49 }
50 
51 // OpenMP RTL interfaces
52 typedef unsigned long long kmp_uint64;
53 typedef long long kmp_int64;
54 
55 #ifdef __cplusplus
56 extern "C" {
57 #endif
58 void
59 __kmpc_taskloop_5(ident_t *loc, int gtid, kmp_task_t *task, int if_val,
60                   kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
61                   int nogroup, int sched, kmp_int64 grainsize, int modifier,
62                   void *task_dup);
63 ptask
64 __kmpc_omp_task_alloc(ident_t *loc, int gtid, int flags,
65                       size_t sizeof_kmp_task_t, size_t sizeof_shareds,
66                       task_entry_t task_entry);
67 void __kmpc_atomic_fixed4_add(void *id_ref, int gtid, int * lhs, int rhs);
68 int  __kmpc_global_thread_num(void *id_ref);
69 #ifdef __cplusplus
70 }
71 #endif
72 
73 // User's code
task_entry(int gtid,ptask task)74 int task_entry(int gtid, ptask task)
75 {
76   pshareds pshar = task->shareds;
77   __kmpc_atomic_fixed4_add(NULL, gtid, pshar->ptask_count, 1);
78 
79   for (task->i = task->lb; task->i <= (int)task->ub; task->i += task->st) {
80     task->th = omp_get_thread_num();
81     __kmpc_atomic_fixed4_add(NULL,gtid,pshar->pcounter,1);
82     task->j = task->i;
83   }
84   my_sleep( 0.1 ); // sleep 100 ms in order to allow other threads to steal tasks
85   if (task->last) {
86     *(pshar->pj) = task->j; // lastprivate
87   }
88   return 0;
89 }
90 
task_loop(int sched_type,int sched_val,int modifier)91 void task_loop(int sched_type, int sched_val, int modifier)
92 {
93   int i, j, gtid = __kmpc_global_thread_num(NULL);
94   ptask task;
95   pshareds psh;
96   omp_set_dynamic(0);
97   counter = 0;
98   task_count = 0;
99   #pragma omp parallel num_threads(N)
100   {
101     #pragma omp master
102     {
103       int gtid = __kmpc_global_thread_num(NULL);
104       task = __kmpc_omp_task_alloc(NULL, gtid, 1, sizeof(struct task),
105                                    sizeof(struct shar), &task_entry);
106       psh = task->shareds;
107       psh->pcounter = &counter;
108       psh->ptask_count = &task_count;
109       psh->pj = &j;
110       task->lb = LB;
111       task->ub = UB;
112       task->st = ST;
113 
114       __kmpc_taskloop_5(
115         NULL,             // location
116         gtid,             // gtid
117         task,             // task structure
118         1,                // if clause value
119         &task->lb,        // lower bound
120         &task->ub,        // upper bound
121         ST,               // loop increment
122         0,                // 1 if nogroup specified
123         sched_type,       // schedule type: 0-none, 1-grainsize, 2-num_tasks
124         sched_val,        // schedule value (ignored for type 0)
125         modifier,         // strict modifier
126         (void*)&__task_dup_entry // tasks duplication routine
127       );
128     } // end master
129   } // end parallel
130 // check results
131   int tc;
132   if (ST == 1) { // most common case
133     tc = UB - LB + 1;
134   } else if (ST < 0) {
135     tc = (LB - UB) / (-ST) + 1;
136   } else { // ST > 0
137     tc = (UB - LB) / ST + 1;
138   }
139   int count;
140   if (sched_type == 1) {
141     count = (sched_val > tc) ? 1 : (tc + sched_val - 1) / sched_val;
142   } else {
143     count = (sched_val > tc) ? tc : sched_val;
144   }
145   if (j != LB + (tc - 1) * ST) {
146     printf("Error in lastprivate, %d != %d\n", j, LB + (tc - 1) * ST);
147     exit(1);
148   }
149   if (counter != tc) {
150     printf("Error, counter %d != %d\n", counter, tc);
151     exit(1);
152   }
153   if (task_count != count) {
154     printf("Error, task count %d != %d\n", task_count, count);
155     exit(1);
156   }
157 }
158 
main(int argc,char * argv[])159 int main(int argc, char *argv[]) {
160   task_loop(1, 6, 1); // create 7 tasks
161   task_loop(2, 6, 1); // create 6 tasks
162   task_loop(1, 50, 1); // create 1 task
163   task_loop(2, 50, 1); // create 40 tasks
164 
165   printf("Test passed\n");
166   return 0;
167 }
168