From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/6474 Path: news.gmane.org!not-for-mail From: Joakim Sindholt Newsgroups: gmane.linux.lib.musl.general Subject: [PATCH] Add stdatomic.h for clang>=3.1 and gcc>=4.1 Date: Sun, 9 Nov 2014 13:53:16 +0100 Message-ID: <386bdfe0.dNq.dMV.22.ce88IE@mailjet.com> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org X-Trace: ger.gmane.org 1415538752 18082 80.91.229.3 (9 Nov 2014 13:12:32 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 9 Nov 2014 13:12:32 +0000 (UTC) Cc: Joakim Sindholt To: musl@lists.openwall.com Original-X-From: musl-return-6487-gllmg-musl=m.gmane.org@lists.openwall.com Sun Nov 09 14:12:27 2014 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1XnSI4-0008Ru-6z for gllmg-musl@m.gmane.org; Sun, 09 Nov 2014 14:12:24 +0100 Original-Received: (qmail 15816 invoked by uid 550); 9 Nov 2014 13:12:23 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 31926 invoked from network); 9 Nov 2014 12:53:33 -0000 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/simple; q=dns/txt; d=zhasha.com; i=opensource@zhasha.com; s=mailjet; h=domainkey-signature:message-id:from:to:subject:date:cc:list-unsubscribe; bh=JW/1UvrskSvVtYWMYePzl0uMfi8=; b=dhMRA+ihTffdEw0IfpSnpNVumrpB2RMebY4y/Hoe1+ZHyjVFAT7rqG5b5jSGShTScQPPXa2yQmOqOlcGqcqckdxigDnZr4fiWGmWLtWERp9gp9PXrlkjvTmowq0d+fqZ2BDGIjLVVvLaNZIgslkHs63GNlhmclv3SwBjFzQJZmM= Domainkey-Signature: a=rsa-sha1; c=simple; q=dns; d=zhasha.com; s=mailjet; h=message-id:from:to:subject:date:cc:list-unsubscribe; b=iz+uQrjIiAykqz8VwdRB6UdBC6UVEq2Lch3ib0mYmgD6vlt83NekeEx26LNM5CIWZqnzjmDNV+LjJ3Ydg+pNIeZ3FbZJJgdxRyxyPUkbqVXFGcmihWP6L/j1qDUIqLGpBw0oTqAlHEH0N7p0NAi9xQWk7z5r3tghGo7OmQeSYeU= Xref: news.gmane.org gmane.linux.lib.musl.general:6474 Archived-At: GCC and Clang ship their own stdatomic.h headers but not for all the versions mentioned above. They ship many other standard headers too that musl also ships (stdbool/def/int/...). In the end musl should be a complete libc with all standard headers and this is one of them. It is up to the individual programmer to ensure that his or her compiler is properly supported by for example checking __STD_NO_ATOMICS__ and __STDC_VERSION__ >= 201112L. For clang the support is complete for versions >= 3.1. GCC added the __atomic functions in 4.7 but not _Atomic until 4.9 so from 4.1 it will work correctly so long as you don't use VLAs together with things like the ++ operator in arguments and is subject to the same limitations as 4.7. From 4.7 it will work as inteded so long as you only use the function-like-macros and from 4.9 it will have full support. This patch has only been tested with clang. The __typeof__ magic is to avoid changes to alltypes. It should be changed before committing this to musl. This patch is only for people who want to test themselves. This work is released to the Public Domain. --- include/stdatomic.h | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 include/stdatomic.h diff --git a/include/stdatomic.h b/include/stdatomic.h new file mode 100644 index 0000000..3a61e47 --- /dev/null +++ b/include/stdatomic.h @@ -0,0 +1,287 @@ +#ifndef _STDATOMIC_H +#define _STDATOMIC_H + +#ifndef __has_extension +#define __has_extension(x) 0 +#define __musl_has_extension 1 +#endif + +#if defined(__clang__) && __has_extension(c_atomic) + +#define kill_dependency(y) (y) + +#define ATOMIC_VAR_INIT(value) (value) +#define atomic_init(obj, value) __c11_atomic_init(obj, value) + +#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(obj)) +#define __atomic_type_is_lock_free(type) \ + __c11_atomic_is_lock_free(sizeof(type)) + +#define atomic_thread_fence(order) __c11_atomic_thread_fence(order) +#define atomic_signal_fence(order) __c11_atomic_signal_fence(order) + +#define atomic_store_explicit(object, desired, order) \ + __c11_atomic_store(object, desired, order) +#define atomic_load_explicit(object, order) \ + __c11_atomic_load(object, order) + +#define atomic_exchange_explicit(object, value, order) \ + __c11_atomic_exchange(object, value, order) +#define atomic_compare_exchange_strong_explicit(object, expected, desired, \ + success, failure) \ + __c11_atomic_compare_exchange_strong(object, expected, desired, \ + success, failure) +#define atomic_compare_exchange_weak_explicit(object, expected, desired, \ + success, failure) \ + __c11_atomic_compare_exchange_weak(object, expected, desired, \ + success, failure) + +#define atomic_fetch_add_explicit(object, operand, order) \ + __c11_atomic_fetch_add(object, operand, order) +#define atomic_fetch_sub_explicit(object, operand, order) \ + __c11_atomic_fetch_sub(object, operand, order) +#define atomic_fetch_or_explicit(object, operand, order) \ + __c11_atomic_fetch_or(object, operand, order) +#define atomic_fetch_xor_explicit(object, operand, order) \ + __c11_atomic_fetch_xor(object, operand, order) +#define atomic_fetch_and_explicit(object, operand, order) \ + __c11_atomic_fetch_and(object, operand, order) + +#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || __GNUC__ > 4 + +#define ATOMIC_VAR_INIT(value) (value) +#define atomic_init(obj, value) do { *(obj) = (value); } while (0) + +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4 +#define kill_dependency(y) __extension__({__auto_type __y = (y); __y;}) + +#define atomic_is_lock_free(obj) \ + __extension__({ \ + __auto_type __obj = (obj); \ + __atomic_is_lock_free(sizeof(*__obj), __obj); \ + }) +#else +#define __NEED__Atomic + +#define kill_dependency(y) (y) + +#define atomic_is_lock_free(obj) \ + __atomic_is_lock_free(sizeof(*(obj)), (void *)0) +#endif + +#define __atomic_type_is_lock_free(type) \ + __atomic_always_lock_free(sizeof(type), (void *)0) + +#define atomic_thread_fence(order) __atomic_thread_fence(order) +#define atomic_signal_fence(order) __atomic_signal_fence(order) + +#define atomic_store_explicit(object, value, order) \ + __atomic_store_n(object, value, order) +#define atomic_load_explicit(object, order) \ + __atomic_load_n(object, order) + +#define atomic_exchange_explicit(object, desired, order) \ + __atomic_exchange_n(object, desired, order) +#define atomic_compare_exchange_strong_explicit(object, expected, desired, \ + success, failure) \ + __atomic_compare_exchange_n(object, expected, desired, 0, success, failure) +#define atomic_compare_exchange_weak_explicit(object, expected, desired, \ + success, failure) \ + __atomic_compare_exchange_n(object, expected, desired, 1, success, failure) + +#define atomic_fetch_add_explicit(object, operand, order) \ + __atomic_fetch_add(object, operand, order) +#define atomic_fetch_sub_explicit(object, operand, order) \ + __atomic_fetch_sub(object, operand, order) +#define atomic_fetch_or_explicit(object, operand, order) \ + __atomic_fetch_or(object, operand, order) +#define atomic_fetch_xor_explicit(object, operand, order) \ + __atomic_fetch_xor(object, operand, order) +#define atomic_fetch_and_explicit(object, operand, order) \ + __atomic_fetch_and(object, operand, order) + +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 1 + +#define __NEED__Atomic + +#define kill_dependency(y) (y) + +#define ATOMIC_VAR_INIT(value) (value) +#define atomic_init(obj, value) do { *(obj) = (value); } while (0) + +#define atomic_is_lock_free(obj) (sizeof(obj) <= sizeof(void *)) +#define __atomic_type_is_lock_free(type) (sizeof(type) <= sizeof(void *)) + +#define atomic_thread_fence(order) __sync_synchronize() +#define atomic_signal_fence(order) __asm__ volatile ("" : : : "memory") + +/* for GCC < 4.7 some concessions are made. First off, ordering is ignored and + * always treated as a full seq_cst barrier. Second, although these are + * described as "generic functions" GCC < 4.7 cannot support uses such as: + * int n = 4; + * atomic_int arr[n]; + * atomic_int *i = arr; + * if (atomic_compare_exchange_strong(i++, ...)) {... + * because of the liberal use of the __typeof__ extension. + * Furthermore, GCC specified that test_and_set doesn't necessarily support + * arbitrary values. It's used as both exchange and store here. Be careful. */ + +#define atomic_store_explicit(object, value, order) \ + do { \ + __sync_lock_test_and_set(object, value); \ + __sync_synchronize(); \ + while (0) +#define atomic_load_explicit(object, order) \ + __atomic_fetch_and_add(object, 0) + +#define atomic_exchange_explicit(object, desired, order) \ + __extension__({ \ + __typeof__(*(object)) __ret; \ + __ret = __sync_lock_test_and_set(object, desired); \ + __sync_synchronize(); \ + __ret; \ + }) +#define atomic_compare_exchange_strong_explicit(object, expected, desired, \ + success, failure) \ + __extension__({ \ + __typeof__(object) __expected = (expected); \ + __typeof__(*__expected) __prev; \ + _Bool __ret; \ + __prev = __sync_val_compare_and_swap(object, *__expected, desired); \ + __ret = (__prev == *__expected); \ + *__expected = __prev; \ + __ret; \ + }) +#define atomic_compare_exchange_weak_explicit(object, expected, desired, \ + success, failure) \ + atomic_compare_exchange_strong_explicit(object, expected, desired, \ + success, failure) + +#define atomic_fetch_add_explicit(object, operand, order) \ + __sync_fetch_and_add(object, operand) +#define atomic_fetch_sub_explicit(object, operand, order) \ + __sync_fetch_and_sub(object, operand) +#define atomic_fetch_or_explicit(object, operand, order) \ + __sync_fetch_and_or(object, operand) +#define atomic_fetch_xor_explicit(object, operand, order) \ + __sync_fetch_and_xor(object, operand) +#define atomic_fetch_and_explicit(object, operand, order) \ + __sync_fetch_and_and(object, operand) + +#else + +#error "Musl's stdatomic.h does not support your compiler" + +#endif + +#ifdef __musl_has_extension +#undef __musl_has_extension +#undef __has_extension +#endif + +#ifdef __NEED__Atomic +#undef __NEED__Atomic +#define _Atomic volatile +#define volatile(x) x volatile +#endif + +typedef enum { + memory_order_relaxed = 0, + memory_order_consume = 1, + memory_order_acquire = 2, + memory_order_release = 3, + memory_order_acq_rel = 4, + memory_order_seq_cst = 5 +} memory_order; + +typedef _Atomic _Bool atomic_bool; +typedef _Atomic char atomic_char; +typedef _Atomic signed char atomic_schar; +typedef _Atomic short atomic_short; +typedef _Atomic int atomic_int; +typedef _Atomic long atomic_long; +typedef _Atomic long long atomic_llong; +typedef _Atomic unsigned char atomic_uchar; +typedef _Atomic unsigned short atomic_ushort; +typedef _Atomic unsigned int atomic_uint; +typedef _Atomic unsigned long atomic_ulong; +typedef _Atomic unsigned long long atomic_ullong; +typedef _Atomic unsigned short atomic_char16_t; +typedef _Atomic unsigned atomic_char32_t; +typedef _Atomic __typeof__(L'\0') atomic_wchar_t; +typedef _Atomic signed char atomic_int_least8_t; +typedef _Atomic short atomic_int_least16_t; +typedef _Atomic int atomic_int_least32_t; +typedef _Atomic __typeof__(0x100000000) atomic_int_least64_t; +typedef _Atomic signed char atomic_int_fast8_t; +typedef _Atomic int atomic_int_fast16_t; +typedef _Atomic int atomic_int_fast32_t; +typedef _Atomic __typeof__(0x100000000) atomic_int_fast64_t; +typedef _Atomic unsigned char atomic_uint_least8_t; +typedef _Atomic unsigned short atomic_uint_least16_t; +typedef _Atomic unsigned int atomic_uint_least32_t; +typedef _Atomic __typeof__(0x100000000U) atomic_uint_least64_t; +typedef _Atomic unsigned char atomic_uint_fast8_t; +typedef _Atomic unsigned atomic_uint_fast16_t; +typedef _Atomic unsigned atomic_uint_fast32_t; +typedef _Atomic __typeof__(0x100000000U) atomic_uint_fast64_t; +typedef _Atomic __typeof__((char *)0 - (char *)0) atomic_intptr_t; +typedef _Atomic __typeof__(sizeof(0)) atomic_uintptr_t; +typedef _Atomic __typeof__(sizeof(0)) atomic_size_t_t; +typedef _Atomic __typeof__((char *)0 - (char *)0) atomic_ptrdiff_t; +typedef _Atomic __typeof__((char *)0 - (char *)0) atomic_intmax_t; +typedef _Atomic __typeof__(sizeof(0)) atomic_uintmax_t; + +#define ATOMIC_BOOL_LOCK_FREE __atomic_type_is_lock_free(_Bool) +#define ATOMIC_CHAR_LOCK_FREE __atomic_type_is_lock_free(char) +#define ATOMIC_CHAR16_T_LOCK_FREE __atomic_type_is_lock_free(unsigned short) +#define ATOMIC_CHAR32_T_LOCK_FREE __atomic_type_is_lock_free(unsigned) +#define ATOMIC_WCHAR_T_LOCK_FREE __atomic_type_is_lock_free(__typeof__(L'\0')) +#define ATOMIC_SHORT_LOCK_FREE __atomic_type_is_lock_free(short) +#define ATOMIC_INT_LOCK_FREE __atomic_type_is_lock_free(int) +#define ATOMIC_LONG_LOCK_FREE __atomic_type_is_lock_free(long) +#define ATOMIC_LLONG_LOCK_FREE __atomic_type_is_lock_free(long long) +#define ATOMIC_POINTER_LOCK_FREE __atomic_type_is_lock_free(void *) + +#define atomic_store(object, desired) \ + atomic_store_explicit(object, desired, memory_order_seq_cst) +#define atomic_load(object) \ + atomic_load_explicit(object, memory_order_seq_cst) + +#define atomic_exchange(object, desired) \ + atomic_exchange_explicit(object, desired, memory_order_seq_cst) +#define atomic_compare_exchange_strong(object, expected, desired) \ + atomic_compare_exchange_strong_explicit(object, expected, desired, \ + memory_order_seq_cst, \ + memory_order_seq_cst) +#define atomic_compare_exchange_weak(object, expected, desired) \ + atomic_compare_exchange_weak_explicit(object, expected, desired, \ + memory_order_seq_cst, \ + memory_order_seq_cst) + +#define atomic_fetch_add(object, operand) \ + atomic_fetch_add_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_sub(object, operand) \ + atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_or(object, operand) \ + atomic_fetch_or_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_xor(object, operand) \ + atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst) +#define atomic_fetch_and(object, operand) \ + atomic_fetch_and_explicit(object, operand, memory_order_seq_cst) + +typedef _Atomic _Bool atomic_flag; + +#define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0) + +#define atomic_flag_test_and_set(object) \ + atomic_exchange(object, 1) +#define atomic_flag_test_and_set_explicit(object, order) \ + atomic_exchange_explicit(object, 1, order) + +#define atomic_flag_clear(object) \ + atomic_store(object, 0) +#define atomic_flag_clear_explicit(object, order) \ + atomic_store_explicit(object, 0, order) + +#endif -- 2.0.4