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
12int th_counter[N];
13int counter;
14
15
16// Compiler-generated code (emulation)
17typedef struct ident {
18 void* dummy;
19} ident_t;
20
21typedef struct shar {
22 int(*pth_counter)[N];
23 int *pcounter;
24 int *pj;
25} *pshareds;
26
27typedef 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
41typedef int(* task_entry_t)( int, ptask );
42
43void
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
53typedef unsigned long long kmp_uint64;
54typedef long long kmp_int64;
55
56#ifdef __cplusplus
57extern "C" {
58#endif
59void
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 );
63ptask
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 );
67void __kmpc_atomic_fixed4_add(void *id_ref, int gtid, int * lhs, int rhs);
68int __kmpc_global_thread_num(void *id_ref);
69#ifdef __cplusplus
70}
71#endif
72
73
74// User's code
75int 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,lhs: pshar->pcounter,rhs: 1);
81 __kmpc_atomic_fixed4_add(NULL,gtid,lhs: &((*pshar->pth_counter)[task->th]),rhs: 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
91int 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,flags: 1,sizeof_kmp_task_t: sizeof(struct task),sizeof_shareds: sizeof(struct shar),task_entry: &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 if_val: 1, // if clause value
132 lb: &task->lb, // lower bound
133 ub: &task->ub, // upper bound
134 STRIDE, // loop increment
135 nogroup: 0, // 1 if nogroup specified
136 sched: 2, // schedule type: 0-none, 1-grainsize, 2-num_tasks
137 N, // schedule value (ignored for type 0)
138 task_dup: (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(format: "Error in lastprivate, %d != %d\n",j,N*GRAIN*STRIDE-STRIDE);
145 return 1;
146 }
147 if( counter != N*GRAIN ) {
148 printf(format: "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(format: "Error, th_counter[%d] = %d\n",i,th_counter[i]);
154 return 1;
155 }
156 }
157 printf(format: "passed\n");
158 return 0;
159}
160

source code of openmp/runtime/test/tasking/kmp_taskloop.c