1 | // RUN: %libomp-compile-and-run |
2 | #include <stdio.h> |
3 | #include "omp_testsuite.h" |
4 | |
5 | /* |
6 | * This test will hang if the nowait is not working properly. |
7 | * |
8 | * It relies on a thread skipping to the second for construct to |
9 | * release the threads in the first for construct. |
10 | * |
11 | * Also, we use static scheduling to guarantee that one |
12 | * thread will make it to the second for construct. |
13 | */ |
14 | volatile int release; |
15 | volatile int count; |
16 | |
17 | void wait_for_release_then_increment(int rank) |
18 | { |
19 | fprintf(stderr, format: "Thread nr %d enters first for construct" |
20 | " and waits.\n" , rank); |
21 | while (release == 0); |
22 | #pragma omp atomic |
23 | count++; |
24 | } |
25 | |
26 | void release_and_increment(int rank) |
27 | { |
28 | fprintf(stderr, format: "Thread nr %d sets release to 1\n" , rank); |
29 | release = 1; |
30 | #pragma omp atomic |
31 | count++; |
32 | } |
33 | |
34 | int test_omp_for_nowait() |
35 | { |
36 | release = 0; |
37 | count = 0; |
38 | |
39 | #pragma omp parallel num_threads(4) |
40 | { |
41 | int rank; |
42 | int i; |
43 | |
44 | rank = omp_get_thread_num(); |
45 | |
46 | #pragma omp for schedule(static) nowait |
47 | for (i = 0; i < 4; i++) { |
48 | if (i < 3) |
49 | wait_for_release_then_increment(rank); |
50 | else { |
51 | fprintf(stderr, format: "Thread nr %d enters first for and goes " |
52 | "immediately to the next for construct to release.\n" , rank); |
53 | #pragma omp atomic |
54 | count++; |
55 | } |
56 | } |
57 | |
58 | #pragma omp for schedule(static) |
59 | for (i = 0; i < 4; i++) { |
60 | release_and_increment(rank); |
61 | } |
62 | } |
63 | return (count==8); |
64 | } |
65 | |
66 | int main() |
67 | { |
68 | int i; |
69 | int num_failed=0; |
70 | |
71 | for(i = 0; i < REPETITIONS; i++) { |
72 | if(!test_omp_for_nowait()) { |
73 | num_failed++; |
74 | } |
75 | } |
76 | return num_failed; |
77 | } |
78 | |