http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48894

           Summary: generic omp_get_ancestor_thread_num(l(i)) produces
                    incorrect output
           Product: gcc
           Version: 4.5.3
            Status: UNCONFIRMED
          Severity: minor
          Priority: P3
         Component: fortran
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: lo...@cray.com


I wavered between "minor" and "trivial" on this one, but the OpenMP testers
came up with this end case.  It seems very unlikely to arise in a real program,
but is also probably easy to fix in the library code.

> cat test1.f90
!  derived from OpenMP test OMP3f/F03_3_2_17_1a.F90
!  See - OpenMP 3.0 API spec, p. 131, lines 2-9.
program F03_3_2_17_1a
   use omp_lib
   implicit none

   logical, parameter :: FALSE=.false.
   logical, parameter :: TRUE=.true.
   integer, parameter :: ZERO=0
   integer, parameter :: TWO=2
   integer*4, parameter :: ZERO4=0
   integer, parameter :: MHUGE4=-huge(ZERO4)
   integer :: level(10) =            &
     (/-huge(ZERO), -huge(ZERO)+3, MHUGE4, -1, 0, 1, 2, 3, 4, huge(ZERO)/)

   integer :: i
   integer, dimension(10) :: expected_ancestor_thread_num,        &
                       actual_ancestor_thread_num = (/(-huge(i), i=1,10)/)

   call omp_set_dynamic( FALSE )
   call omp_set_nested( TRUE )
   call omp_set_max_active_levels(TWO) ! one inactive parallel region

   ! if the implementation supports nested parallelism, then expected value of
   ! omp_get_ancestor_thread(2) == 1, else 0
   if (omp_get_nested()) then
      expected_ancestor_thread_num = (/-1, -1, -1, -1, 0, 2, 1, 0, -1, -1/)
   else
      expected_ancestor_thread_num = (/-1, -1, -1, -1, 0, 2, 0, 0, -1, -1/)
   end if

   !$omp parallel num_threads(3)    ! nest level 1
   if (omp_get_thread_num() == 2) then ! ancestor thread num = 2 at this level
      !$omp parallel num_threads(2) ! nest level 2
      if ((omp_get_nested() .and. omp_get_thread_num() == 1) .or. &
          (omp_get_nested() .eqv. .false. .and. omp_get_thread_num() == 0))
then
         !$omp parallel             ! nest level 3
         ! inactive parallel region due to max-active-level-var == 2,
         ! so should be executed by only one thread
         do i = 1, size(level)
            actual_ancestor_thread_num(i)
=omp_get_ancestor_thread_num(level(i))
         end do
         !$omp end parallel
      end if 
      !$omp end parallel
   end if
   !$omp end parallel

   do i = 1, size(level)
       print *, 'level(i)=', level(i)
      if (actual_ancestor_thread_num(i) /= expected_ancestor_thread_num(i))
then
         print *, "FAIL - omp_get_ancestor_thread_num(", level(i), ")", &
                  " == ", actual_ancestor_thread_num(i), " (expected ", & 
                  expected_ancestor_thread_num(i), ")"
      end if 
   end do

end program F03_3_2_17_1a

> gfortran -fopenmp -fdefault-integer-8 -fdefault-real-8 test1.f90
> ./a.out 
level(i)= -9223372036854775807
 FAIL - omp_get_ancestor_thread_num( -9223372036854775807 ) ==                 
   2  (expected                    -1 )
 level(i)= -9223372036854775804
 level(i)=          -2147483647
 level(i)=                   -1
 level(i)=                    0
 level(i)=                    1
 level(i)=                    2
 level(i)=                    3
 level(i)=                    4
 level(i)=  9223372036854775807
> 


>From the OpenMP spec from page 131, lines 2-5:

"The omp_get_ancestor_thread_num routine returns the thread number of the
ancestor at a given nest level of the current thread or the thread number of
the current thread. If the requested nest level is outside the range of 0 and
the nest level of the current thread, as returned by the omp_get_level routine,
the routine returns -1."

The routine omp_get_level() always returns a result that is 0 or a positive
integer. So any negative argument to omp_get_ancestor_thread_num that is
negative is outside the range 0..omp_get_level(), so the result should be -1.

I suspect what is happening here is that the computation inside
omp_get_ancestor_thread_num (n) involves a subtract of n - num_threads which
wraps around because the value of n is at the limit of representable integers.
Note that the second trial input is different by 3 (and num_threads is 3), so
it just barely avoids the wrap.

Reply via email to