[PATCH] D22073: libc++: test lock-free atomic alignment

JF Bastien via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 6 16:45:26 PDT 2016


jfb created this revision.
jfb added a reviewer: cfe-commits.

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.

http://reviews.llvm.org/D22073

Files:
  test/std/atomics/atomics.align/align.pass.cpp

Index: test/std/atomics/atomics.align/align.pass.cpp
===================================================================
--- /dev/null
+++ test/std/atomics/atomics.align/align.pass.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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
+
+// <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 {});
+  CHECK_ALIGNMENT(struct { int i; });
+  CHECK_ALIGNMENT(struct { int i[2]; });
+  CHECK_ALIGNMENT(struct { long long int i[2]; });
+  CHECK_ALIGNMENT(struct { long long int i[4]; });
+  CHECK_ALIGNMENT(struct { long long int i[8]; });
+  CHECK_ALIGNMENT(struct { long long int i[16]; });
+  CHECK_ALIGNMENT(struct { char c; /* padding */ long long int i; });
+  CHECK_ALIGNMENT(union { int i; float f; });
+}


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D22073.62997.patch
Type: text/x-patch
Size: 4034 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160706/7d1be1b8/attachment-0001.bin>


More information about the cfe-commits mailing list