! { dg-do run } ! { dg-options "-ffixed-form" } REAL FUNCTION FN1(I) INTEGER I FN1 = I * 2.0 RETURN END FUNCTION FN1 REAL FUNCTION FN2(A, B) REAL A, B FN2 = A + B RETURN END FUNCTION FN2 PROGRAM A18 INCLUDE "omp_lib.h" ! or USE OMP_LIB INTEGER ISYNC(256) REAL WORK(256) REAL RESULT(256) INTEGER IAM, NEIGHBOR !$OMP PARALLEL PRIVATE(IAM, NEIGHBOR) SHARED(WORK, ISYNC) NUM_THREADS(4) IAM = OMP_GET_THREAD_NUM() + 1 ISYNC(IAM) = 0 !$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. !$OMP FLUSH(WORK,ISYNC) ISYNC(IAM) = 1 !$OMP FLUSH(ISYNC) ! Wait until neighbor is done. 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. IF (IAM .EQ. 1) THEN NEIGHBOR = OMP_GET_NUM_THREADS() ELSE NEIGHBOR = IAM - 1 ENDIF DO WHILE (ISYNC(NEIGHBOR) .EQ. 0) !$OMP FLUSH(ISYNC) END DO !$OMP FLUSH(WORK, ISYNC) RESULT(IAM) = FN2(WORK(NEIGHBOR), WORK(IAM)) !$OMP END PARALLEL DO I=1,4 IF (I .EQ. 1) THEN NEIGHBOR = 4 ELSE NEIGHBOR = I - 1 ENDIF IF (RESULT(I) .NE. I * 2 + NEIGHBOR * 2) THEN CALL ABORT ENDIF ENDDO END PROGRAM A18