xref: /llvm-project/openmp/runtime/test/tasking/kmp_taskloop.c (revision aa5cdafa405e32956226dcc1cacd86430ac9ad1a)
1283a215cSJonathan Peyton // RUN: %libomp-compile-and-run
2*93e17cfeSJonathan Peyton // RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run
3283a215cSJonathan Peyton #include <stdio.h>
4283a215cSJonathan Peyton #include <omp.h>
5283a215cSJonathan Peyton #include "omp_my_sleep.h"
6283a215cSJonathan Peyton 
7283a215cSJonathan Peyton #define N 4
8283a215cSJonathan Peyton #define GRAIN 10
9283a215cSJonathan Peyton #define STRIDE 3
10283a215cSJonathan Peyton 
11283a215cSJonathan Peyton // globals
12283a215cSJonathan Peyton int th_counter[N];
13283a215cSJonathan Peyton int counter;
14283a215cSJonathan Peyton 
15283a215cSJonathan Peyton 
16283a215cSJonathan Peyton // Compiler-generated code (emulation)
17283a215cSJonathan Peyton typedef struct ident {
18283a215cSJonathan Peyton     void* dummy;
19283a215cSJonathan Peyton } ident_t;
20283a215cSJonathan Peyton 
21283a215cSJonathan Peyton typedef struct shar {
22283a215cSJonathan Peyton     int(*pth_counter)[N];
23283a215cSJonathan Peyton     int *pcounter;
24283a215cSJonathan Peyton     int *pj;
25283a215cSJonathan Peyton } *pshareds;
26283a215cSJonathan Peyton 
27283a215cSJonathan Peyton typedef struct task {
28283a215cSJonathan Peyton     pshareds shareds;
29283a215cSJonathan Peyton     int(* routine)(int,struct task*);
30283a215cSJonathan Peyton     int part_id;
31283a215cSJonathan Peyton // privates:
32283a215cSJonathan Peyton     unsigned long long lb; // library always uses ULONG
33283a215cSJonathan Peyton     unsigned long long ub;
34283a215cSJonathan Peyton     int st;
35283a215cSJonathan Peyton     int last;
36283a215cSJonathan Peyton     int i;
37283a215cSJonathan Peyton     int j;
38283a215cSJonathan Peyton     int th;
39283a215cSJonathan Peyton } *ptask, kmp_task_t;
40283a215cSJonathan Peyton 
41283a215cSJonathan Peyton typedef int(* task_entry_t)( int, ptask );
42283a215cSJonathan Peyton 
43283a215cSJonathan Peyton void
__task_dup_entry(ptask task_dst,ptask task_src,int lastpriv)44283a215cSJonathan Peyton __task_dup_entry(ptask task_dst, ptask task_src, int lastpriv)
45283a215cSJonathan Peyton {
46283a215cSJonathan Peyton // setup lastprivate flag
47283a215cSJonathan Peyton     task_dst->last = lastpriv;
48283a215cSJonathan Peyton // could be constructor calls here...
49283a215cSJonathan Peyton }
50283a215cSJonathan Peyton 
51283a215cSJonathan Peyton 
52283a215cSJonathan Peyton // OpenMP RTL interfaces
53283a215cSJonathan Peyton typedef unsigned long long kmp_uint64;
54283a215cSJonathan Peyton typedef long long kmp_int64;
55283a215cSJonathan Peyton 
56283a215cSJonathan Peyton #ifdef __cplusplus
57283a215cSJonathan Peyton extern "C" {
58283a215cSJonathan Peyton #endif
59283a215cSJonathan Peyton void
60283a215cSJonathan Peyton __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int if_val,
61283a215cSJonathan Peyton                 kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
62283a215cSJonathan Peyton                 int nogroup, int sched, kmp_int64 grainsize, void *task_dup );
63283a215cSJonathan Peyton ptask
64283a215cSJonathan Peyton __kmpc_omp_task_alloc( ident_t *loc, int gtid, int flags,
65283a215cSJonathan Peyton                   size_t sizeof_kmp_task_t, size_t sizeof_shareds,
66283a215cSJonathan Peyton                   task_entry_t task_entry );
67283a215cSJonathan Peyton void __kmpc_atomic_fixed4_add(void *id_ref, int gtid, int * lhs, int rhs);
68283a215cSJonathan Peyton int  __kmpc_global_thread_num(void *id_ref);
69283a215cSJonathan Peyton #ifdef __cplusplus
70283a215cSJonathan Peyton }
71283a215cSJonathan Peyton #endif
72283a215cSJonathan Peyton 
73283a215cSJonathan Peyton 
74283a215cSJonathan Peyton // User's code
task_entry(int gtid,ptask task)75283a215cSJonathan Peyton int task_entry(int gtid, ptask task)
76283a215cSJonathan Peyton {
77283a215cSJonathan Peyton     pshareds pshar = task->shareds;
78283a215cSJonathan Peyton     for( task->i = task->lb; task->i <= (int)task->ub; task->i += task->st ) {
79283a215cSJonathan Peyton         task->th = omp_get_thread_num();
80283a215cSJonathan Peyton         __kmpc_atomic_fixed4_add(NULL,gtid,pshar->pcounter,1);
81283a215cSJonathan Peyton         __kmpc_atomic_fixed4_add(NULL,gtid,&((*pshar->pth_counter)[task->th]),1);
82283a215cSJonathan Peyton         task->j = task->i;
83283a215cSJonathan Peyton     }
84283a215cSJonathan Peyton     my_sleep( 0.1 ); // sleep 100 ms in order to allow other threads to steal tasks
85283a215cSJonathan Peyton     if( task->last ) {
86283a215cSJonathan Peyton         *(pshar->pj) = task->j; // lastprivate
87283a215cSJonathan Peyton     }
88283a215cSJonathan Peyton     return 0;
89283a215cSJonathan Peyton }
90283a215cSJonathan Peyton 
main()91283a215cSJonathan Peyton int main()
92283a215cSJonathan Peyton {
93283a215cSJonathan Peyton     int i, j, gtid = __kmpc_global_thread_num(NULL);
94283a215cSJonathan Peyton     ptask task;
95283a215cSJonathan Peyton     pshareds psh;
96283a215cSJonathan Peyton     omp_set_dynamic(0);
97283a215cSJonathan Peyton     counter = 0;
98283a215cSJonathan Peyton     for( i=0; i<N; ++i )
99283a215cSJonathan Peyton         th_counter[i] = 0;
100283a215cSJonathan Peyton     #pragma omp parallel num_threads(N)
101283a215cSJonathan Peyton     {
102283a215cSJonathan Peyton       #pragma omp master
103283a215cSJonathan Peyton       {
104283a215cSJonathan Peyton         int gtid = __kmpc_global_thread_num(NULL);
105283a215cSJonathan Peyton /*
106283a215cSJonathan Peyton  *  This is what the OpenMP runtime calls correspond to:
107283a215cSJonathan Peyton     #pragma omp taskloop num_tasks(N) lastprivate(j)
108283a215cSJonathan Peyton     for( i=0; i<N*GRAIN*STRIDE-1; i+=STRIDE )
109283a215cSJonathan Peyton     {
110283a215cSJonathan Peyton         int th = omp_get_thread_num();
111283a215cSJonathan Peyton         #pragma omp atomic
112283a215cSJonathan Peyton             counter++;
113283a215cSJonathan Peyton         #pragma omp atomic
114283a215cSJonathan Peyton             th_counter[th]++;
115283a215cSJonathan Peyton         j = i;
116283a215cSJonathan Peyton     }
117283a215cSJonathan Peyton */
118283a215cSJonathan Peyton     task = __kmpc_omp_task_alloc(NULL,gtid,1,sizeof(struct task),sizeof(struct shar),&task_entry);
119283a215cSJonathan Peyton     psh = task->shareds;
120283a215cSJonathan Peyton     psh->pth_counter = &th_counter;
121283a215cSJonathan Peyton     psh->pcounter = &counter;
122283a215cSJonathan Peyton     psh->pj = &j;
123283a215cSJonathan Peyton     task->lb = 0;
124283a215cSJonathan Peyton     task->ub = N*GRAIN*STRIDE-2;
125283a215cSJonathan Peyton     task->st = STRIDE;
126283a215cSJonathan Peyton 
127283a215cSJonathan Peyton     __kmpc_taskloop(
128283a215cSJonathan Peyton         NULL,             // location
129283a215cSJonathan Peyton         gtid,             // gtid
130283a215cSJonathan Peyton         task,             // task structure
131283a215cSJonathan Peyton         1,                // if clause value
132283a215cSJonathan Peyton         &task->lb,        // lower bound
133283a215cSJonathan Peyton         &task->ub,        // upper bound
134283a215cSJonathan Peyton         STRIDE,           // loop increment
135283a215cSJonathan Peyton         0,                // 1 if nogroup specified
136283a215cSJonathan Peyton         2,                // schedule type: 0-none, 1-grainsize, 2-num_tasks
137283a215cSJonathan Peyton         N,                // schedule value (ignored for type 0)
138283a215cSJonathan Peyton         (void*)&__task_dup_entry // tasks duplication routine
139283a215cSJonathan Peyton         );
140283a215cSJonathan Peyton       } // end master
141283a215cSJonathan Peyton     } // end parallel
142283a215cSJonathan Peyton // check results
143283a215cSJonathan Peyton     if( j != N*GRAIN*STRIDE-STRIDE ) {
144283a215cSJonathan Peyton         printf("Error in lastprivate, %d != %d\n",j,N*GRAIN*STRIDE-STRIDE);
145283a215cSJonathan Peyton         return 1;
146283a215cSJonathan Peyton     }
147283a215cSJonathan Peyton     if( counter != N*GRAIN ) {
148283a215cSJonathan Peyton         printf("Error, counter %d != %d\n",counter,N*GRAIN);
149283a215cSJonathan Peyton         return 1;
150283a215cSJonathan Peyton     }
151283a215cSJonathan Peyton     for( i=0; i<N; ++i ) {
152283a215cSJonathan Peyton         if( th_counter[i] % GRAIN ) {
153283a215cSJonathan Peyton             printf("Error, th_counter[%d] = %d\n",i,th_counter[i]);
154283a215cSJonathan Peyton             return 1;
155283a215cSJonathan Peyton         }
156283a215cSJonathan Peyton     }
157283a215cSJonathan Peyton     printf("passed\n");
158283a215cSJonathan Peyton     return 0;
159283a215cSJonathan Peyton }
160