diff options
| author | JF Bastien <jfb@google.com> | 2016-08-01 19:27:08 +0000 |
|---|---|---|
| committer | JF Bastien <jfb@google.com> | 2016-08-01 19:27:08 +0000 |
| commit | a2b1c14911d042b4a2c0b9b8d78f804f12d2e434 (patch) | |
| tree | 94b0b142716e7091a6d07d1d5b1099793ea1ffba /libcxx/test | |
| parent | 755220bcefcf90ebbcc54f03392a809d84d64146 (diff) | |
| download | bcm5719-llvm-a2b1c14911d042b4a2c0b9b8d78f804f12d2e434.tar.gz bcm5719-llvm-a2b1c14911d042b4a2c0b9b8d78f804f12d2e434.zip | |
libc++: test lock-free atomic alignment
Summary:
libc++ implements std::atomic<_Tp> using __atomic_base<_Tp> with
`mutable _Atomic(_Tp) __a_`. That member must be suitably aligned on
relevant ISAs for instructions such as cmpxchg to work properly, but
this alignment isn't checked anywhere. __atomic_base's implementation
relies on _Atomic doing "the right thing" since it's under the
compiler's control, and only the compiler knows about lock-freedom and
instruction generation. This test makes sure that the compiler isn't
breaking libc++'s expectations.
I'm looking at a few odd things in the C++ standard, and will have a few
other fixes around this area in the future.
This requires building with `-DLIBCXX_HAS_ATOMIC_LIB=True`, the test
marks the dependency as REQUIRES and won't be run without.
Reviewers: cfe-commits
Subscribers: EricWF, mclow.lists
Differential Revision: http://reviews.llvm.org/D22073
llvm-svn: 277368
Diffstat (limited to 'libcxx/test')
| -rw-r--r-- | libcxx/test/libcxx/atomics/atomics.align/align.pass.sh.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/libcxx/test/libcxx/atomics/atomics.align/align.pass.sh.cpp b/libcxx/test/libcxx/atomics/atomics.align/align.pass.sh.cpp new file mode 100644 index 00000000000..505fe469aa0 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.align/align.pass.sh.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: libcpp-has-no-threads, c++98, c++03 +// REQUIRES: libatomic +// RUN: %build -latomic +// RUN: %run + +// <atomic> + +// Verify that the content of atomic<T> is properly aligned if the type is +// lock-free. This can't be observed through the atomic<T> API. It is +// nonetheless required for correctness of the implementation: lock-free implies +// that ISA instructions are used, and these instructions assume "suitable +// alignment". Supported architectures all require natural alignment for +// lock-freedom (e.g. load-linked / store-conditional, or cmpxchg). + +#include <atomic> +#include <cassert> + +template <typename T> struct atomic_test : public std::__atomic_base<T> { + atomic_test() { + if (this->is_lock_free()) + assert(alignof(this->__a_) >= sizeof(this->__a_) && + "expected natural alignment for lock-free type"); + } +}; + +int main() { + +// structs and unions can't be defined in the template invocation. +// Work around this with a typedef. +#define CHECK_ALIGNMENT(T) \ + do { \ + typedef T type; \ + atomic_test<type> t; \ + } while (0) + + CHECK_ALIGNMENT(bool); + CHECK_ALIGNMENT(char); + CHECK_ALIGNMENT(signed char); + CHECK_ALIGNMENT(unsigned char); + CHECK_ALIGNMENT(char16_t); + CHECK_ALIGNMENT(char32_t); + CHECK_ALIGNMENT(wchar_t); + CHECK_ALIGNMENT(short); + CHECK_ALIGNMENT(unsigned short); + CHECK_ALIGNMENT(int); + CHECK_ALIGNMENT(unsigned int); + CHECK_ALIGNMENT(long); + CHECK_ALIGNMENT(unsigned long); + CHECK_ALIGNMENT(long long); + CHECK_ALIGNMENT(unsigned long long); + CHECK_ALIGNMENT(std::nullptr_t); + CHECK_ALIGNMENT(void *); + CHECK_ALIGNMENT(float); + CHECK_ALIGNMENT(double); + CHECK_ALIGNMENT(long double); + CHECK_ALIGNMENT(int __attribute__((vector_size(1 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(2 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(4 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(16 * sizeof(int))))); + CHECK_ALIGNMENT(int __attribute__((vector_size(32 * sizeof(int))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(1 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(2 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(4 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(16 * sizeof(float))))); + CHECK_ALIGNMENT(float __attribute__((vector_size(32 * sizeof(float))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(1 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(2 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(4 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(16 * sizeof(double))))); + CHECK_ALIGNMENT(double __attribute__((vector_size(32 * sizeof(double))))); + CHECK_ALIGNMENT(struct Empty {}); + CHECK_ALIGNMENT(struct OneInt { int i; }); + CHECK_ALIGNMENT(struct IntArr2 { int i[2]; }); + CHECK_ALIGNMENT(struct LLIArr2 { long long int i[2]; }); + CHECK_ALIGNMENT(struct LLIArr4 { long long int i[4]; }); + CHECK_ALIGNMENT(struct LLIArr8 { long long int i[8]; }); + CHECK_ALIGNMENT(struct LLIArr16 { long long int i[16]; }); + CHECK_ALIGNMENT(struct Padding { char c; /* padding */ long long int i; }); + CHECK_ALIGNMENT(union IntFloat { int i; float f; }); +} |

