1 // RUN: %libomp-compile-and-run
2 // RUN: %libomp-compile && env KMP_TASKLOOP_MIN_TASKS=1 %libomp-run
3 #include <stdio.h>
4 #include <omp.h>
5 #include "omp_my_sleep.h"
6
7 #define N 4
8 #define GRAIN 10
9 #define STRIDE 3
10
11 // globals
12 int th_counter[N];
13 int counter;
14
15
16 // Compiler-generated code (emulation)
17 typedef struct ident {
18 void* dummy;
19 } ident_t;
20
21 typedef struct shar {
22 int(*pth_counter)[N];
23 int *pcounter;
24 int *pj;
25 } *pshareds;
26
27 typedef struct task {
28 pshareds shareds;
29 int(* routine)(int,struct task*);
30 int part_id;
31 // privates:
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
52 // OpenMP RTL interfaces
53 typedef unsigned long long kmp_uint64;
54 typedef long long kmp_int64;
55
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59 void
60 __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int if_val,
61 kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st,
62 int nogroup, int sched, kmp_int64 grainsize, 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
74 // User's code
task_entry(int gtid,ptask task)75 int task_entry(int gtid, ptask task)
76 {
77 pshareds pshar = task->shareds;
78 for( task->i = task->lb; task->i <= (int)task->ub; task->i += task->st ) {
79 task->th = omp_get_thread_num();
80 __kmpc_atomic_fixed4_add(NULL,gtid,pshar->pcounter,1);
81 __kmpc_atomic_fixed4_add(NULL,gtid,&((*pshar->pth_counter)[task->th]),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
main()91 int main()
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 for( i=0; i<N; ++i )
99 th_counter[i] = 0;
100 #pragma omp parallel num_threads(N)
101 {
102 #pragma omp master
103 {
104 int gtid = __kmpc_global_thread_num(NULL);
105 /*
106 * This is what the OpenMP runtime calls correspond to:
107 #pragma omp taskloop num_tasks(N) lastprivate(j)
108 for( i=0; i<N*GRAIN*STRIDE-1; i+=STRIDE )
109 {
110 int th = omp_get_thread_num();
111 #pragma omp atomic
112 counter++;
113 #pragma omp atomic
114 th_counter[th]++;
115 j = i;
116 }
117 */
118 task = __kmpc_omp_task_alloc(NULL,gtid,1,sizeof(struct task),sizeof(struct shar),&task_entry);
119 psh = task->shareds;
120 psh->pth_counter = &th_counter;
121 psh->pcounter = &counter;
122 psh->pj = &j;
123 task->lb = 0;
124 task->ub = N*GRAIN*STRIDE-2;
125 task->st = STRIDE;
126
127 __kmpc_taskloop(
128 NULL, // location
129 gtid, // gtid
130 task, // task structure
131 1, // if clause value
132 &task->lb, // lower bound
133 &task->ub, // upper bound
134 STRIDE, // loop increment
135 0, // 1 if nogroup specified
136 2, // schedule type: 0-none, 1-grainsize, 2-num_tasks
137 N, // schedule value (ignored for type 0)
138 (void*)&__task_dup_entry // tasks duplication routine
139 );
140 } // end master
141 } // end parallel
142 // check results
143 if( j != N*GRAIN*STRIDE-STRIDE ) {
144 printf("Error in lastprivate, %d != %d\n",j,N*GRAIN*STRIDE-STRIDE);
145 return 1;
146 }
147 if( counter != N*GRAIN ) {
148 printf("Error, counter %d != %d\n",counter,N*GRAIN);
149 return 1;
150 }
151 for( i=0; i<N; ++i ) {
152 if( th_counter[i] % GRAIN ) {
153 printf("Error, th_counter[%d] = %d\n",i,th_counter[i]);
154 return 1;
155 }
156 }
157 printf("passed\n");
158 return 0;
159 }
160