This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Testing parallel mode and PR34106
- From: "Jonathan Wakely" <jwakely dot gcc at gmail dot com>
- To: "Benjamin Kosnik" <bkoz at redhat dot com>
- Cc: libstdc++ at gcc dot gnu dot org
- Date: Tue, 11 Dec 2007 14:02:36 +0000
- Subject: Testing parallel mode and PR34106
Should I be able to run "make check-parallel" with no FAILs? Even
before I touched any parallel headers I'm seeing several failures.
This isn't strictly necessary, but might be a good idea:
Index: include/parallel/tree.h
===================================================================
--- include/parallel/tree.h (revision 130747)
+++ include/parallel/tree.h (working copy)
@@ -1090,7 +1090,7 @@
* them have finished).
* \li READY_NOT: at least one of the children
* concatenation_problem have not finished */
- int is_ready;
+ _Atomic_word is_ready;
/** @brief Parent concatenation problem to solve when @c
is_ready = READY_YES */
Should include/parallel/types.h use BITS_PER_UNIT here, not 8?
/**
* @brief Number of bits of ::lcas_t.
*/
static const int lcas_t_bits = sizeof(lcas_t) * 8;
For parallel/compatibility.h, fetch_and_add can't be easily
implemented with __exchange_and_add_dispatch because it needs to work
with 32 and 64 bit types, and the ext/atomicity.h dispatchers only
support _Atomic_word, so the best I've come up with is:
template<typename T>
inline T
fetch_and_add(volatile T* ptr, T addend)
{
#if _GLIBCXX_ATOMIC_BUILTINS
return __sync_fetch_and_add(ptr, addend);
#else
#pragma message("slow fetch_and_add")
#pragma omp critical
{
T tmp = *ptr;
*ptr += addend;
return tmp;
}
#endif
}
compare_and_swap could check __default_lock_policy == _S_atomic but
that only guarantees 16-bit and 32-bit types can be used. In the
absence of a more fine-grained set of enumerations for _Lock_policy
(which would complicate shared_ptr slightly) this seems to work:
template<size_t _Sz> struct _CAS_helper { };
template<typename T, size_t _Sz>
bool
__compare_and_swap_helper(volatile T* ptr, T comparand, T replacement,
_CAS_helper<_Sz>)
{
#pragma message("slow compare_and_swap")
bool res = false;
#pragma omp critical
{
if (*ptr == comparand)
{
*ptr = replacement;
res = true;
}
}
return res;
}
#if __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
template<typename T>
inline bool
__compare_and_swap_helper(volatile T* ptr, T comparand, T replacement,
_CAS_helper<1>)
{
return __sync_bool_compare_and_swap(ptr, comparand, replacement);
}
#endif
// repeat for _2 _4 _8 _16 ...
template<typename T>
inline bool
compare_and_swap(volatile T* ptr, T comparand, T replacement)
{
return __compare_and_swap_helper(ptr, comparand, replacement,
_CAS_helper<sizeof(T)>());
}
I think this is going in the opposite direction to what Benjamin
wanted, where _Lock_policy dictates this sort of thing. I don't yet
see how to make that work without making _Lock_policy far more
fine-grained, in which case it becomes less useful for other cases.
Jon