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