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