xref: /openbsd-src/gnu/gcc/libgomp/testsuite/libgomp.fortran/appendix-a/a.18.1.f90 (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert! { dg-do run }
2*404b540aSrobert! { dg-options "-ffixed-form" }
3*404b540aSrobert      REAL FUNCTION FN1(I)
4*404b540aSrobert        INTEGER I
5*404b540aSrobert        FN1 = I * 2.0
6*404b540aSrobert        RETURN
7*404b540aSrobert      END FUNCTION FN1
8*404b540aSrobert
9*404b540aSrobert      REAL FUNCTION FN2(A, B)
10*404b540aSrobert        REAL A, B
11*404b540aSrobert        FN2 = A + B
12*404b540aSrobert        RETURN
13*404b540aSrobert      END FUNCTION FN2
14*404b540aSrobert
15*404b540aSrobert      PROGRAM A18
16*404b540aSrobert      INCLUDE "omp_lib.h"     ! or USE OMP_LIB
17*404b540aSrobert      INTEGER ISYNC(256)
18*404b540aSrobert      REAL    WORK(256)
19*404b540aSrobert      REAL    RESULT(256)
20*404b540aSrobert      INTEGER IAM, NEIGHBOR
21*404b540aSrobert!$OMP PARALLEL PRIVATE(IAM, NEIGHBOR) SHARED(WORK, ISYNC) NUM_THREADS(4)
22*404b540aSrobert          IAM = OMP_GET_THREAD_NUM() + 1
23*404b540aSrobert          ISYNC(IAM) = 0
24*404b540aSrobert!$OMP BARRIER
25*404b540aSrobert!     Do computation into my portion of work array
26*404b540aSrobert          WORK(IAM) = FN1(IAM)
27*404b540aSrobert!     Announce that I am done with my work.
28*404b540aSrobert!     The first flush ensures that my work is made visible before
29*404b540aSrobert!     synch. The second flush ensures that synch is made visible.
30*404b540aSrobert!$OMP FLUSH(WORK,ISYNC)
31*404b540aSrobert       ISYNC(IAM) = 1
32*404b540aSrobert!$OMP FLUSH(ISYNC)
33*404b540aSrobert
34*404b540aSrobert!      Wait until neighbor is done. The first flush ensures that
35*404b540aSrobert!      synch is read from memory, rather than from the temporary
36*404b540aSrobert!      view of memory. The second flush ensures that work is read
37*404b540aSrobert!      from memory, and is done so after the while loop exits.
38*404b540aSrobert       IF (IAM .EQ. 1) THEN
39*404b540aSrobert            NEIGHBOR = OMP_GET_NUM_THREADS()
40*404b540aSrobert        ELSE
41*404b540aSrobert            NEIGHBOR = IAM - 1
42*404b540aSrobert        ENDIF
43*404b540aSrobert        DO WHILE (ISYNC(NEIGHBOR) .EQ. 0)
44*404b540aSrobert!$OMP FLUSH(ISYNC)
45*404b540aSrobert        END DO
46*404b540aSrobert!$OMP FLUSH(WORK, ISYNC)
47*404b540aSrobert        RESULT(IAM) = FN2(WORK(NEIGHBOR), WORK(IAM))
48*404b540aSrobert!$OMP END PARALLEL
49*404b540aSrobert        DO I=1,4
50*404b540aSrobert          IF (I .EQ. 1) THEN
51*404b540aSrobert                NEIGHBOR = 4
52*404b540aSrobert          ELSE
53*404b540aSrobert                NEIGHBOR = I - 1
54*404b540aSrobert          ENDIF
55*404b540aSrobert          IF (RESULT(I) .NE. I * 2 + NEIGHBOR * 2) THEN
56*404b540aSrobert            CALL ABORT
57*404b540aSrobert          ENDIF
58*404b540aSrobert        ENDDO
59*404b540aSrobert        END PROGRAM A18
60