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