From: Julian Seward Date: Tue, 26 Dec 2006 03:10:51 +0000 (+0000) Subject: Merge r6371 (fix handling of MPI_LONG_DOUBLE) X-Git-Tag: svn/VALGRIND_3_2_2~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9301d98828cd220cbbb2ffbedff9f509f7c38efd;p=thirdparty%2Fvalgrind.git Merge r6371 (fix handling of MPI_LONG_DOUBLE) git-svn-id: svn://svn.valgrind.org/valgrind/branches/VALGRIND_3_2_BRANCH@6426 --- diff --git a/auxprogs/libmpiwrap.c b/auxprogs/libmpiwrap.c index 0c6c1f5c1a..999c1e433f 100644 --- a/auxprogs/libmpiwrap.c +++ b/auxprogs/libmpiwrap.c @@ -90,6 +90,7 @@ #define I_WRAP_FNNAME_U(_name) I_WRAP_SONAME_FNNAME_ZU(libmpiZdsoZa,_name) + /*------------------------------------------------------------*/ /*--- Decls ---*/ /*------------------------------------------------------------*/ @@ -108,6 +109,10 @@ typedef unsigned long UWord; # define offsetof(type,memb) ((int)&((type*)0)->memb) #endif +/* Find the size of long double image (not 'sizeof(long double)'). + See comments in sizeofOneNamedTy. */ +static long sizeof_long_double_image ( void ); + /*------------------------------------------------------------*/ /*--- Simple helpers ---*/ @@ -380,9 +385,13 @@ static void maybeFreeTy ( MPI_Datatype* ty ) There is a subtlety, which is that this is required to return the exact size of one item of the type, NOT the size of it when padded suitably to make an array of them. In particular that's why the - size of LONG_DOUBLE is 10 and not sizeof(long double), since the - latter is 12 at least on x86. Except if sizeof(long double) is - claimed to be 8 then we'd better respect that. + size of LONG_DOUBLE is computed by looking at the result of doing a + long double store, rather than just asking what is the sizeof(long + double). + + For LONG_DOUBLE on x86-linux and amd64-linux my impression is that + the right answer is 10 even though sizeof(long double) says 12 and + 16 respectively. On ppc32-linux it appears to be 16. Ref: MPI 1.1 doc p18 */ static long sizeofOneNamedTy ( MPI_Datatype ty ) @@ -398,9 +407,8 @@ static long sizeofOneNamedTy ( MPI_Datatype ty ) if (ty == MPI_FLOAT) return sizeof(float); if (ty == MPI_DOUBLE) return sizeof(double); if (ty == MPI_BYTE) return 1; - if (ty == MPI_LONG_DOUBLE) - return sizeof(long double)==8 - ? 8 : 10; /* NOT: sizeof(long double); */ + if (ty == MPI_LONG_DOUBLE) return sizeof_long_double_image(); + /* MPI_PACKED */ /* new in MPI2: */ # if defined(MPI_WCHAR) @@ -424,6 +432,60 @@ static long sizeofOneNamedTy ( MPI_Datatype ty ) } +/* Find the size of long double image (not 'sizeof(long double)'). + See comments in sizeofOneNamedTy. +*/ +static long sizeof_long_double_image ( void ) +{ + long i; + unsigned char* p; + static long cached_result = 0; + + /* Hopefully we have it already. */ + if (cached_result != 0) { + assert(cached_result == 10 || cached_result == 16 || cached_result == 8); + return cached_result; + } + + /* No? Then we'll have to compute it. This isn't thread-safe but + it doesn't really matter since all races to compute it should + produce the same answer. */ + p = malloc(64); + assert(p); + for (i = 0; i < 64; i++) + p[i] = 0x55; + + /* Write a value which isn't known at compile time and therefore + must come out of a register. If we just store a constant here, + some compilers write more data than a store from a machine + register would. Therefore we have to force a store from a + machine register by storing a value which isn't known at compile + time. Since getpid() will return a value < 1 million, turn it + into a zero by dividing by 1e+30. */ + *(long double*)(&p[16]) = (long double)(1.0e-30 * (double)getpid()); + + for (i = 0; i < 16; i++) { + assert(p[i] == 0x55); + assert(p[i+48] == 0x55); + } + for (i = 16; i <= 48; i++) { + if (p[i] == 0x55) + break; + } + + assert(i < 48); + assert(i > 16); + free(p); + cached_result = i - 16; + + if (0) + printf("sizeof_long_double_image: computed %d\n", (int)cached_result); + + assert(cached_result == 10 || cached_result == 16 || cached_result == 8); + return cached_result; +} + + /*------------------------------------------------------------*/ /*--- Unpicking datatypes ---*/ /*------------------------------------------------------------*/ @@ -684,11 +746,12 @@ void mpiwrap_walk_type_EXTERNALLY_VISIBLE /* ---------------- Do corresponding checks on memory areas defined using a - straightforward (start, length) description. + straightforward (start, length) description. Not inlined + so as to make any resulting error tracebacks easier to read. ---------------- */ -static inline +static void check_mem_is_defined_untyped ( void* buffer, long nbytes ) { if (nbytes > 0) { @@ -696,7 +759,7 @@ void check_mem_is_defined_untyped ( void* buffer, long nbytes ) } } -static inline +static void check_mem_is_addressable_untyped ( void* buffer, long nbytes ) { if (nbytes > 0) { @@ -704,7 +767,7 @@ void check_mem_is_addressable_untyped ( void* buffer, long nbytes ) } } -static inline +static void make_mem_defined_if_addressable_untyped ( void* buffer, long nbytes ) { if (nbytes > 0) { @@ -712,7 +775,7 @@ void make_mem_defined_if_addressable_untyped ( void* buffer, long nbytes ) } } -static inline +static void make_mem_defined_if_addressable_if_success_untyped ( int err, void* buffer, long nbytes ) { @@ -721,17 +784,6 @@ void make_mem_defined_if_addressable_if_success_untyped ( int err, } } -/* Set the specified area to 'addressible but undefined' - (safe-to-write) state. */ - -static inline -void make_mem_undefined_untyped ( void* buffer, long nbytes ) -{ - if (nbytes > 0) { - VALGRIND_MAKE_MEM_UNDEFINED(buffer, nbytes); - } -} - /* ---------------- Do checks on memory areas defined using the MPI (buffer, count,