1 | // RUN: %libomp-compile-and-run |
2 | #include <stdio.h> |
3 | #include <stdlib.h> |
4 | #include "omp_testsuite.h" |
5 | #include "omp_my_sleep.h" |
6 | |
7 | #define CFSMAX_SIZE 1000 |
8 | #define MAX_TIME 0.01 |
9 | |
10 | #ifdef SLEEPTIME |
11 | #undef SLEEPTIME |
12 | #define SLEEPTIME 0.0005 |
13 | #endif |
14 | |
15 | #define VERBOSE 0 |
16 | |
17 | int test_omp_for_schedule_static_3() |
18 | { |
19 | int threads; |
20 | int i,lasttid; |
21 | |
22 | int * tids; |
23 | int * tids2; |
24 | int notout; |
25 | int maxiter; |
26 | int chunk_size; |
27 | |
28 | int counter = 0; |
29 | int tmp_count=1; |
30 | int lastthreadsstarttid = -1; |
31 | int result = 1; |
32 | chunk_size = 7; |
33 | |
34 | tids = (int *) malloc (size: sizeof (int) * (CFSMAX_SIZE + 1)); |
35 | notout = 1; |
36 | maxiter = 0; |
37 | |
38 | #pragma omp parallel shared(tids,counter) |
39 | { /* begin of parallel*/ |
40 | #pragma omp single |
41 | { |
42 | threads = omp_get_num_threads (); |
43 | } /* end of single */ |
44 | } /* end of parallel */ |
45 | |
46 | /* Ensure that at least two threads are created */ |
47 | if (threads < 2) { |
48 | omp_set_num_threads(2); |
49 | threads = 2; |
50 | } |
51 | fprintf (stderr,format: "Using an internal count of %d\nUsing a" |
52 | " specified chunksize of %d\n" , CFSMAX_SIZE, chunk_size); |
53 | tids[CFSMAX_SIZE] = -1; /* setting endflag */ |
54 | |
55 | #pragma omp parallel shared(tids) |
56 | { /* begin of parallel */ |
57 | double count; |
58 | int tid; |
59 | int j; |
60 | |
61 | tid = omp_get_thread_num (); |
62 | |
63 | #pragma omp for nowait schedule(static,chunk_size) |
64 | for(j = 0; j < CFSMAX_SIZE; ++j) { |
65 | count = 0.; |
66 | #pragma omp flush(maxiter) |
67 | if (j > maxiter) { |
68 | #pragma omp critical |
69 | { |
70 | maxiter = j; |
71 | } |
72 | } |
73 | /*printf ("thread %d sleeping\n", tid);*/ |
74 | while (notout && (count < MAX_TIME) && (maxiter == j)) { |
75 | #pragma omp flush(maxiter,notout) |
76 | my_sleep (SLEEPTIME); |
77 | count += SLEEPTIME; |
78 | printf(format: "." ); |
79 | } |
80 | #ifdef VERBOSE |
81 | if (count > 0.) printf(format: " waited %lf s\n" , count); |
82 | #endif |
83 | /*printf ("thread %d awake\n", tid);*/ |
84 | tids[j] = tid; |
85 | #ifdef VERBOSE |
86 | printf(format: "%d finished by %d\n" ,j,tid); |
87 | #endif |
88 | } /* end of omp parallel for */ |
89 | |
90 | notout = 0; |
91 | #pragma omp flush(maxiter,notout) |
92 | } /* end of parallel */ |
93 | |
94 | /**** analysing the data in array tids ****/ |
95 | |
96 | lasttid = tids[0]; |
97 | tmp_count = 0; |
98 | |
99 | for (i = 0; i < CFSMAX_SIZE + 1; ++i) { |
100 | /* If the work was done by the same thread |
101 | increase tmp_count by one. */ |
102 | if (tids[i] == lasttid) { |
103 | tmp_count++; |
104 | #ifdef VERBOSE |
105 | fprintf (stderr, format: "%d: %d \n" , i, tids[i]); |
106 | #endif |
107 | continue; |
108 | } |
109 | |
110 | /* Check if the next thread had has the right thread number. |
111 | * When finding threadnumber -1 the end should be reached. |
112 | */ |
113 | if (tids[i] == (lasttid + 1) % threads || tids[i] == -1) { |
114 | /* checking for the right chunk size */ |
115 | if (tmp_count == chunk_size) { |
116 | tmp_count = 1; |
117 | lasttid = tids[i]; |
118 | #ifdef VERBOSE |
119 | fprintf (stderr, format: "OK\n" ); |
120 | #endif |
121 | } else { |
122 | /* If the chunk size was wrong, check if the end was reached */ |
123 | if (tids[i] == -1) { |
124 | if (i == CFSMAX_SIZE) { |
125 | fprintf (stderr, format: "Last thread had chunk size %d\n" , |
126 | tmp_count); |
127 | break; |
128 | } else { |
129 | fprintf (stderr, format: "ERROR: Last thread (thread with" |
130 | " number -1) was found before the end.\n" ); |
131 | result = 0; |
132 | } |
133 | } else { |
134 | fprintf (stderr, format: "ERROR: chunk size was %d. (assigned" |
135 | " was %d)\n" , tmp_count, chunk_size); |
136 | result = 0; |
137 | } |
138 | } |
139 | } else { |
140 | fprintf(stderr, format: "ERROR: Found thread with number %d (should be" |
141 | " inbetween 0 and %d)." , tids[i], threads - 1); |
142 | result = 0; |
143 | } |
144 | #ifdef VERBOSE |
145 | fprintf (stderr, format: "%d: %d \n" , i, tids[i]); |
146 | #endif |
147 | } |
148 | |
149 | /* Now we check if several loop regions in one parallel region have the |
150 | * same logical assignment of chunks to threads. We use the nowait |
151 | * clause to increase the probability to get an error. */ |
152 | |
153 | /* First we allocate some more memory */ |
154 | free (ptr: tids); |
155 | tids = (int *) malloc (sizeof (int) * LOOPCOUNT); |
156 | tids2 = (int *) malloc (sizeof (int) * LOOPCOUNT); |
157 | |
158 | #pragma omp parallel |
159 | { |
160 | { |
161 | int n; |
162 | #pragma omp for schedule(static) nowait |
163 | for (n = 0; n < LOOPCOUNT; n++) { |
164 | if (LOOPCOUNT == n + 1 ) |
165 | my_sleep(SLEEPTIME); |
166 | |
167 | tids[n] = omp_get_thread_num(); |
168 | } |
169 | } |
170 | { |
171 | int m; |
172 | #pragma omp for schedule(static) nowait |
173 | for (m = 1; m <= LOOPCOUNT; m++) { |
174 | tids2[m-1] = omp_get_thread_num(); |
175 | } |
176 | } |
177 | } |
178 | |
179 | for (i = 0; i < LOOPCOUNT; i++) |
180 | if (tids[i] != tids2[i]) { |
181 | fprintf (stderr, "Chunk no. %d was assigned once to thread %d and" |
182 | " later to thread %d.\n" , i, tids[i],tids2[i]); |
183 | result = 0; |
184 | } |
185 | |
186 | free (ptr: tids); |
187 | free (ptr: tids2); |
188 | return result; |
189 | } |
190 | |
191 | int main() |
192 | { |
193 | int i; |
194 | int num_failed=0; |
195 | |
196 | for (i = 0; i < REPETITIONS; i++) { |
197 | if(!test_omp_for_schedule_static_3()) { |
198 | num_failed++; |
199 | } |
200 | } |
201 | return num_failed; |
202 | } |
203 | |