On 11/22/2011 03:48 PM, Joseph S. Myers wrote:
On Tue, 22 Nov 2011, Andrew MacLeod wrote:
It certainly does have those types, as typedefs defined in<uchar.h> for
the same types as uint_least16_t and uint_least32_t. And<stdatomic.h> is
also required to define ATOMIC_CHAR16_T_LOCK_FREE and
ATOMIC_CHAR32_T_LOCK_FREE.
but there isn't a stdatomic.h until we support C1x right? didnt we bail on
It still seems better to predefine the macros for those types, using
char16_type_node and char32_type_node, using them initially for C++ and
then later for C as well.
OK, here's a reworked patch. This bootstraps but there is a
regression... one set of PCH tests fail in a very odd way. I've
investigated it and it turns out that for some reason, ptr_type_node
doesn't always have it size set if code isn't being generated (all the
other nodes do)... in particular I can reproduce it on a small test case
on my x86-64 machine where size is 8 when generating code, and 0 if -E
is used to output pre-processed source. I'm looking into that today.
Question, the purpose of the testcase in the patch macros.c... is it
to simply test for standard compliance, or to test both compliance PLUS
what we expect? I made the change assuming the latter. We will always
generate a 1 or a 2 for the macros, and we also want the macros to now
be compile time satisfied so they can be used in #if statements like
bkoz was trying to do.
Andrew
c-family
* c-cpp-builtin.c (cpp_atomic_builtins):New. Emit all atomic
predefines in one place. Add LOCK_FREE predefines.
(c_cpp_builtins): Move Legacy HAVE_SYNC predefines to
new func.
libstdc++-v3
* include/bits/atomic_base.h (ATOMIC_*_LOCK_FREE): Use new cpp
predefined macros.
* testsuite/29_atomics/headers/atomic/macros.cc: Add BOOL and POINTER
macro checks. Check for expected compile time values.
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
*** gcc/c-family/c-cppbuiltin.c (revision 181698)
--- gcc/c-family/c-cppbuiltin.c (working copy)
*************** c_cpp_builtins_optimize_pragma (cpp_read
*** 568,573 ****
--- 568,677 ----
}
+ /* This function will emit cpp macros to indicate the presence of various lock
+ free atomic operations. */
+
+ static void
+ cpp_atomic_builtins (cpp_reader *pfile)
+ {
+ /* Set a flag for each size of object that compare and swap exists for up to
+ a 16 byte object. */
+ #define SWAP_LIMIT 17
+ bool have_swap[SWAP_LIMIT];
+
+ /* Clear the map of sizes compare_and swap exists for. */
+ memset (have_swap, 0, sizeof (have_swap));
+
+ /* Tell source code if the compiler makes sync_compare_and_swap
+ builtins available. */
+ #ifndef HAVE_sync_compare_and_swapqi
+ #define HAVE_sync_compare_and_swapqi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapqi
+ #define HAVE_atomic_compare_and_swapqi 0
+ #endif
+
+ if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ have_swap[1] = true;
+ }
+
+ #ifndef HAVE_sync_compare_and_swaphi
+ #define HAVE_sync_compare_and_swaphi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swaphi
+ #define HAVE_atomic_compare_and_swaphi 0
+ #endif
+ if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ have_swap[2] = true;
+ }
+
+ #ifndef HAVE_sync_compare_and_swapsi
+ #define HAVE_sync_compare_and_swapsi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapsi
+ #define HAVE_atomic_compare_and_swapsi 0
+ #endif
+ if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ have_swap[4] = true;
+ }
+
+ #ifndef HAVE_sync_compare_and_swapdi
+ #define HAVE_sync_compare_and_swapdi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapdi
+ #define HAVE_atomic_compare_and_swapdi 0
+ #endif
+ if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+ have_swap[8] = true;
+ }
+
+ #ifndef HAVE_sync_compare_and_swapti
+ #define HAVE_sync_compare_and_swapti 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapti
+ #define HAVE_atomic_compare_and_swapti 0
+ #endif
+ if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+ have_swap[16] = true;
+ }
+
+ /* Tell the source code about various types. These map to the C++11 and C1x
+ macros where 2 indicates lock-free always, and 1 indicates sometimes
+ lock free. */
+ #define SIZEOF_NODE(T) (tree_low_cst (TYPE_SIZE_UNIT (T), 1))
+ #define SWAP_INDEX(T) ((SIZEOF_NODE (T) < SWAP_LIMIT) ? SIZEOF_NODE (T) : 0)
+ builtin_define_with_int_value ("__GCC_ATOMIC_BOOL_LOCK_FREE",
+ (have_swap[SWAP_INDEX (boolean_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR_LOCK_FREE",
+ (have_swap[SWAP_INDEX (signed_char_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR16_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (char16_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR32_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (char32_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_WCHAR_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (wchar_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_SHORT_LOCK_FREE",
+ (have_swap[SWAP_INDEX (short_integer_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_INT_LOCK_FREE",
+ (have_swap[SWAP_INDEX (integer_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_LONG_LOCK_FREE",
+ (have_swap[SWAP_INDEX (long_integer_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_LLONG_LOCK_FREE",
+ (have_swap[SWAP_INDEX (long_long_integer_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_POINTER_LOCK_FREE",
+ (have_swap[SWAP_INDEX (ptr_type_node)]? 2 : 1));
+ }
+
/* Hook that registers front end and target-specific built-ins. */
void
c_cpp_builtins (cpp_reader *pfile)
*************** c_cpp_builtins (cpp_reader *pfile)
*** 756,808 ****
if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
cpp_define (pfile, "__WCHAR_UNSIGNED__");
! /* Tell source code if the compiler makes sync_compare_and_swap
! builtins available. */
! #ifndef HAVE_sync_compare_and_swapqi
! #define HAVE_sync_compare_and_swapqi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapqi
! #define HAVE_atomic_compare_and_swapqi 0
! #endif
! if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
! cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
!
! #ifndef HAVE_sync_compare_and_swaphi
! #define HAVE_sync_compare_and_swaphi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swaphi
! #define HAVE_atomic_compare_and_swaphi 0
! #endif
! if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
! cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
!
! #ifndef HAVE_sync_compare_and_swapsi
! #define HAVE_sync_compare_and_swapsi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapsi
! #define HAVE_atomic_compare_and_swapsi 0
! #endif
! if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
! cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
!
! #ifndef HAVE_sync_compare_and_swapdi
! #define HAVE_sync_compare_and_swapdi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapdi
! #define HAVE_atomic_compare_and_swapdi 0
! #endif
! if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
! cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
!
! #ifndef HAVE_sync_compare_and_swapti
! #define HAVE_sync_compare_and_swapti 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapti
! #define HAVE_atomic_compare_and_swapti 0
! #endif
! if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
! cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
!
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_cfi_asm ())
cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
--- 860,867 ----
if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
cpp_define (pfile, "__WCHAR_UNSIGNED__");
! cpp_atomic_builtins (pfile);
!
#ifdef DWARF2_UNWIND_INFO
if (dwarf2out_do_cfi_asm ())
cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
Index: libstdc++-v3/include/bits/atomic_base.h
===================================================================
*** libstdc++-v3/include/bits/atomic_base.h (revision 181698)
--- libstdc++-v3/include/bits/atomic_base.h (working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 91,108 ****
/// Lock-free Property
- #define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1)
! #define ATOMIC_BOOL_LOCK_FREE LOCKFREE_PROP (bool)
! #define ATOMIC_CHAR_LOCK_FREE LOCKFREE_PROP (char)
! #define ATOMIC_CHAR16_T_LOCK_FREE LOCKFREE_PROP (char16_t)
! #define ATOMIC_CHAR32_T_LOCK_FREE LOCKFREE_PROP (char32_t)
! #define ATOMIC_WCHAR_T_LOCK_FREE LOCKFREE_PROP (wchar_t)
! #define ATOMIC_SHORT_LOCK_FREE LOCKFREE_PROP (short)
! #define ATOMIC_INT_LOCK_FREE LOCKFREE_PROP (int)
! #define ATOMIC_LONG_LOCK_FREE LOCKFREE_PROP (long)
! #define ATOMIC_LLONG_LOCK_FREE LOCKFREE_PROP (long long)
! #define ATOMIC_POINTER_LOCK_FREE LOCKFREE_PROP (void *)
// Base types for atomics.
template<typename _IntTp>
--- 91,107 ----
/// Lock-free Property
! #define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
! #define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
! #define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
! #define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
! #define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
! #define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
! #define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
! #define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
! #define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
! #define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
// Base types for atomics.
template<typename _IntTp>
Index: libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc
===================================================================
*** libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc (revision
181698)
--- libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc (working copy)
***************
*** 20,25 ****
--- 20,29 ----
#include <atomic>
+ #ifndef ATOMIC_BOOL_LOCK_FREE
+ # error "ATOMIC_BOOL_LOCK_FREE must be a macro"
+ #endif
+
#ifndef ATOMIC_CHAR_LOCK_FREE
# error "ATOMIC_CHAR_LOCK_FREE must be a macro"
#endif
***************
*** 52,57 ****
--- 56,65 ----
# error "ATOMIC_LLONG_LOCK_FREE must be a macro"
#endif
+ #ifndef ATOMIC_POINTER_LOCK_FREE
+ # error "ATOMIC_POINTER_LOCK_FREE must be a macro"
+ #endif
+
#ifndef ATOMIC_FLAG_INIT
#error "ATOMIC_FLAG_INIT_must_be_a_macro"
#endif
*************** extern void abort(void);
*** 65,99 ****
int main ()
{
! if (ATOMIC_CHAR_LOCK_FREE != 0 && ATOMIC_CHAR_LOCK_FREE != 1
! && ATOMIC_CHAR_LOCK_FREE != 2)
abort ();
! if (ATOMIC_CHAR16_T_LOCK_FREE != 0 && ATOMIC_CHAR16_T_LOCK_FREE != 1
! && ATOMIC_CHAR16_T_LOCK_FREE != 2)
abort ();
! if (ATOMIC_CHAR32_T_LOCK_FREE != 0 && ATOMIC_CHAR32_T_LOCK_FREE != 1
! && ATOMIC_CHAR32_T_LOCK_FREE != 2)
abort ();
! if (ATOMIC_WCHAR_T_LOCK_FREE != 0 && ATOMIC_WCHAR_T_LOCK_FREE != 1
! && ATOMIC_WCHAR_T_LOCK_FREE != 2)
abort ();
! if (ATOMIC_SHORT_LOCK_FREE != 0 && ATOMIC_SHORT_LOCK_FREE != 1
! && ATOMIC_SHORT_LOCK_FREE != 2)
abort ();
! if (ATOMIC_INT_LOCK_FREE != 0 && ATOMIC_INT_LOCK_FREE != 1
! && ATOMIC_INT_LOCK_FREE != 2)
abort ();
! if (ATOMIC_LONG_LOCK_FREE != 0 && ATOMIC_LONG_LOCK_FREE != 1
! && ATOMIC_LONG_LOCK_FREE != 2)
abort ();
! if (ATOMIC_LLONG_LOCK_FREE != 0 && ATOMIC_LLONG_LOCK_FREE != 1
! && ATOMIC_LLONG_LOCK_FREE != 2)
abort ();
}
--- 73,115 ----
int main ()
{
! #if (ATOMIC_BOOL_LOCK_FREE != 1 && ATOMIC_BOOL_LOCK_FREE != 2)
! abort ();
! #endif
!
! #if (ATOMIC_CHAR_LOCK_FREE != 1 && ATOMIC_CHAR_LOCK_FREE != 2)
! abort ();
! #endif
!
! #if (ATOMIC_CHAR16_T_LOCK_FREE != 1 && ATOMIC_CHAR16_T_LOCK_FREE != 2)
abort ();
+ #endif
! #if (ATOMIC_CHAR32_T_LOCK_FREE != 1 && ATOMIC_CHAR32_T_LOCK_FREE != 2)
abort ();
+ #endif
! #if (ATOMIC_WCHAR_T_LOCK_FREE != 1 && ATOMIC_WCHAR_T_LOCK_FREE != 2)
abort ();
+ #endif
! #if (ATOMIC_SHORT_LOCK_FREE != 1 && ATOMIC_SHORT_LOCK_FREE != 2)
abort ();
+ #endif
! #if (ATOMIC_INT_LOCK_FREE != 1 && ATOMIC_INT_LOCK_FREE != 2)
abort ();
+ #endif
! #if (ATOMIC_LONG_LOCK_FREE != 1 && ATOMIC_LONG_LOCK_FREE != 2)
abort ();
+ #endif
! #if (ATOMIC_LLONG_LOCK_FREE != 1 && ATOMIC_LLONG_LOCK_FREE != 2)
abort ();
+ #endif
! #if (ATOMIC_POINTER_LOCK_FREE != 1 && ATOMIC_POINTER_LOCK_FREE != 2)
abort ();
+ #endif
}