svn commit: r236326 - stable/9/include

David Chisnall theraven at FreeBSD.org
Wed May 30 19:21:55 UTC 2012


Author: theraven
Date: Wed May 30 19:21:54 2012
New Revision: 236326
URL: http://svn.freebsd.org/changeset/base/236326

Log:
  MFC r228862, 228880, 228882, 228906, 228977, 229332, 229575, 229591, 229704,
  229716, 230062, 230225, 230267, 234958
  
  This brings stdatomic.h into -STABLE and includes improvements to tgmath.h that
  significantly decrease compile times on a C11 compiler (such as the clang in
  the base system).

Added:
  stable/9/include/stdatomic.h
     - copied, changed from r228862, head/include/stdatomic.h
Modified:
  stable/9/include/tgmath.h
Directory Properties:
  stable/9/include/   (props changed)

Copied and modified: stable/9/include/stdatomic.h (from r228862, head/include/stdatomic.h)
==============================================================================
--- head/include/stdatomic.h	Sat Dec 24 15:17:01 2011	(r228862, copy source)
+++ stable/9/include/stdatomic.h	Wed May 30 19:21:54 2012	(r236326)
@@ -35,14 +35,14 @@
 
 #if __has_feature(cxx_atomic)
 #define	__CLANG_ATOMICS
-#elif defined(__GNUC__)
+#elif __GNUC_PREREQ__(4, 7)
 #define	__GNUC_ATOMICS
-#else
+#elif !defined(__GNUC__)
 #error "stdatomic.h does not support your compiler"
 #endif
 
-#ifdef __GNUC_ATOMICS
-#define	_Atomic(T)				struct { volatile T __val; }
+#if !defined(__CLANG_ATOMICS)
+#define	_Atomic(T)			struct { volatile T __val; }
 #endif
 
 /*
@@ -50,11 +50,13 @@
  */
 
 #if defined(__CLANG_ATOMICS)
-#define	ATOMIC_VAR_INIT(value)			(value)
-#define	atomic_init(obj, value)			__atomic_init(obj, value)
-#elif defined(__GNUC_ATOMICS)
-#define	ATOMIC_VAR_INIT(value)			{ .__val = (value) }
-#define	atomic_init(obj, value)			(obj = ATOMIC_VAR_INIT(value))
+#define	ATOMIC_VAR_INIT(value)		(value)
+#define	atomic_init(obj, value)		__c11_atomic_init(obj, value)
+#else
+#define	ATOMIC_VAR_INIT(value)		{ .__val = (value) }
+#define	atomic_init(obj, value) do {					\
+	(obj)->__val = (value);						\
+} while (0)
 #endif
 
 /*
@@ -64,29 +66,29 @@
  */
 
 #ifndef __ATOMIC_RELAXED
-#define __ATOMIC_RELAXED			0
+#define __ATOMIC_RELAXED		0
 #endif
 #ifndef __ATOMIC_CONSUME
-#define __ATOMIC_CONSUME			1
+#define __ATOMIC_CONSUME		1
 #endif
 #ifndef __ATOMIC_ACQUIRE
-#define __ATOMIC_ACQUIRE			2
+#define __ATOMIC_ACQUIRE		2
 #endif
 #ifndef __ATOMIC_RELEASE
-#define __ATOMIC_RELEASE			3
+#define __ATOMIC_RELEASE		3
 #endif
 #ifndef __ATOMIC_ACQ_REL
-#define __ATOMIC_ACQ_REL			4
+#define __ATOMIC_ACQ_REL		4
 #endif
 #ifndef __ATOMIC_SEQ_CST
-#define __ATOMIC_SEQ_CST			5
+#define __ATOMIC_SEQ_CST		5
 #endif
 
 /*
  * 7.17.3 Order and consistency.
  *
  * The memory_order_* constants that denote the barrier behaviour of the
- * atomic operations.  
+ * atomic operations.
  */
 
 enum memory_order {
@@ -102,21 +104,30 @@ enum memory_order {
  * 7.17.4 Fences.
  */
 
-#if defined(__CLANG_ATOMICS)
-#define	atomic_thread_fence(order)	__atomic_thread_fence(order)
+#ifdef __CLANG_ATOMICS
+#define	atomic_thread_fence(order)	__c11_atomic_thread_fence(order)
+#define	atomic_signal_fence(order)	__c11_atomic_signal_fence(order)
 #elif defined(__GNUC_ATOMICS)
+#define	atomic_thread_fence(order)	__atomic_thread_fence(order)
+#define	atomic_signal_fence(order)	__atomic_signal_fence(order)
+#else
 #define	atomic_thread_fence(order)	__sync_synchronize()
+#define	atomic_signal_fence(order)	__asm volatile ("" : : : "memory")
 #endif
-#define	atomic_signal_fence(order)	__asm volatile ("" : : : "memory");
 
 /*
  * 7.17.5 Lock-free property.
  */
 
 #if defined(__CLANG_ATOMICS)
-#define	atomic_is_lock_free(obj)	__atomic_is_lock_free(obj)
+#define	atomic_is_lock_free(obj) \
+	__c11_atomic_is_lock_free(sizeof(obj))
 #elif defined(__GNUC_ATOMICS)
-#define	atomic_is_lock_free(obj)	(sizeof((obj->__val)) <= sizeof(void *))
+#define	atomic_is_lock_free(obj) \
+	__atomic_is_lock_free(sizeof((obj)->__val))
+#else
+#define	atomic_is_lock_free(obj) \
+	(sizeof((obj)->__val) <= sizeof(void *))
 #endif
 
 /*
@@ -174,38 +185,64 @@ typedef _Atomic(__uintmax_t)		atomic_uin
 #if defined(__CLANG_ATOMICS)
 #define	atomic_compare_exchange_strong_explicit(object, expected,	\
     desired, success, failure)						\
-	__atomic_compare_exchange_strong(object, expected, desired,	\
+	__c11_atomic_compare_exchange_strong(object, expected, desired,	\
 	    success, failure)
 #define	atomic_compare_exchange_weak_explicit(object, expected,		\
     desired, success, failure)						\
-	__atomic_compare_exchange_weak(object, expected, desired,	\
+	__c11_atomic_compare_exchange_weak(object, expected, desired,	\
 	    success, failure)
 #define	atomic_exchange_explicit(object, desired, order)		\
-	__atomic_exchange(object, desired, order)
+	__c11_atomic_exchange(object, desired, order)
 #define	atomic_fetch_add_explicit(object, operand, order)		\
-	__atomic_fetch_add(object, operand, order)
+	__c11_atomic_fetch_add(object, operand, order)
 #define	atomic_fetch_and_explicit(object, operand, order)		\
-	__atomic_fetch_and(object, operand, order)
+	__c11_atomic_fetch_and(object, operand, order)
 #define	atomic_fetch_or_explicit(object, operand, order)		\
-	__atomic_fetch_or(object, operand, order)
+	__c11_atomic_fetch_or(object, operand, order)
 #define	atomic_fetch_sub_explicit(object, operand, order)		\
-	__atomic_fetch_sub(object, operand, order)
+	__c11_atomic_fetch_sub(object, operand, order)
 #define	atomic_fetch_xor_explicit(object, operand, order)		\
-	__atomic_fetch_xor(object, operand, order)
+	__c11_atomic_fetch_xor(object, operand, order)
 #define	atomic_load_explicit(object, order)				\
-	__atomic_load(object, order)
+	__c11_atomic_load(object, order)
 #define	atomic_store_explicit(object, desired, order)			\
-	__atomic_store(object, desired, order)
+	__c11_atomic_store(object, desired, order)
 #elif defined(__GNUC_ATOMICS)
 #define	atomic_compare_exchange_strong_explicit(object, expected,	\
+    desired, success, failure)						\
+	__atomic_compare_exchange_n(&(object)->__val, expected,		\
+	    desired, 0, success, failure)
+#define	atomic_compare_exchange_weak_explicit(object, expected,		\
+    desired, success, failure)						\
+	__atomic_compare_exchange_n(&(object)->__val, expected,		\
+	    desired, 1, success, failure)
+#define	atomic_exchange_explicit(object, desired, order)		\
+	__atomic_exchange_n(&(object)->__val, desired, order)
+#define	atomic_fetch_add_explicit(object, operand, order)		\
+	__atomic_fetch_add(&(object)->__val, operand, order)
+#define	atomic_fetch_and_explicit(object, operand, order)		\
+	__atomic_fetch_and(&(object)->__val, operand, order)
+#define	atomic_fetch_or_explicit(object, operand, order)		\
+	__atomic_fetch_or(&(object)->__val, operand, order)
+#define	atomic_fetch_sub_explicit(object, operand, order)		\
+	__atomic_fetch_sub(&(object)->__val, operand, order)
+#define	atomic_fetch_xor_explicit(object, operand, order)		\
+	__atomic_fetch_xor(&(object)->__val, operand, order)
+#define	atomic_load_explicit(object, order)				\
+	__atomic_load_n(&(object)->__val, order)
+#define	atomic_store_explicit(object, desired, order)			\
+	__atomic_store_n(&(object)->__val, desired, order)
+#else
+#define	atomic_compare_exchange_strong_explicit(object, expected,	\
     desired, success, failure) ({					\
 	__typeof__((object)->__val) __v;				\
-	__v =								\
-	__sync_val_compare_and_swap((__typeof(&((object)->__val)))object,\
-		*expected, desired);					\
-	*expected = __v;						\
-	(*expected == __v);						\
-	})
+	_Bool __r;							\
+	__v = __sync_val_compare_and_swap(&(object)->__val,		\
+	    *(expected), desired);					\
+	__r = *(expected) == __v;					\
+	*(expected) = __v;						\
+	__r;								\
+})
 
 #define	atomic_compare_exchange_weak_explicit(object, expected,		\
     desired, success, failure)						\
@@ -214,7 +251,7 @@ typedef _Atomic(__uintmax_t)		atomic_uin
 #if __has_builtin(__sync_swap)
 /* Clang provides a full-barrier atomic exchange - use it if available. */
 #define atomic_exchange_explicit(object, desired, order)		\
-	__sync_swap(&(object)->value, desired)
+	__sync_swap(&(object)->__val, desired)
 #else
 /*
  * __sync_lock_test_and_set() is only an acquire barrier in theory (although in
@@ -223,7 +260,7 @@ typedef _Atomic(__uintmax_t)		atomic_uin
  */
 #define	atomic_exchange_explicit(object, desired, order) ({		\
 	__typeof__((object)->__val) __v;				\
-	__v = __sync_lock_test_and_set(object, desired);		\
+	__v = __sync_lock_test_and_set(&(object)->__val, desired);	\
 	__sync_synchronize();						\
 	__v;								\
 })
@@ -278,9 +315,9 @@ typedef _Atomic(__uintmax_t)		atomic_uin
  * 7.17.8 Atomic flag type and operations.
  */
 
-typedef atomic_bool		atomic_flag;
+typedef atomic_bool			atomic_flag;
 
-#define	ATOMIC_FLAG_INIT	ATOMIC_VAR_INIT(0)
+#define	ATOMIC_FLAG_INIT		ATOMIC_VAR_INIT(0)
 
 #define	atomic_flag_clear_explicit(object, order)			\
 	atomic_store_explicit(object, 0, order)
@@ -288,9 +325,8 @@ typedef atomic_bool		atomic_flag;
 	atomic_compare_exchange_strong_explicit(object, 0, 1, order, order)
 
 #define	atomic_flag_clear(object)					\
-	atomic_flag_clear_explicit(object, 0, memory_order_seq_cst)
+	atomic_flag_clear_explicit(object, memory_order_seq_cst)
 #define	atomic_flag_test_and_set(object)				\
-	atomic_flag_test_and_set_explicit(object, 0, 1,			\
-	    memory_order_seq_cst, memory_order_seq_cst)
+	atomic_flag_test_and_set_explicit(object, memory_order_seq_cst)
 
 #endif /* !_STDATOMIC_H_ */

Modified: stable/9/include/tgmath.h
==============================================================================
--- stable/9/include/tgmath.h	Wed May 30 18:05:48 2012	(r236325)
+++ stable/9/include/tgmath.h	Wed May 30 19:21:54 2012	(r236326)
@@ -2,6 +2,9 @@
  * Copyright (c) 2004 Stefan Farfeleder.
  * All rights reserved.
  *
+ * Copyright (c) 2012 Ed Schouten <ed at FreeBSD.org>
+ * All rights reserved.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -33,64 +36,104 @@
 #include <math.h>
 
 /*
- * This implementation of <tgmath.h> requires two implementation-dependent
- * macros to be defined:
- * __tg_impl_simple(x, y, z, fn, fnf, fnl, ...)
+ * This implementation of <tgmath.h> uses the two following macros,
+ * which are based on the macros described in C11 proposal N1404:
+ * __tg_impl_simple(x, y, z, fnl, fn, fnf, ...)
  *	Invokes fnl() if the corresponding real type of x, y or z is long
  *	double, fn() if it is double or any has an integer type, and fnf()
  *	otherwise.
- * __tg_impl_full(x, y, z, fn, fnf, fnl, cfn, cfnf, cfnl, ...)
- *	Invokes [c]fnl() if the corresponding real type of x, y or z is long
+ * __tg_impl_full(x, y, cfnl, cfn, cfnf, fnl, fn, fnf, ...)
+ *	Invokes [c]fnl() if the corresponding real type of x or y is long
  *	double, [c]fn() if it is double or any has an integer type, and
  *	[c]fnf() otherwise.  The function with the 'c' prefix is called if
- *	any of x, y or z is a complex number.
+ *	any of x or y is a complex number.
  * Both macros call the chosen function with all additional arguments passed
  * to them, as given by __VA_ARGS__.
  *
  * Note that these macros cannot be implemented with C's ?: operator,
  * because the return type of the whole expression would incorrectly be long
  * double complex regardless of the argument types.
+ *
+ * The structure of the C11 implementation of these macros can in
+ * principle be reused for non-C11 compilers, but due to an integer
+ * promotion bug for complex types in GCC 4.2, simply let non-C11
+ * compilers use an inefficient yet reliable version.
  */
 
-#if __GNUC_PREREQ__(3, 1)
-#define	__tg_type(e, t)	__builtin_types_compatible_p(__typeof__(e), t)
-#define	__tg_type3(e1, e2, e3, t)					\
-	(__tg_type(e1, t) || __tg_type(e2, t) || __tg_type(e3, t))
-#define	__tg_type_corr(e1, e2, e3, t)					\
-	(__tg_type3(e1, e2, e3, t) || __tg_type3(e1, e2, e3, t _Complex))
-#define	__tg_integer(e1, e2, e3)					\
-	(((__typeof__(e1))1.5 == 1) || ((__typeof__(e2))1.5 == 1) ||	\
-	    ((__typeof__(e3))1.5 == 1))
-#define	__tg_is_complex(e1, e2, e3)					\
-	(__tg_type3(e1, e2, e3, float _Complex) ||			\
-	    __tg_type3(e1, e2, e3, double _Complex) ||			\
-	    __tg_type3(e1, e2, e3, long double _Complex) ||		\
-	    __tg_type3(e1, e2, e3, __typeof__(_Complex_I)))
-
-#define	__tg_impl_simple(x, y, z, fn, fnf, fnl, ...)			\
-	__builtin_choose_expr(__tg_type_corr(x, y, z, long double),	\
-	    fnl(__VA_ARGS__), __builtin_choose_expr(			\
-		__tg_type_corr(x, y, z, double) || __tg_integer(x, y, z),\
-		fn(__VA_ARGS__), fnf(__VA_ARGS__)))
-
-#define	__tg_impl_full(x, y, z, fn, fnf, fnl, cfn, cfnf, cfnl, ...)	\
-	__builtin_choose_expr(__tg_is_complex(x, y, z),			\
-	    __tg_impl_simple(x, y, z, cfn, cfnf, cfnl, __VA_ARGS__),	\
-	    __tg_impl_simple(x, y, z, fn, fnf, fnl, __VA_ARGS__))
-
-#else	/* __GNUC__ */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define	__tg_generic(x, cfnl, cfn, cfnf, fnl, fn, fnf)			\
+	_Generic(x,							\
+		long double _Complex: cfnl,				\
+		double _Complex: cfn,					\
+		float _Complex: cfnf,					\
+		long double: fnl,					\
+		default: fn,						\
+		float: fnf						\
+	)
+#define	__tg_type(x)							\
+	__tg_generic(x, (long double _Complex)0, (double _Complex)0,	\
+	    (float _Complex)0, (long double)0, (double)0, (float)0)
+#define	__tg_impl_simple(x, y, z, fnl, fn, fnf, ...)			\
+	__tg_generic(							\
+	    __tg_type(x) + __tg_type(y) + __tg_type(z),			\
+	    fnl, fn, fnf, fnl, fn, fnf)(__VA_ARGS__)
+#define	__tg_impl_full(x, y, cfnl, cfn, cfnf, fnl, fn, fnf, ...)	\
+	__tg_generic(							\
+	    __tg_type(x) + __tg_type(y),				\
+	    cfnl, cfn, cfnf, fnl, fn, fnf)(__VA_ARGS__)
+#elif defined(__generic)
+#define	__tg_generic_simple(x, fnl, fn, fnf)				\
+	__generic(x, long double _Complex, fnl,				\
+	    __generic(x, double _Complex, fn,				\
+	        __generic(x, float _Complex, fnf,			\
+	            __generic(x, long double, fnl,			\
+	                __generic(x, float, fnf, fn)))))
+#define	__tg_impl_simple(x, y, z, fnl, fn, fnf, ...)			\
+	__tg_generic_simple(x,						\
+	    __tg_generic_simple(y,					\
+	        __tg_generic_simple(z, fnl, fnl, fnl),			\
+	        __tg_generic_simple(z, fnl, fnl, fnl),			\
+	        __tg_generic_simple(z, fnl, fnl, fnl)),			\
+	    __tg_generic_simple(y,					\
+	        __tg_generic_simple(z, fnl, fnl, fnl),			\
+	        __tg_generic_simple(z, fnl, fn , fn ),			\
+	        __tg_generic_simple(z, fnl, fn , fn )),			\
+	    __tg_generic_simple(y,					\
+	        __tg_generic_simple(z, fnl, fnl, fnl),			\
+	        __tg_generic_simple(z, fnl, fn , fn ),			\
+	        __tg_generic_simple(z, fnl, fn , fnf)))(__VA_ARGS__)
+#define	__tg_generic_full(x, cfnl, cfn, cfnf, fnl, fn, fnf)		\
+	__generic(x, long double _Complex, cfnl,			\
+	    __generic(x, double _Complex, cfn,				\
+	        __generic(x, float _Complex, cfnf,			\
+	            __generic(x, long double, fnl,			\
+	                __generic(x, float, fnf, fn)))))
+#define	__tg_impl_full(x, y, cfnl, cfn, cfnf, fnl, fn, fnf, ...)	\
+	__tg_generic_full(x,						\
+	    __tg_generic_full(y, cfnl, cfnl, cfnl, cfnl, cfnl, cfnl),	\
+	    __tg_generic_full(y, cfnl, cfn , cfn , cfnl, cfn , cfn ),	\
+	    __tg_generic_full(y, cfnl, cfn , cfnf, cfnl, cfn , cfnf),	\
+	    __tg_generic_full(y, cfnl, cfnl, cfnl, fnl , fnl , fnl ),	\
+	    __tg_generic_full(y, cfnl, cfn , cfn , fnl , fn  , fn  ),	\
+	    __tg_generic_full(y, cfnl, cfn , cfnf, fnl , fn  , fnf ))	\
+	    (__VA_ARGS__)
+#else
 #error "<tgmath.h> not implemented for this compiler"
-#endif	/* !__GNUC__ */
+#endif
 
 /* Macros to save lots of repetition below */
 #define	__tg_simple(x, fn)						\
-	__tg_impl_simple(x, x, x, fn, fn##f, fn##l, x)
+	__tg_impl_simple(x, x, x, fn##l, fn, fn##f, x)
 #define	__tg_simple2(x, y, fn)						\
-	__tg_impl_simple(x, x, y, fn, fn##f, fn##l, x, y)
+	__tg_impl_simple(x, x, y, fn##l, fn, fn##f, x, y)
+#define	__tg_simple3(x, y, z, fn)					\
+	__tg_impl_simple(x, y, z, fn##l, fn, fn##f, x, y, z)
 #define	__tg_simplev(x, fn, ...)					\
-	__tg_impl_simple(x, x, x, fn, fn##f, fn##l, __VA_ARGS__)
+	__tg_impl_simple(x, x, x, fn##l, fn, fn##f, __VA_ARGS__)
 #define	__tg_full(x, fn)						\
-	__tg_impl_full(x, x, x, fn, fn##f, fn##l, c##fn, c##fn##f, c##fn##l, x)
+	__tg_impl_full(x, x, c##fn##l, c##fn, c##fn##f, fn##l, fn, fn##f, x)
+#define	__tg_full2(x, y, fn)						\
+	__tg_impl_full(x, y, c##fn##l, c##fn, c##fn##f, fn##l, fn, fn##f, x, y)
 
 /* 7.22#4 -- These macros expand to real or complex functions, depending on
  * the type of their arguments. */
@@ -108,13 +151,12 @@
 #define	tanh(x)		__tg_full(x, tanh)
 #define	exp(x)		__tg_full(x, exp)
 #define	log(x)		__tg_full(x, log)
-#define	pow(x, y)	__tg_impl_full(x, x, y, pow, powf, powl,	\
-			    cpow, cpowf, cpowl, x, y)
+#define	pow(x, y)	__tg_full2(x, y, pow)
 #define	sqrt(x)		__tg_full(x, sqrt)
 
 /* "The corresponding type-generic macro for fabs and cabs is fabs." */
-#define	fabs(x)		__tg_impl_full(x, x, x, fabs, fabsf, fabsl,	\
-    			    cabs, cabsf, cabsl, x)
+#define	fabs(x)		__tg_impl_full(x, x, cabsl, cabs, cabsf,	\
+    			    fabsl, fabs, fabsf, x)
 
 /* 7.22#5 -- These macros are only defined for arguments with real type. */
 #define	atan2(x, y)	__tg_simple2(x, y, atan2)
@@ -127,7 +169,7 @@
 #define	expm1(x)	__tg_simple(x, expm1)
 #define	fdim(x, y)	__tg_simple2(x, y, fdim)
 #define	floor(x)	__tg_simple(x, floor)
-#define	fma(x, y, z)	__tg_impl_simple(x, y, z, fma, fmaf, fmal, x, y, z)
+#define	fma(x, y, z)	__tg_simple3(x, y, z, fma)
 #define	fmax(x, y)	__tg_simple2(x, y, fmax)
 #define	fmin(x, y)	__tg_simple2(x, y, fmin)
 #define	fmod(x, y)	__tg_simple2(x, y, fmod)
@@ -148,8 +190,8 @@
 #define	nextafter(x, y)	__tg_simple2(x, y, nextafter)
 #define	nexttoward(x, y) __tg_simplev(x, nexttoward, x, y)
 #define	remainder(x, y)	__tg_simple2(x, y, remainder)
-#define	remquo(x, y, z)	__tg_impl_simple(x, x, y, remquo, remquof,	\
-			    remquol, x, y, z)
+#define	remquo(x, y, z)	__tg_impl_simple(x, x, y, remquol, remquo,	\
+			    remquof, x, y, z)
 #define	rint(x)		__tg_simple(x, rint)
 #define	round(x)	__tg_simple(x, round)
 #define	scalbn(x, y)	__tg_simplev(x, scalbn, x, y)


More information about the svn-src-stable-9 mailing list