!
! -*- Mode: Fortran; -*-
!
! (C) 2012 by Argonne National Laboratory.
! See COPYRIGHT in top-level directory.
!
!
! In MPI 2.2, the behavior of attributes set in one language and retrieved
! from another was defined. There are three types of attribute values:
! 1. pointer (void *): "The C type"
! 2. INTEGER : "The MPI-1 Fortran type"
! 3. INTEGER (KIND=MPI_ADDRESS_KIND) : "The MPI-2 Fortran type"
!
! All three apply to Communicator attributes, with case 2 using the
! deprecated MPI_ATTR_GET and MPI_ATTR_PUT routines. For Datatype and
! RMA Window attributes, cases 1 and 3 apply.
!
! Note, just to make this more complex, there are some reasons why an MPI
! implementation may choose to make MPI_Aint (and the corresponding
! Fortran MPI_ADDRESS_KIND) larger than a void pointer. Specifically,
! make it as large as MPI_Offset, which simplifies certain operations
! with datatypes.
!
! There are 9 cases:
! 1. C sets, C gets
! 2. C sets, Fortran INTEGER gets
! 3. C sets, Fortran ADDRESS_KIND gets
! 4. Fortran INTEGER sets, C gets
! 5. Fortran INTEGER sets, Fortran INTEGER gets
! 6. Fortran INTEGER sets, Fortran ADDRESS_KIND gets
! 7. Fortran ADDRESS_KIND sets, C gets
! 8. Fortran ADDRESS_KIND sets, Fortran INTEGER gets
! 9. Fortran ADDRESS_KIND sets, Fortran ADDRESS_KIND gets
!
! These are the basic cases. They are complicated by the fact that
! the attribute values have 3 types: void * (C interface), MPI_Fint
! (Fortran INTEGER), and MPI_Aint (Fortran ADDRESS_KIND). These
! have the following size relationships:
!
! sizeof(void *) <= sizeof(MPI_Aint)
! (For some systems, MPI_Aint is set to the same size as
! MPI_Offset, and may be larger than a void *.)
! sizeof(MPI_Fint) <= sizeof(MPI_Aint)
! (Not strictly defined, but all reasonable implementations will
! have this property)
!
! When a value is stored, the full value is stored (this may be fewer
! bytes than the maximum-sized attribute, in which case the high
! bytes are stored as zero). When a value is retrieved, if the
! destination location is smaller, the low bytes (in value) are
! saved; this is the same as trunction. If the destination location
! is longer, then then value is sign-extended (See MPI-3, 17.2.7).
!
! Specifically, if the value was set from Fortran, C will return a
! pointer to the appropriate-sized integer.
! When the value is set from C but accessed from Fortran, the value
! is converted to an integer of the appropriate length, possibly truncated.
!
! FIXME: The above different-length attribute case is not yet handled
! in this code.
!
! In addition to setting and getting attributes, they are accessed
! through duplication (COMM_DUP and TYPE_DUP), and on deletion of the
! object to which they are attached, when the copy functions will be
! well-defined.
!
! This code was inspired by a code written by Jeff Squyres to test these
! nine cases. This code, however, is different.
!
! So, for each of the same->same tests:
! Store largest positive and negative attributes. Dup them,
! retrieve them, delete them. All bytes should remain value, and
! no other. Use keys created in all three languages for set/get;
! use language under test for dup.
!
! For X->Y tests:
! Using X, store into key created in all three.
! Using Y, retrive all attributes. See above for handling of
! truncated or sign-extended
!
! Use Fortran to drive tests (Fortran main program). Call C for
! C routines and to check data with different sizes (to ensure that
! the proper bytes are used in the value).
!
! Use the same keyval for attributes used in both C and Fortran (both
! modes). This found an error in MPICH, where the type of the
! attribute (e.g., pointer, integer, or address-sized integer) needs
! to be saved.
!
! Module containing the keys and other information, including
! interfaces to the C routines
module keyvals
use mpi, only: MPI_ADDRESS_KIND
logical fverbose, useintSize
integer ptrSize, intSize, aintSize
integer fcomm1_key, fcomm1_extra
integer fcomm2_key, ftype2_key, fwin2_key
integer ccomm1_key
integer ccomm2_key, ctype2_key, cwin2_key
integer win
integer (kind=MPI_ADDRESS_KIND) fcomm2_extra, ftype2_extra,&
& fwin2_extra
interface
pure function bigint()
integer bigint
end function bigint
pure function bigaint()
use mpi, only : MPI_ADDRESS_KIND
integer (kind=MPI_ADDRESS_KIND) bigaint
end function bigaint
! Could use bind(c) once we require that level of Fortran support.
subroutine csetmpi( fcomm, fkey, val, errs )
integer, INTENT(IN) :: fcomm, fkey, val
integer errs
end subroutine csetmpi
subroutine csetmpi2( fcomm, fkey, val, errs )
use mpi, only : MPI_ADDRESS_KIND
integer, INTENT(IN) :: fcomm, fkey
integer errs
integer (KIND=MPI_ADDRESS_KIND) val
end subroutine csetmpi2
subroutine cattrinit( fv )
integer fv
end subroutine cattrinit
subroutine cgetsizes( ps, is, as )
integer, INTENT(OUT) :: ps, is, as
end subroutine cgetsizes
subroutine ccreatekeys( k1, k2, k3, k4 )
integer, INTENT(OUT) :: k1, k2, k3, k4
end subroutine ccreatekeys
subroutine cfreekeys()
end subroutine cfreekeys
subroutine ctoctest( errs )
integer errs
end subroutine ctoctest
end interface
end module keyvals
!
program main
use mpi
use keyvals
implicit none
integer ierr
integer errs, tv, rank
integer(MPI_ADDRESS_KIND) tmp
errs = 0
call MTEST_INIT( ierr )
call MPI_COMM_RANK( MPI_COMM_WORLD, rank, ierr )
!
! Let the C routines know about debugging
call cgetenvbool( "MPITEST_VERBOSE", tv )
if (tv .eq. 1) then
fverbose = .true.
call cattrinit( 1 )
else
fverbose = .false.
call cattrinit( 0 )
endif
!
! If this value is true, define an "big MPI_Aint" value that fits in
! an MPI_Fint (see function bigaint)
call cgetenvbool( "MPITEST_ATTR_INTFORAINT", tv )
if (tv .eq. 1) then
useintSize = .true.
else
useintSize = .false.
endif
!
! Get the sizes of the three types of attributes
call cgetsizes( ptrSize, intSize, aintSize )
if (fverbose) then
print *, 'sizeof(ptr)=',ptrSize, ' sizeof(int)=', intSize, ' &
&sizeof(aint)=', aintSize
endif
!
! Create the keyvals
!
! Create the attribute values to use. We want these to use the full
! available width, which depends on both the type and the test,
! since when switching between types of different sizes, we need to
! check only the "low" bits (those shared in types of each size).
!
!
if (fverbose) then
print *, "Creating Fortran attribute keys"
endif
call fCreateKeys()
if (fverbose) then
print *, "Creating C attribute keys"
endif
call ccreatekeys( ccomm1_key, ccomm2_key, ctype2_key, cwin2_key&
& )
!
! Create a window to use with the attribute tests in Fortran
tmp = 0
call MPI_WIN_CREATE( MPI_BOTTOM, tmp, 1, MPI_INFO_NULL,&
& MPI_COMM_WORLD, win, ierr )
!
if (fverbose) then
print *, "Case 1: C sets and C gets"
endif
call ctoctest( errs )
if (fverbose) then
print *, "Case 2: C sets and Fortran (MPI1) gets"
endif
call ctof1test( errs )
if (fverbose) then
print *, "Case 3: C sets and Fortran (MPI2) gets"
endif
call ctof2test( errs )
if (fverbose) then
print *, "Case 4: Fortran (MPI1) sets and C gets"
endif
call f1toctest( errs )
if (fverbose) then
print *, "Case 5: Fortran (MPI1) sets and gets"
endif
call f1tof1test( errs )
if (fverbose) then
print *, "Case 6: Fortran (MPI1) sets and Fortran (MPI2) gets"
endif
call f1tof2test( errs )
if (fverbose) then
print *, "Case 7: Fortran (MPI2) sets and C gets"
endif
call f2toctest( errs )
if (fverbose) then
print *, "Case 8: Fortran (MPI2) sets and Fortran (MPI1) gets"
endif
call f2tof1test( errs )
if (fverbose) then
print *, "Case 9: Fortran (MPI2) sets and gets"
endif
call f2tof2test( errs )
! Cleanup
call ffreekeys()
call cfreekeys()
call MPI_WIN_FREE( win, ierr )
call MTEST_FINALIZE( errs )
end
!
! -------------------------------------------------------------------
! Check attribute set in Fortran (MPI-1) and read from Fortran (MPI-1)
! -------------------------------------------------------------------
integer function FMPI1checkCommAttr( comm, key, expected, msg )
use mpi
integer comm, key, expected
character*(*) msg
integer value, ierr
logical flag
!
FMPI1checkCommAttr = 0
call MPI_ATTR_GET( comm, key, value, flag, ierr )
if (.not. flag) then
print *, "Error: reading Fortran INTEGER attribute: ", msg
FMPI1checkCommAttr = 1
return
endif
if (value .ne. expected) then
print *, "Error: Fortran INTEGER attribute: ", msg
print *, "Expected ", expected, " but got ", value
FMPI1checkCommAttr = 1
endif
return
end
!
! -------------------------------------------------------------------
! Functions associated with attribute copy/delete.
! -------------------------------------------------------------------
subroutine FMPI1_COPY_FN( oldcomm, key, extrastate, inval,&
& outval, flag, ierr )
use mpi
use keyvals, only : fverbose
integer oldcomm, key, extrastate, inval, outval, ierr
logical flag
!
if (fverbose) then
print *, 'FMPI1_COPY: Attr in = ', inval, ' extra = ',&
& extrastate
endif
flag = .true.
outval = inval + 1
ierr = MPI_SUCCESS
end
!
subroutine FMPI1_DELETE_FN( oldcomm, key, extrastate, inval,&
& ierr )
use mpi
use keyvals, only : fverbose
integer oldcomm, key, extrastate, inval, ierr
logical flag
!
if (fverbose) then
print *, "FMPI1_DELETE: inval = ", inval, " extra = ",&
& extrastate
endif
ierr = MPI_SUCCESS
end
!
!
subroutine FMPI2_COPY_FN( oldcomm, key, extrastate, inval, outval,&
& flag, ierr )
use mpi
use keyvals, only : fverbose
implicit none
integer oldcomm, key, ierr
integer (KIND=MPI_ADDRESS_KIND) inval, outval, extrastate
logical flag
!
if (fverbose) then
print *, 'FMPI2_COPY: Attr in = ', inval, ' extra = ',&
& extrastate
endif
flag = .true.
outval = inval + 1
ierr = MPI_SUCCESS
end
!
subroutine FMPI2_DELETE_FN( oldcomm, key, extrastate, inval,&
& ierr )
use mpi
use keyvals, only : fverbose
implicit none
integer oldcomm, key, ierr
integer (kind=MPI_ADDRESS_KIND) inval, extrastate
!
if (fverbose) then
print *, "FMPI2_DELETE: inval = ", inval, " extra = ",&
& extrastate
endif
ierr = MPI_SUCCESS
end
! -------------------------------------------------------------------
!
! Typical check pattern
!
! Set value
! Get value (check set in same form)
! Get value in other modes
! Dup object (updates value)
! Get value in other modes
! Delete dup'ed object; check correct value sent to delete routine
!
subroutine fcreateKeys( )
use mpi
use keyvals
implicit none
external FMPI1_COPY_FN, FMPI1_DELETE_FN, FMPI2_COPY_FN,&
& FMPI2_DELETE_FN
integer ierr
fcomm1_extra = 0
fcomm2_extra = 0
ftype2_extra = 0
fwin2_extra = 0
call MPI_KEYVAL_CREATE( FMPI1_COPY_FN, FMPI1_DELETE_FN,&
& fcomm1_key, fcomm1_extra, ierr )
call MPI_COMM_CREATE_KEYVAL( FMPI2_COPY_FN, FMPI2_DELETE_FN,&
& fcomm2_key, fcomm2_extra, ierr )
call MPI_TYPE_CREATE_KEYVAL( FMPI2_COPY_FN, FMPI2_DELETE_FN,&
& ftype2_key, ftype2_extra, ierr )
call MPI_WIN_CREATE_KEYVAL( FMPI2_COPY_FN, FMPI2_DELETE_FN,&
& fwin2_key, fwin2_extra, ierr )
end subroutine fcreateKeys
!
subroutine ffreekeys()
use mpi
use keyvals
implicit none
integer ierr
call MPI_KEYVAL_FREE( fcomm1_key, ierr )
call MPI_COMM_FREE_KEYVAL( fcomm2_key, ierr )
call MPI_TYPE_FREE_KEYVAL( ftype2_key, ierr )
call MPI_WIN_FREE_KEYVAL( fwin2_key, ierr )
return
end subroutine ffreekeys
! -------------------------------------------------------------------
! Set attributes in Fortran (MPI-1) and read them from Fortran (MPI-1)
subroutine f1tof1test(errs)
use mpi
use keyvals
implicit none
integer errs
integer ierr, attrval, fcomm1attr, fdup
!
fcomm1attr = bigint()
attrval = fcomm1attr
call MPI_ATTR_PUT( MPI_COMM_SELF, fcomm1_key, fcomm1attr,&
& ierr )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, &
&"F to F (check value)", errs )
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi1read( fdup, fcomm1_key, attrval + 1, "F to F dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
!
! Use a negative value
fcomm1attr = -bigint()
attrval = fcomm1attr
call MPI_ATTR_PUT( MPI_COMM_SELF, fcomm1_key, fcomm1attr,&
& ierr )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, &
&"F to F (check neg value)", errs )
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi1read( fdup, fcomm1_key, attrval + 1, "F to F dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
end subroutine f1tof1test
!
! Set attributes in C and read them from Fortran (MPI-1)
subroutine ctof1test(errs)
use mpi
use keyvals
implicit none
integer errs
integer ierr, attrval, fcomm1attr, fdup
!
fcomm1attr = bigint()
attrval = fcomm1attr
call csetmpi( MPI_COMM_SELF, fcomm1_key, fcomm1attr, errs )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, "C to F",&
& errs )
if (ptrSize .eq. intSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi1read( fdup, fcomm1_key, attrval + 1, "C to F dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
!
fcomm1attr = -bigint()
attrval = fcomm1attr
call csetmpi( MPI_COMM_SELF, fcomm1_key, fcomm1attr, errs )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, "C to F",&
& errs )
if (ptrSize .eq. intSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi1read( fdup, fcomm1_key, attrval + 1, "C to F dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
end subroutine ctof1test
!
! Set attributes in Fortran (MPI-1) and read in Fortran (MPI-2)
subroutine f1tof2test(errs)
use mpi
use keyvals
implicit none
integer errs
integer ierr, attrval, fcomm1attr, fdup
integer (kind=MPI_ADDRESS_KIND) expected
!
fcomm1attr = bigint()
attrval = fcomm1attr
call MPI_ATTR_PUT( MPI_COMM_SELF, fcomm1_key, fcomm1attr,&
& ierr )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, &
& "F to F (check value for F2 test)", errs )
if (intSize .eq. aintSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
expected = attrval + 1
call fmpi2read( fdup, fcomm1_key, expected, "F to F2 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
!
fcomm1attr = -bigint()
attrval = fcomm1attr
call MPI_ATTR_PUT( MPI_COMM_SELF, fcomm1_key, fcomm1attr,&
& ierr )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, &
&"F to F (check neg value for F2 test)", errs )
if (intSize .eq. aintSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
expected = attrval + 1
call fmpi2read( fdup, fcomm1_key, expected, "F to F2 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
end subroutine f1tof2test
!
subroutine fmpi1read( comm, key, expected, msg, errs )
use mpi
implicit none
integer comm, key, expected, errs
character *(*) msg
logical flag
integer ierr, attrval
!
call MPI_ATTR_GET( comm, key, attrval, flag, ierr )
if (.not. flag) then
print *, 'Error: flag false for Attr_get: ', msg
errs = errs + 1
return
endif
if (attrval .ne. expected) then
print *, 'Error: expected ', expected, ' but saw ',&
& attrval, ':', msg
errs = errs + 1
endif
return
end subroutine fmpi1read
subroutine fmpi2read( comm, key, expected, msg, errs )
use mpi
implicit none
integer comm, key, errs
integer (kind=MPI_ADDRESS_KIND) expected
character *(*) msg
logical flag
integer ierr
integer (kind=MPI_ADDRESS_KIND) attrval
!
call MPI_COMM_GET_ATTR( comm, key, attrval, flag, ierr )
if (.not. flag) then
print *, 'Error: flag false for Attr_get: ', msg
errs = errs + 1
return
endif
if (attrval .ne. expected) then
print *, 'Error: expected ', expected, ' but saw ',&
& attrval, ':', msg
errs = errs + 1
endif
return
end subroutine fmpi2read
subroutine fmpi2readwin( win, key, expected, msg, errs )
use mpi
implicit none
integer win, key, errs
integer (kind=MPI_ADDRESS_KIND) expected
character *(*) msg
logical flag
integer ierr
integer (kind=MPI_ADDRESS_KIND) attrval
!
call MPI_WIN_GET_ATTR( win, key, attrval, flag, ierr )
if (.not. flag) then
print *, 'Error: flag false for Win_get_attr: ', msg
errs = errs + 1
return
endif
if (attrval .ne. expected) then
print *, 'Error: expected ', expected, ' but saw ',&
& attrval, ':', msg
errs = errs + 1
endif
return
end subroutine fmpi2readwin
subroutine fmpi2readtype( dtype, key, expected, msg, errs )
use mpi
implicit none
integer dtype, key, errs
integer (kind=MPI_ADDRESS_KIND) expected
character *(*) msg
logical flag
integer ierr
integer (kind=MPI_ADDRESS_KIND) attrval
!
call MPI_TYPE_GET_ATTR( dtype, key, attrval, flag, ierr )
if (.not. flag) then
print *, 'Error: flag false for Type_get_attr: ', msg
errs = errs + 1
return
endif
if (attrval .ne. expected) then
print *, 'Error: expected ', expected, ' but saw ',&
& attrval, ':', msg
errs = errs + 1
endif
return
end subroutine fmpi2readtype
subroutine f2tof2test(errs)
use mpi
use keyvals
implicit none
integer errs
integer ierr, fdup, tdup
integer (kind=MPI_ADDRESS_KIND) fcomm2attr, ftype2attr,&
& fwin2attr, attrval
!
fcomm2attr = bigaint()
attrval = fcomm2attr
call MPI_COMM_SET_ATTR( MPI_COMM_SELF, fcomm2_key, fcomm2attr,&
& ierr )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "F2 to F2",&
& errs )
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi2read( fdup, fcomm2_key, attrval + 1, "F2 to F2 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
!
ftype2attr = bigaint()-9
attrval = ftype2attr
call MPI_TYPE_SET_ATTR( MPI_INTEGER, ftype2_key, ftype2attr,&
& ierr )
call fmpi2readtype( MPI_INTEGER, ftype2_key, attrval, "F2 type&
& to F2", errs )
call MPI_TYPE_DUP( MPI_INTEGER, tdup, ierr )
call fmpi2readtype( tdup, ftype2_key, attrval + 1, "F2 type to&
& F dup", errs )
call MPI_TYPE_FREE( tdup, ierr )
fwin2attr = bigaint()-9
attrval = fwin2attr
call MPI_WIN_SET_ATTR( win, fwin2_key, fwin2attr,&
& ierr )
call fmpi2readwin( win, fwin2_key, attrval, "F2 win to F2",&
& errs )
!
fcomm2attr = -bigaint()
attrval = fcomm2attr
call MPI_COMM_SET_ATTR( MPI_COMM_SELF, fcomm2_key, fcomm2attr,&
& ierr )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "F2 to F2",&
& errs )
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi2read( fdup, fcomm2_key, attrval + 1, "F2 to F2 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
!
ftype2attr = -(bigaint()-9)
attrval = ftype2attr
call MPI_TYPE_SET_ATTR( MPI_INTEGER, ftype2_key, ftype2attr,&
& ierr )
call fmpi2readtype( MPI_INTEGER, ftype2_key, attrval, "F2 type&
& to F2", errs )
call MPI_TYPE_DUP( MPI_INTEGER, tdup, ierr )
call fmpi2readtype( tdup, ftype2_key, attrval + 1, "F2 type to&
& F dup", errs )
call MPI_TYPE_FREE( tdup, ierr )
fwin2attr = -(bigaint()-9)
attrval = fwin2attr
call MPI_WIN_SET_ATTR( win, fwin2_key, fwin2attr,&
& ierr )
call fmpi2readwin( win, fwin2_key, attrval, "F2 win to F2",&
& errs )
end subroutine f2tof2test
!
subroutine f1toctest( errs )
use mpi
use keyvals
implicit none
integer errs
integer ierr, attrval, fcomm1attr, fdup
!
fcomm1attr = bigint()
attrval = fcomm1attr
call MPI_ATTR_PUT( MPI_COMM_SELF, fcomm1_key, fcomm1attr,&
& ierr )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, &
& "F to F (check for F to C)", errs )
if (intSize .eq. ptrSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call cmpif1read( fdup, fcomm1_key, attrval + 1, errs, &
& "F to F2 dup" )
call MPI_COMM_FREE( fdup, ierr )
endif
!
fcomm1attr = -bigint()
attrval = fcomm1attr
call MPI_ATTR_PUT( MPI_COMM_SELF, fcomm1_key, fcomm1attr,&
& ierr )
call fmpi1read( MPI_COMM_SELF, fcomm1_key, attrval, &
&"F to F (check neg value for F to C)", errs )
if (intSize .eq. ptrSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call cmpif1read( fdup, fcomm1_key, attrval + 1, errs, &
"F to C dup" )
call MPI_COMM_FREE( fdup, ierr )
endif
end subroutine f1toctest
subroutine f2tof1test(errs)
use mpi
use keyvals
implicit none
integer errs
integer ierr, fdup, tdup
integer (kind=MPI_ADDRESS_KIND) fcomm2attr, ftype2attr,&
& fwin2attr, attrval
integer expected
!
fcomm2attr = bigaint()
attrval = fcomm2attr
call MPI_COMM_SET_ATTR( MPI_COMM_SELF, fcomm2_key, fcomm2attr,&
& ierr )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "F2 to F2",&
& errs )
if (aintSize .eq. intSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
expected = attrval + 1
call fmpi1read( fdup, fcomm2_key, expected, "F2 to F1 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
!
fcomm2attr = -bigaint()
attrval = fcomm2attr
call MPI_COMM_SET_ATTR( MPI_COMM_SELF, fcomm2_key, fcomm2attr,&
& ierr )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "F2 to F2",&
& errs )
if (aintSize .eq. intSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
expected = attrval + 1
call fmpi1read( fdup, fcomm2_key, expected, "F2 to F1 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
!
end subroutine f2tof1test
!
subroutine f2toctest(errs)
use mpi
use keyvals
implicit none
integer errs
integer ierr, fdup, tdup
integer (kind=MPI_ADDRESS_KIND) fcomm2attr, ftype2attr,&
& fwin2attr, attrval
!
fcomm2attr = bigaint()
attrval = fcomm2attr
call MPI_COMM_SET_ATTR( MPI_COMM_SELF, fcomm2_key, fcomm2attr,&
& ierr )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "F2 to F2",&
& errs )
if (aintSize .eq. ptrSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call cmpif2read( fdup, fcomm2_key, attrval + 1, errs, "F2 t&
&o c dup")
call MPI_COMM_FREE( fdup, ierr )
endif
!
ftype2attr = bigaint()-9
attrval = ftype2attr
call MPI_TYPE_SET_ATTR( MPI_INTEGER, ftype2_key, ftype2attr,&
& ierr )
call fmpi2readtype( MPI_INTEGER, ftype2_key, attrval, "F2 type&
& to F2", errs )
if (aintSize .eq. ptrSize) then
call MPI_TYPE_DUP( MPI_INTEGER, tdup, ierr )
call cmpif2readtype( tdup, ftype2_key, attrval + 1, errs, "F2 &
&type toF dup" )
call MPI_TYPE_FREE( tdup, ierr )
endif
fwin2attr = bigaint()-9
attrval = fwin2attr
call MPI_WIN_SET_ATTR( win, fwin2_key, fwin2attr, ierr )
call cmpif2readwin( win, fwin2_key, attrval, errs, "F2 win to &
&c" )
!
fcomm2attr = -bigaint()
attrval = fcomm2attr
call MPI_COMM_SET_ATTR( MPI_COMM_SELF, fcomm2_key, fcomm2attr,&
& ierr )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "F2 to F2",&
& errs )
if (aintSize .eq. ptrSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call cmpif2read( fdup, fcomm2_key, attrval + 1, errs, "F2 t&
&o c dup")
call MPI_COMM_FREE( fdup, ierr )
endif
!
ftype2attr = -(bigaint()-9)
attrval = ftype2attr
call MPI_TYPE_SET_ATTR( MPI_INTEGER, ftype2_key, ftype2attr,&
& ierr )
call fmpi2readtype( MPI_INTEGER, ftype2_key, attrval, "F2 type&
& to F2", errs )
if (aintSize .eq. ptrSize) then
call MPI_TYPE_DUP( MPI_INTEGER, tdup, ierr )
call cmpif2readtype( tdup, ftype2_key, attrval + 1, errs, "F2 &
&type toF dup" )
call MPI_TYPE_FREE( tdup, ierr )
endif
fwin2attr = -(bigaint()-9)
attrval = fwin2attr
call MPI_WIN_SET_ATTR( win, fwin2_key, fwin2attr, ierr )
call cmpif2readwin( win, fwin2_key, attrval, errs, "F2 win to &
&c" )
end subroutine f2toctest
!
subroutine ctof2test(errs)
use mpi
use keyvals
implicit none
integer errs
integer ierr, fdup, tdup
integer (kind=MPI_ADDRESS_KIND) fcomm2attr, ftype2attr,&
& fwin2attr, attrval
!
fcomm2attr = bigaint()
attrval = fcomm2attr
call csetmpi2( MPI_COMM_SELF, fcomm2_key, fcomm2attr, errs )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "c to F2",&
& errs )
if (aintSize .eq. ptrSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi2read( fdup, fcomm2_key, attrval + 1, "c to F2 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
!
ftype2attr = bigaint()-9
attrval = ftype2attr
call csetmpitype( MPI_INTEGER, ftype2_key, ftype2attr, errs )
call fmpi2readtype( MPI_INTEGER, ftype2_key, attrval, "c type&
& to F2", errs )
if (aintSize .eq. ptrSize) then
call MPI_TYPE_DUP( MPI_INTEGER, tdup, ierr )
call fmpi2readtype( tdup, ftype2_key, attrval + 1, "c type to&
& F2 dup", errs )
call MPI_TYPE_FREE( tdup, ierr )
endif
fwin2attr = bigaint()-9
attrval = fwin2attr
call csetmpiwin( win, fwin2_key, fwin2attr, errs )
call fmpi2readwin( win, fwin2_key, attrval, "c win to F2",&
& errs )
!
fcomm2attr = -bigaint()
attrval = fcomm2attr
call csetmpi2( MPI_COMM_SELF, fcomm2_key, fcomm2attr, errs )
call fmpi2read( MPI_COMM_SELF, fcomm2_key, attrval, "c to F2",&
& errs )
if (aintSize .eq. ptrSize) then
call MPI_COMM_DUP( MPI_COMM_SELF, fdup, ierr )
call fmpi2read( fdup, fcomm2_key, attrval + 1, "c to F2 dup",&
& errs )
call MPI_COMM_FREE( fdup, ierr )
endif
!
ftype2attr = -(bigaint()-9)
attrval = ftype2attr
call csetmpitype( MPI_INTEGER, ftype2_key, ftype2attr, errs )
call fmpi2readtype( MPI_INTEGER, ftype2_key, attrval, "c type&
& to F2", errs )
if (aintSize .eq. ptrSize) then
call MPI_TYPE_DUP( MPI_INTEGER, tdup, ierr )
call fmpi2readtype( tdup, ftype2_key, attrval + 1, "c type to&
& F2 dup", errs )
call MPI_TYPE_FREE( tdup, ierr )
endif
fwin2attr = -(bigaint()-9)
attrval = fwin2attr
call csetmpiwin( win, fwin2_key, fwin2attr, errs )
call fmpi2readwin( win, fwin2_key, attrval, "c win to F2",&
& errs )
end subroutine ctof2test
! -------------------------------------------------------------------
! Return an integer value that fills all of the bytes
pure integer function bigint()
integer i, v, digits
digits = range(i)
v = 0
do i=1,digits
v = v * 10 + i
enddo
bigint = v
return
end function bigint
!
! Return an integer value that fill all of the bytes in an AINT
! The logical "useintsize" allows us to specify that only an int-sized
! result should be returned
pure function bigaint()
use mpi, only : MPI_ADDRESS_KIND
use keyvals, only : useintsize
implicit none
integer (kind=MPI_ADDRESS_KIND) bigaint, v
integer i, digits
if (useintsize) then
digits = range(i)
else
digits = range(v)
endif
v = 0
do i=1,digits
v = v * 10 + i
enddo
bigaint = v
return
end function bigaint