forked from OSchip/llvm-project
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
This commit is contained in:
parent
755220bcef
commit
a2b1c14911
|
@ -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; });
|
||||
}
|
Loading…
Reference in New Issue