xref: /openbsd-src/gnu/gcc/libgomp/testsuite/libgomp.c/appendix-a/a.18.1.c (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert /* { dg-do run } */
2*404b540aSrobert 
3*404b540aSrobert #include <omp.h>
4*404b540aSrobert #include <stdio.h>
5*404b540aSrobert 
6*404b540aSrobert extern void abort (void);
7*404b540aSrobert 
8*404b540aSrobert #define NUMBER_OF_THREADS 4
9*404b540aSrobert 
10*404b540aSrobert int synch[NUMBER_OF_THREADS];
11*404b540aSrobert int work[NUMBER_OF_THREADS];
12*404b540aSrobert int result[NUMBER_OF_THREADS];
13*404b540aSrobert int
fn1(int i)14*404b540aSrobert fn1 (int i)
15*404b540aSrobert {
16*404b540aSrobert   return i * 2;
17*404b540aSrobert }
18*404b540aSrobert 
19*404b540aSrobert int
fn2(int a,int b)20*404b540aSrobert fn2 (int a, int b)
21*404b540aSrobert {
22*404b540aSrobert   return a + b;
23*404b540aSrobert }
24*404b540aSrobert 
25*404b540aSrobert int
main()26*404b540aSrobert main ()
27*404b540aSrobert {
28*404b540aSrobert   int i, iam, neighbor;
29*404b540aSrobert   omp_set_num_threads (NUMBER_OF_THREADS);
30*404b540aSrobert #pragma omp parallel private(iam,neighbor) shared(work,synch)
31*404b540aSrobert   {
32*404b540aSrobert     iam = omp_get_thread_num ();
33*404b540aSrobert     synch[iam] = 0;
34*404b540aSrobert #pragma omp barrier
35*404b540aSrobert     /*Do computation into my portion of work array */
36*404b540aSrobert     work[iam] = fn1 (iam);
37*404b540aSrobert     /* Announce that I am done with my work. The first flush
38*404b540aSrobert      * ensures that my work is made visible before synch.
39*404b540aSrobert      * The second flush ensures that synch is made visible.
40*404b540aSrobert      */
41*404b540aSrobert #pragma omp flush(work,synch)
42*404b540aSrobert     synch[iam] = 1;
43*404b540aSrobert #pragma omp flush(synch)
44*404b540aSrobert     /* Wait for neighbor. The first flush ensures that synch is read
45*404b540aSrobert      * from memory, rather than from the temporary view of memory.
46*404b540aSrobert      * The second flush ensures that work is read from memory, and
47*404b540aSrobert      * is done so after the while loop exits.
48*404b540aSrobert      */
49*404b540aSrobert     neighbor = (iam > 0 ? iam : omp_get_num_threads ()) - 1;
50*404b540aSrobert     while (synch[neighbor] == 0)
51*404b540aSrobert       {
52*404b540aSrobert #pragma omp flush(synch)
53*404b540aSrobert       }
54*404b540aSrobert #pragma omp flush(work,synch)
55*404b540aSrobert     /* Read neighbor's values of work array */
56*404b540aSrobert     result[iam] = fn2 (work[neighbor], work[iam]);
57*404b540aSrobert   }
58*404b540aSrobert   /* output result here */
59*404b540aSrobert   for (i = 0; i < NUMBER_OF_THREADS; i++)
60*404b540aSrobert     {
61*404b540aSrobert       neighbor = (i > 0 ? i : NUMBER_OF_THREADS) - 1;
62*404b540aSrobert       if (result[i] != i * 2 + neighbor * 2)
63*404b540aSrobert 	abort ();
64*404b540aSrobert     }
65*404b540aSrobert 
66*404b540aSrobert   return 0;
67*404b540aSrobert }
68