/* { dg-do run } */ #include #include extern void abort (void); #define NUMBER_OF_THREADS 4 int synch[NUMBER_OF_THREADS]; int work[NUMBER_OF_THREADS]; int result[NUMBER_OF_THREADS]; int fn1 (int i) { return i * 2; } int fn2 (int a, int b) { return a + b; } int main () { int i, iam, neighbor; omp_set_num_threads (NUMBER_OF_THREADS); #pragma omp parallel private(iam,neighbor) shared(work,synch) { iam = omp_get_thread_num (); synch[iam] = 0; #pragma omp barrier /*Do computation into my portion of work array */ work[iam] = fn1 (iam); /* Announce that I am done with my work. The first flush * ensures that my work is made visible before synch. * The second flush ensures that synch is made visible. */ #pragma omp flush(work,synch) synch[iam] = 1; #pragma omp flush(synch) /* Wait for neighbor. The first flush ensures that synch is read * from memory, rather than from the temporary view of memory. * The second flush ensures that work is read from memory, and * is done so after the while loop exits. */ neighbor = (iam > 0 ? iam : omp_get_num_threads ()) - 1; while (synch[neighbor] == 0) { #pragma omp flush(synch) } #pragma omp flush(work,synch) /* Read neighbor's values of work array */ result[iam] = fn2 (work[neighbor], work[iam]); } /* output result here */ for (i = 0; i < NUMBER_OF_THREADS; i++) { neighbor = (i > 0 ? i : NUMBER_OF_THREADS) - 1; if (result[i] != i * 2 + neighbor * 2) abort (); } return 0; }