Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-20 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 71934.
tavianator marked an inline comment as done.
tavianator added a comment.

s/indended/intended/


https://reviews.llvm.org/D21803

Files:
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in
  test/thread_local_destruction_order.pass.cpp

Index: test/thread_local_destruction_order.pass.cpp
===
--- test/thread_local_destruction_order.pass.cpp
+++ test/thread_local_destruction_order.pass.cpp
@@ -0,0 +1,56 @@
+//===-- thread_local_destruction_order.pass.cpp ---===//
+//
+// 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: c++98, c++03
+
+#include 
+#include 
+
+int seq = 0;
+
+class OrderChecker {
+public:
+  explicit OrderChecker(int n) : n_{n} { }
+
+  ~OrderChecker() {
+assert(seq++ == n_);
+  }
+
+private:
+  int n_;
+};
+
+template 
+class CreatesThreadLocalInDestructor {
+public:
+  ~CreatesThreadLocalInDestructor() {
+thread_local OrderChecker checker{ID};
+  }
+};
+
+OrderChecker global{7};
+
+void thread_fn() {
+  static OrderChecker fn_static{5};
+  thread_local CreatesThreadLocalInDestructor<2> creates_tl2;
+  thread_local OrderChecker fn_thread_local{1};
+  thread_local CreatesThreadLocalInDestructor<0> creates_tl0;
+}
+
+int main() {
+  static OrderChecker fn_static{6};
+
+  std::thread{thread_fn}.join();
+  assert(seq == 3);
+
+  thread_local OrderChecker fn_thread_local{4};
+  thread_local CreatesThreadLocalInDestructor<3> creates_tl;
+
+  return 0;
+}
Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,133 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
-extern "C" {
 
-#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+  using Dtor = void(*)(void*);
 
-_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
-void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern "C"
+#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
+  // A weak symbol is used to detect this function's presence in the C library
+  // at runtime, even if libc++ is built against an older libc
+  __attribute__((__weak__))
+#endif
+  int __cxa_thread_atexit_impl(Dtor, void*, void*)

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-15 Thread Eric Fiselier via cfe-commits
EricWF accepted this revision.
EricWF added a comment.
This revision is now accepted and ready to land.

LGTM. Thanks for the patch.



Comment at: src/cxa_thread_atexit.cpp:70
@@ +69,3 @@
+
+  void run_dtors(void*) {
+while (auto head = dtors) {

Na I thought I was solving a bug that didn't exist. You give me too much credit.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-15 Thread Tavian Barnes via cfe-commits
tavianator marked 5 inline comments as done.


Comment at: src/cxa_thread_atexit.cpp:70
@@ +69,3 @@
+while (auto head = dtors) {
+  dtors = head->next;
+  head->dtor(head->obj);

EricWF wrote:
> tavianator wrote:
> > EricWF wrote:
> > > tavianator wrote:
> > > > EricWF wrote:
> > > > > There is a bug here. If `head->next == nullptr` and if 
> > > > > `head->dtor(head->obj))` creates a TL variable in the destructor then 
> > > > > that destructor will not be invoked.
> > > > > 
> > > > > Here's an updated test case which catches the bug: 
> > > > > https://gist.github.com/EricWF/3bb50d4f28b91aa28d2adefea0e94a0e
> > > > I can't reproduce that failure here, your exact test case passes (even 
> > > > with `#undef HAVE___CXA_THREAD_ATEXIT_IMPL` and the weak symbol test 
> > > > commented out).
> > > > 
> > > > Tracing the implementation logic, it seems correct.  If `head->next == 
> > > > nullptr` then this line does `dtors = nullptr`.  Then if 
> > > > `head->dtor(head->obj)` registers a new `thread_local`, 
> > > > `__cxa_thread_atexit()` does `head = malloc(...); ... dtors = head;`.  
> > > > Then the next iteration of the loop `while (auto head = dtors) {` picks 
> > > > up that new node.
> > > > 
> > > > Have I missed something?
> > > I can't reproduce this morning either, I must have been doing something 
> > > funny. I'll look at this with a fresh head tomorrow. If I can't find 
> > > anything this will be good to go. Thanks for working on this. 
> > No problem!  I can integrate your updated test case anyway if you want.
> Yeah I would like to see the upgraded test case applied. At least that way 
> we're testing the case in question.
> 
> So I agree with your above analysis of what happens, and that all destructors 
> are correctly called during the first iteration of pthread key destruction. 
> My one issues is that we still register a new non-null key which forces 
> pthread to run the destructor for the key again. I would like to see this 
> fixed.
Yep, done!  I guess that was the point of `thread_alive` from your original 
patch-to-my-patch, sorry for stripping it out.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-15 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 71508.
tavianator added a comment.
Herald added subscribers: mgorny, beanz.

Integrated @EricWF's expanded test case, and avoid an unneeded 
pthread_setspecific() call if the last thread_local's destructor initializes a 
new thread_local.


https://reviews.llvm.org/D21803

Files:
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in
  test/thread_local_destruction_order.pass.cpp

Index: test/thread_local_destruction_order.pass.cpp
===
--- test/thread_local_destruction_order.pass.cpp
+++ test/thread_local_destruction_order.pass.cpp
@@ -0,0 +1,56 @@
+//===-- thread_local_destruction_order.pass.cpp ---===//
+//
+// 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: c++98, c++03
+
+#include 
+#include 
+
+int seq = 0;
+
+class OrderChecker {
+public:
+  explicit OrderChecker(int n) : n_{n} { }
+
+  ~OrderChecker() {
+assert(seq++ == n_);
+  }
+
+private:
+  int n_;
+};
+
+template 
+class CreatesThreadLocalInDestructor {
+public:
+  ~CreatesThreadLocalInDestructor() {
+thread_local OrderChecker checker{ID};
+  }
+};
+
+OrderChecker global{7};
+
+void thread_fn() {
+  static OrderChecker fn_static{5};
+  thread_local CreatesThreadLocalInDestructor<2> creates_tl2;
+  thread_local OrderChecker fn_thread_local{1};
+  thread_local CreatesThreadLocalInDestructor<0> creates_tl0;
+}
+
+int main() {
+  static OrderChecker fn_static{6};
+
+  std::thread{thread_fn}.join();
+  assert(seq == 3);
+
+  thread_local OrderChecker fn_thread_local{4};
+  thread_local CreatesThreadLocalInDestructor<3> creates_tl;
+
+  return 0;
+}
Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,133 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
-extern "C" {
 
-#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+  using Dtor = void(*)(void*);
 
-_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
-void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern "C"
+#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
+  // A weak symbol is used to detect this function's presence in the C library
+  // at runtim

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-14 Thread Eric Fiselier via cfe-commits
EricWF added a comment.

LGTM after addressing the inline comments.



Comment at: src/cxa_thread_atexit.cpp:70
@@ +69,3 @@
+while (auto head = dtors) {
+  dtors = head->next;
+  head->dtor(head->obj);

tavianator wrote:
> EricWF wrote:
> > tavianator wrote:
> > > EricWF wrote:
> > > > There is a bug here. If `head->next == nullptr` and if 
> > > > `head->dtor(head->obj))` creates a TL variable in the destructor then 
> > > > that destructor will not be invoked.
> > > > 
> > > > Here's an updated test case which catches the bug: 
> > > > https://gist.github.com/EricWF/3bb50d4f28b91aa28d2adefea0e94a0e
> > > I can't reproduce that failure here, your exact test case passes (even 
> > > with `#undef HAVE___CXA_THREAD_ATEXIT_IMPL` and the weak symbol test 
> > > commented out).
> > > 
> > > Tracing the implementation logic, it seems correct.  If `head->next == 
> > > nullptr` then this line does `dtors = nullptr`.  Then if 
> > > `head->dtor(head->obj)` registers a new `thread_local`, 
> > > `__cxa_thread_atexit()` does `head = malloc(...); ... dtors = head;`.  
> > > Then the next iteration of the loop `while (auto head = dtors) {` picks 
> > > up that new node.
> > > 
> > > Have I missed something?
> > I can't reproduce this morning either, I must have been doing something 
> > funny. I'll look at this with a fresh head tomorrow. If I can't find 
> > anything this will be good to go. Thanks for working on this. 
> No problem!  I can integrate your updated test case anyway if you want.
Yeah I would like to see the upgraded test case applied. At least that way 
we're testing the case in question.

So I agree with your above analysis of what happens, and that all destructors 
are correctly called during the first iteration of pthread key destruction. My 
one issues is that we still register a new non-null key which forces pthread to 
run the destructor for the key again. I would like to see this fixed.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-08 Thread Tavian Barnes via cfe-commits
tavianator added inline comments.


Comment at: src/cxa_thread_atexit.cpp:70
@@ +69,3 @@
+while (auto head = dtors) {
+  dtors = head->next;
+  head->dtor(head->obj);

EricWF wrote:
> tavianator wrote:
> > EricWF wrote:
> > > There is a bug here. If `head->next == nullptr` and if 
> > > `head->dtor(head->obj))` creates a TL variable in the destructor then 
> > > that destructor will not be invoked.
> > > 
> > > Here's an updated test case which catches the bug: 
> > > https://gist.github.com/EricWF/3bb50d4f28b91aa28d2adefea0e94a0e
> > I can't reproduce that failure here, your exact test case passes (even with 
> > `#undef HAVE___CXA_THREAD_ATEXIT_IMPL` and the weak symbol test commented 
> > out).
> > 
> > Tracing the implementation logic, it seems correct.  If `head->next == 
> > nullptr` then this line does `dtors = nullptr`.  Then if 
> > `head->dtor(head->obj)` registers a new `thread_local`, 
> > `__cxa_thread_atexit()` does `head = malloc(...); ... dtors = head;`.  Then 
> > the next iteration of the loop `while (auto head = dtors) {` picks up that 
> > new node.
> > 
> > Have I missed something?
> I can't reproduce this morning either, I must have been doing something 
> funny. I'll look at this with a fresh head tomorrow. If I can't find anything 
> this will be good to go. Thanks for working on this. 
No problem!  I can integrate your updated test case anyway if you want.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-07 Thread Eric Fiselier via cfe-commits
EricWF added inline comments.


Comment at: src/cxa_thread_atexit.cpp:70
@@ +69,3 @@
+while (auto head = dtors) {
+  dtors = head->next;
+  head->dtor(head->obj);

tavianator wrote:
> EricWF wrote:
> > There is a bug here. If `head->next == nullptr` and if 
> > `head->dtor(head->obj))` creates a TL variable in the destructor then that 
> > destructor will not be invoked.
> > 
> > Here's an updated test case which catches the bug: 
> > https://gist.github.com/EricWF/3bb50d4f28b91aa28d2adefea0e94a0e
> I can't reproduce that failure here, your exact test case passes (even with 
> `#undef HAVE___CXA_THREAD_ATEXIT_IMPL` and the weak symbol test commented 
> out).
> 
> Tracing the implementation logic, it seems correct.  If `head->next == 
> nullptr` then this line does `dtors = nullptr`.  Then if 
> `head->dtor(head->obj)` registers a new `thread_local`, 
> `__cxa_thread_atexit()` does `head = malloc(...); ... dtors = head;`.  Then 
> the next iteration of the loop `while (auto head = dtors) {` picks up that 
> new node.
> 
> Have I missed something?
I can't reproduce this morning either, I must have been doing something funny. 
I'll look at this with a fresh head tomorrow. If I can't find anything this 
will be good to go. Thanks for working on this. 


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-07 Thread Tavian Barnes via cfe-commits
tavianator added inline comments.


Comment at: src/cxa_thread_atexit.cpp:70
@@ +69,3 @@
+while (auto head = dtors) {
+  dtors = head->next;
+  head->dtor(head->obj);

EricWF wrote:
> There is a bug here. If `head->next == nullptr` and if 
> `head->dtor(head->obj))` creates a TL variable in the destructor then that 
> destructor will not be invoked.
> 
> Here's an updated test case which catches the bug: 
> https://gist.github.com/EricWF/3bb50d4f28b91aa28d2adefea0e94a0e
I can't reproduce that failure here, your exact test case passes (even with 
`#undef HAVE___CXA_THREAD_ATEXIT_IMPL` and the weak symbol test commented out).

Tracing the implementation logic, it seems correct.  If `head->next == nullptr` 
then this line does `dtors = nullptr`.  Then if `head->dtor(head->obj)` 
registers a new `thread_local`, `__cxa_thread_atexit()` does `head = 
malloc(...); ... dtors = head;`.  Then the next iteration of the loop `while 
(auto head = dtors) {` picks up that new node.

Have I missed something?


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-06 Thread Eric Fiselier via cfe-commits
EricWF added a comment.

LGTM modulo bug fix.



Comment at: src/cxa_thread_atexit.cpp:70
@@ +69,3 @@
+while (auto head = dtors) {
+  dtors = head->next;
+  head->dtor(head->obj);

There is a bug here. If `head->next == nullptr` and if `head->dtor(head->obj))` 
creates a TL variable in the destructor then that destructor will not be 
invoked.

Here's an updated test case which catches the bug: 
https://gist.github.com/EricWF/3bb50d4f28b91aa28d2adefea0e94a0e


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-06 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 70406.
tavianator added a comment.

Uses a __thread variable to hold the destructor list, as @EricWF suggested.


https://reviews.llvm.org/D21803

Files:
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in
  test/thread_local_destruction_order.pass.cpp

Index: test/thread_local_destruction_order.pass.cpp
===
--- test/thread_local_destruction_order.pass.cpp
+++ test/thread_local_destruction_order.pass.cpp
@@ -0,0 +1,59 @@
+//===-- thread_local_destruction_order.pass.cpp ---===//
+//
+// 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: c++98, c++03
+
+#include 
+#include 
+
+int seq = 0;
+
+class OrderChecker {
+public:
+  explicit OrderChecker(int n) : n_{n} { }
+
+  ~OrderChecker() {
+assert(seq++ == n_);
+  }
+
+private:
+  int n_;
+};
+
+class CreatesThreadLocalInDestructor {
+public:
+  CreatesThreadLocalInDestructor(int n) : n_{n} { }
+
+  ~CreatesThreadLocalInDestructor() {
+thread_local OrderChecker checker{n_};
+  }
+
+private:
+  int n_;
+};
+
+OrderChecker global{6};
+
+void thread_fn() {
+  static OrderChecker fn_static{4};
+  thread_local OrderChecker fn_thread_local{1};
+  thread_local CreatesThreadLocalInDestructor creates_tl{0};
+}
+
+int main() {
+  static OrderChecker fn_static{5};
+
+  std::thread{thread_fn}.join();
+  assert(seq == 2);
+
+  thread_local OrderChecker fn_thread_local{3};
+  thread_local CreatesThreadLocalInDestructor creates_tl{2};
+
+  return 0;
+}
Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,129 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
-extern "C" {
 
-#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+  using Dtor = void(*)(void*);
 
-_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
-void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern "C"
+#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
+  // A weak symbol is used to detect this function's presence in the C library
+  // at runtime, even if libc++ is built against an older libc
+  __attribute__((__weak__))
+#endif
+  int __cxa_thread_atexit_impl(Dtor, 

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-02 Thread Eric Fiselier via cfe-commits
EricWF added inline comments.


Comment at: src/cxa_thread_atexit.cpp:42
@@ +41,3 @@
+  // - thread_local destructors on other threads run on the first iteration
+  //   through the pthread_key destructors.  std::notify_all_at_thread_exit()
+  //   and similar functions must be careful to wait until the second iteration

tavianator wrote:
> EricWF wrote:
> > Can you clarify what you mean by "other threads"?
> > 
> > How is libc++ supposed to detect and handle this problem? 
> I meant "non-main threads" ("other" is in relation to the bullet point 
> above), but I can clarify this, sure.
> 
> libc++ could be patched to do something like this:
> 
> ```
> pthread_key_t key1, key2;
> 
> void destructor1(void* ptr) {
>   pthread_setspecific(key2, ptr);
> }
> 
> void destructor2(void* ptr) {
>   // Runs in the second iteration through pthread_key destructors,
>   // therefore after thread_local destructors
> }
> 
> pthread_key_create(&key1, destructor1);
> pthread_key_create(&key2, destructor2);
> 
> pthread_setspecific(key1, ptr);
> ```
> 
> (Or it could use a counter/flag and a single pthread_key.)
> 
> libstdc++ has the same bug when __cxa_thread_atexit_impl() isn't available, 
> so I'm not sure that change would really be necessary.  If it is, I can write 
> up the libc++ patch.
I don't think we need to patch this in libc++. Especially because it would be 
incorrect in the vast majority of cases.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-02 Thread Tavian Barnes via cfe-commits
tavianator added a comment.

In https://reviews.llvm.org/D21803#532309, @EricWF wrote:

> `__thread`
>
> What do you think of this idea?


Makes sense to me, I'll integrate it into the next revision.



Comment at: src/cxa_thread_atexit.cpp:42
@@ +41,3 @@
+  // - thread_local destructors on other threads run on the first iteration
+  //   through the pthread_key destructors.  std::notify_all_at_thread_exit()
+  //   and similar functions must be careful to wait until the second iteration

EricWF wrote:
> Can you clarify what you mean by "other threads"?
> 
> How is libc++ supposed to detect and handle this problem? 
I meant "non-main threads" ("other" is in relation to the bullet point above), 
but I can clarify this, sure.

libc++ could be patched to do something like this:

```
pthread_key_t key1, key2;

void destructor1(void* ptr) {
  pthread_setspecific(key2, ptr);
}

void destructor2(void* ptr) {
  // Runs in the second iteration through pthread_key destructors,
  // therefore after thread_local destructors
}

pthread_key_create(&key1, destructor1);
pthread_key_create(&key2, destructor2);

pthread_setspecific(key1, ptr);
```

(Or it could use a counter/flag and a single pthread_key.)

libstdc++ has the same bug when __cxa_thread_atexit_impl() isn't available, so 
I'm not sure that change would really be necessary.  If it is, I can write up 
the libc++ patch.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-01 Thread Jonathan Roelofs via cfe-commits
jroelofs added a comment.

In https://reviews.llvm.org/D21803#532382, @EricWF wrote:

> In https://reviews.llvm.org/D21803#532347, @jroelofs wrote:
>
> > In https://reviews.llvm.org/D21803#532309, @EricWF wrote:
> >
> > > `__thread`
> > >
> > > What do you think of this idea?
> >
> >
> > You'll have to guard it against all the platforms that don't support TLS. 
> > Darwin 10.6 is one of them.
>
>
> Which is fine because we shouldn't supply a definition of 
> `__cxa_thread_atexit` on those platforms.


Ah, ok. Sounds good.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-01 Thread Eric Fiselier via cfe-commits
EricWF added a comment.

In https://reviews.llvm.org/D21803#532347, @jroelofs wrote:

> In https://reviews.llvm.org/D21803#532309, @EricWF wrote:
>
> > `__thread`
> >
> > What do you think of this idea?
>
>
> You'll have to guard it against all the platforms that don't support TLS. 
> Darwin 10.6 is one of them.


Which is fine because we shouldn't supply a definition of `__cxa_thread_atexit` 
on those platforms.

We might have to guard against it to keep libc++abi building, but if the 
platform doesn't support TLS then


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-01 Thread Jonathan Roelofs via cfe-commits
jroelofs added a comment.

In https://reviews.llvm.org/D21803#532309, @EricWF wrote:

> `__thread`
>
> What do you think of this idea?


You'll have to guard it against all the platforms that don't support TLS. 
Darwin 10.6 is one of them.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-01 Thread Eric Fiselier via cfe-commits
EricWF added a comment.

We can perform far fewer calls to `pthread_getspecific`/`pthread_setspecific` 
if we represent the list head using a global `__thread DtorList* list_head = 
nullptr`.
This also allows us to avoid the hack of setting/unsetting the key during 
`run_dtors()` which I really do not like.

Here is a patch that applies such changes: 
https://gist.github.com/EricWF/a071376b1216aabdd1695eec2175c374

What do you think of this idea?



Comment at: src/cxa_thread_atexit.cpp:42
@@ +41,3 @@
+  // - thread_local destructors on other threads run on the first iteration
+  //   through the pthread_key destructors.  std::notify_all_at_thread_exit()
+  //   and similar functions must be careful to wait until the second iteration

Can you clarify what you mean by "other threads"?

How is libc++ supposed to detect and handle this problem? 


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-01 Thread Eric Fiselier via cfe-commits
EricWF added a comment.

I'll look at this within the hour.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-01 Thread Ben Craig via cfe-commits
bcraig added a comment.

The "@" will do a ping through phabricator, but a direct email is probably 
going to be your best bet at this point.


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-09-01 Thread Tavian Barnes via cfe-commits
tavianator added a comment.

In https://reviews.llvm.org/D21803#530681, @bcraig wrote:

> In https://reviews.llvm.org/D21803#530678, @tavianator wrote:
>
> > Ping?
>
>
> Well, I still think it's fine.  Maybe a direct message to @mclow.lists or 
> @EricWF?


Is there a way to do that through Phabricator?  Or did you mean to email them 
directly?  (Not sure what their emails are but I can probably figure it out 
from the list history.)


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-08-31 Thread Ben Craig via cfe-commits
bcraig added a comment.

In https://reviews.llvm.org/D21803#530678, @tavianator wrote:

> Ping?


Well, I still think it's fine.  Maybe a direct message to @mclow.lists or 
@EricWF?


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-08-31 Thread Tavian Barnes via cfe-commits
tavianator added a comment.

Ping?


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-08-02 Thread Tavian Barnes via cfe-commits
tavianator added a comment.

Anything else I need to do for this patch?


https://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-13 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 63806.
tavianator added a comment.

Make sure the tail of the list is null.


http://reviews.llvm.org/D21803

Files:
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in
  test/thread_local_destruction_order.pass.cpp

Index: test/thread_local_destruction_order.pass.cpp
===
--- test/thread_local_destruction_order.pass.cpp
+++ test/thread_local_destruction_order.pass.cpp
@@ -0,0 +1,59 @@
+//===-- thread_local_destruction_order.pass.cpp ---===//
+//
+// 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: c++98, c++03
+
+#include 
+#include 
+
+int seq = 0;
+
+class OrderChecker {
+public:
+  explicit OrderChecker(int n) : n_{n} { }
+
+  ~OrderChecker() {
+assert(seq++ == n_);
+  }
+
+private:
+  int n_;
+};
+
+class CreatesThreadLocalInDestructor {
+public:
+  CreatesThreadLocalInDestructor(int n) : n_{n} { }
+
+  ~CreatesThreadLocalInDestructor() {
+thread_local OrderChecker checker{n_};
+  }
+
+private:
+  int n_;
+};
+
+OrderChecker global{6};
+
+void thread_fn() {
+  static OrderChecker fn_static{4};
+  thread_local OrderChecker fn_thread_local{1};
+  thread_local CreatesThreadLocalInDestructor creates_tl{0};
+}
+
+int main() {
+  static OrderChecker fn_static{5};
+
+  std::thread{thread_fn}.join();
+  assert(seq == 2);
+
+  thread_local OrderChecker fn_thread_local{3};
+  thread_local CreatesThreadLocalInDestructor creates_tl{2};
+
+  return 0;
+}
Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,151 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
-extern "C" {
 
-#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+  using Dtor = void(*)(void*);
 
-_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
-void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern "C"
+#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
+  // A weak symbol is used to detect this function's presence in the C library
+  // at runtime, even if libc++ is built against an older libc
+  __attribute__((__weak__))
+#endif
+  int __cxa_thread_atexit_impl(Dtor, void*, void*);
+
+#ifndef HAVE___CXA_

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-13 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 63801.
tavianator added a comment.

Update comments to mention that late-initialized thread_locals invoke undefined 
behavior.


http://reviews.llvm.org/D21803

Files:
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in
  test/thread_local_destruction_order.pass.cpp

Index: test/thread_local_destruction_order.pass.cpp
===
--- test/thread_local_destruction_order.pass.cpp
+++ test/thread_local_destruction_order.pass.cpp
@@ -0,0 +1,59 @@
+//===-- thread_local_destruction_order.pass.cpp ---===//
+//
+// 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: c++98, c++03
+
+#include 
+#include 
+
+int seq = 0;
+
+class OrderChecker {
+public:
+  explicit OrderChecker(int n) : n_{n} { }
+
+  ~OrderChecker() {
+assert(seq++ == n_);
+  }
+
+private:
+  int n_;
+};
+
+class CreatesThreadLocalInDestructor {
+public:
+  CreatesThreadLocalInDestructor(int n) : n_{n} { }
+
+  ~CreatesThreadLocalInDestructor() {
+thread_local OrderChecker checker{n_};
+  }
+
+private:
+  int n_;
+};
+
+OrderChecker global{6};
+
+void thread_fn() {
+  static OrderChecker fn_static{4};
+  thread_local OrderChecker fn_thread_local{1};
+  thread_local CreatesThreadLocalInDestructor creates_tl{0};
+}
+
+int main() {
+  static OrderChecker fn_static{5};
+
+  std::thread{thread_fn}.join();
+  assert(seq == 2);
+
+  thread_local OrderChecker fn_thread_local{3};
+  thread_local CreatesThreadLocalInDestructor creates_tl{2};
+
+  return 0;
+}
Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,150 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
-extern "C" {
 
-#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+  using Dtor = void(*)(void*);
 
-_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
-void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern "C"
+#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
+  // A weak symbol is used to detect this function's presence in the C library
+  // at runtime, even if libc++ is built against an older libc
+  __attribute__((__weak__))
+#endif
+  int __cxa_thread_atex

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-08 Thread Ben Craig via cfe-commits
bcraig added a comment.

LGTM (with a comment nit), but you'll need to get approval from @ericwf or 
@mclow.lists.

I would like some of the information from your stack overflow post to make it's 
way to the comments.  In particular, I think I would like to see it documented 
that we have made a choice for some undefined behavior.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-08 Thread Tavian Barnes via cfe-commits
tavianator marked 9 inline comments as done.
tavianator added a comment.

http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-08 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 63232.
tavianator marked 6 inline comments as done.
tavianator added a comment.

- Bring back HAVE___CXA_THREAD_ATEXIT_IMPL, and avoid the weak symbol/fallback 
implementation in that case
- Fix a leak in an error path
- Add a CreatesThreadLocalInDestructor to a non-main thread in the destructor 
ordering test


http://reviews.llvm.org/D21803

Files:
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in
  test/thread_local_destruction_order.pass.cpp

Index: test/thread_local_destruction_order.pass.cpp
===
--- test/thread_local_destruction_order.pass.cpp
+++ test/thread_local_destruction_order.pass.cpp
@@ -0,0 +1,59 @@
+//===-- thread_local_destruction_order.pass.cpp ---===//
+//
+// 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: c++98, c++03
+
+#include 
+#include 
+
+int seq = 0;
+
+class OrderChecker {
+public:
+  explicit OrderChecker(int n) : n_{n} { }
+
+  ~OrderChecker() {
+assert(seq++ == n_);
+  }
+
+private:
+  int n_;
+};
+
+class CreatesThreadLocalInDestructor {
+public:
+  CreatesThreadLocalInDestructor(int n) : n_{n} { }
+
+  ~CreatesThreadLocalInDestructor() {
+thread_local OrderChecker checker{n_};
+  }
+
+private:
+  int n_;
+};
+
+OrderChecker global{6};
+
+void thread_fn() {
+  static OrderChecker fn_static{4};
+  thread_local OrderChecker fn_thread_local{1};
+  thread_local CreatesThreadLocalInDestructor creates_tl{0};
+}
+
+int main() {
+  static OrderChecker fn_static{5};
+
+  std::thread{thread_fn}.join();
+  assert(seq == 2);
+
+  thread_local OrderChecker fn_thread_local{3};
+  thread_local CreatesThreadLocalInDestructor creates_tl{2};
+
+  return 0;
+}
Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,138 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
-extern "C" {
 
-#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+  using Dtor = void(*)(void*);
 
-_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
-void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern "C"
+#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
+  // A weak symbol 

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-05 Thread Ben Craig via cfe-commits
bcraig added inline comments.


Comment at: test/thread_local_destruction_order.pass.cpp:54
@@ +53,3 @@
+  std::thread{thread_fn}.join();
+
+  thread_local OrderChecker fn_thread_local{2};

tavianator wrote:
> bcraig wrote:
> > In the places where you can, validate that dtors actually are getting 
> > called.  This may be your only place where you can do that.
> > 
> > So something like 'assert(seq == 1)' here.
> Sounds good.  What I wanted to do was print some output in the destructors, 
> and check for a certain expected output.  But I couldn't figure out how to do 
> that with lit.
Normally, you would do that by piping the output to the llvm FileCheck utility. 
 My unconfirmed suspicion is that that approach will run into difficulties 
because of libcxx and libcxxabi specific setups.

I think just having the global object's dtor check is good enough for the final 
post condition though.  I'm not terribly worried about global dtors 
malfunctioning.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-05 Thread Tavian Barnes via cfe-commits
tavianator added inline comments.


Comment at: src/cxa_thread_atexit.cpp:47
@@ +46,3 @@
+// called during the loop.
+if (pthread_setspecific(dtors, ptr) != 0) {
+  abort_message("pthread_setspecific() failed during thread_local 
destruction");

bcraig wrote:
> The loop doesn't read pthread_getspecific anymore.  I get the need for the 
> setspecific call here for your previous design, but I don't think it's needed 
> now.
__cxa_thread_atexit() calls pthread_getspecific(), so it's still needed.  
Otherwise it would create a new list instead of adding to the current one, and 
the ordering would be wrong.


Comment at: src/cxa_thread_atexit.cpp:99
@@ +98,3 @@
+
+  if (__cxa_thread_atexit_impl) {
+return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);

bcraig wrote:
> I'm going to have to agree with @majnemer.  I think that the config check for 
> LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL should stay in place.  If 
> cxa_thread_atexit_impl exists, then all of the fallback code can disappear at 
> preprocessing time.
> 
> We do lose out on the minor benefit of avoiding some libc++ recompiles, but 
> we also avoid code bloat.
> 
> For what it's worth, I'm willing to keep the weak symbol check in place if 
> __cxa_thread_atexit_impl isn't present, I just don't want to pay for the 
> fallback when I know I'm not going to use it.
Makes sense, I'll do that.


Comment at: test/thread_local_destruction_order.pass.cpp:48
@@ +47,3 @@
+  thread_local OrderChecker fn_thread_local{0};
+}
+

bcraig wrote:
> Can we have a CreatesThreadLocalInDestructor in the thread_fn as well?  That 
> way we can test both the main function and a pthread.  If I understand your 
> code and comments correctly, those go through different code paths.
Yep, meant to do that actually!


Comment at: test/thread_local_destruction_order.pass.cpp:54
@@ +53,3 @@
+  std::thread{thread_fn}.join();
+
+  thread_local OrderChecker fn_thread_local{2};

bcraig wrote:
> In the places where you can, validate that dtors actually are getting called. 
>  This may be your only place where you can do that.
> 
> So something like 'assert(seq == 1)' here.
Sounds good.  What I wanted to do was print some output in the destructors, and 
check for a certain expected output.  But I couldn't figure out how to do that 
with lit.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-05 Thread Ben Craig via cfe-commits
bcraig added inline comments.


Comment at: src/cxa_thread_atexit.cpp:47
@@ +46,3 @@
+// called during the loop.
+if (pthread_setspecific(dtors, ptr) != 0) {
+  abort_message("pthread_setspecific() failed during thread_local 
destruction");

The loop doesn't read pthread_getspecific anymore.  I get the need for the 
setspecific call here for your previous design, but I don't think it's needed 
now.


Comment at: src/cxa_thread_atexit.cpp:99
@@ +98,3 @@
+
+  if (__cxa_thread_atexit_impl) {
+return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);

I'm going to have to agree with @majnemer.  I think that the config check for 
LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL should stay in place.  If 
cxa_thread_atexit_impl exists, then all of the fallback code can disappear at 
preprocessing time.

We do lose out on the minor benefit of avoiding some libc++ recompiles, but we 
also avoid code bloat.

For what it's worth, I'm willing to keep the weak symbol check in place if 
__cxa_thread_atexit_impl isn't present, I just don't want to pay for the 
fallback when I know I'm not going to use it.


Comment at: test/thread_local_destruction_order.pass.cpp:1
@@ +1,2 @@
+//===- cxa_thread_atexit_test.cpp 
-===//
+//

Nit: file name is wrong here.


Comment at: test/thread_local_destruction_order.pass.cpp:48
@@ +47,3 @@
+  thread_local OrderChecker fn_thread_local{0};
+}
+

Can we have a CreatesThreadLocalInDestructor in the thread_fn as well?  That 
way we can test both the main function and a pthread.  If I understand your 
code and comments correctly, those go through different code paths.


Comment at: test/thread_local_destruction_order.pass.cpp:54
@@ +53,3 @@
+  std::thread{thread_fn}.join();
+
+  thread_local OrderChecker fn_thread_local{2};

In the places where you can, validate that dtors actually are getting called.  
This may be your only place where you can do that.

So something like 'assert(seq == 1)' here.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-07-04 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 62691.
tavianator added a comment.

Added a test case for destructor ordering.  Got rid of 
pthread_{get,set}specific in a loop.


http://reviews.llvm.org/D21803

Files:
  cmake/config-ix.cmake
  src/CMakeLists.txt
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in
  test/thread_local_destruction_order.pass.cpp

Index: test/thread_local_destruction_order.pass.cpp
===
--- test/thread_local_destruction_order.pass.cpp
+++ test/thread_local_destruction_order.pass.cpp
@@ -0,0 +1,59 @@
+//===- cxa_thread_atexit_test.cpp -===//
+//
+// 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: c++98, c++03
+
+#include 
+#include 
+
+int seq = 0;
+
+class OrderChecker
+{
+public:
+  explicit OrderChecker(int n) : n_{n} { }
+
+  ~OrderChecker() {
+assert(seq++ == n_);
+  }
+
+private:
+  int n_;
+};
+
+class CreatesThreadLocalInDestructor
+{
+public:
+  CreatesThreadLocalInDestructor(int n) : n_{n} { }
+
+  ~CreatesThreadLocalInDestructor() {
+thread_local OrderChecker checker{n_};
+  }
+
+private:
+  int n_;
+};
+
+OrderChecker global{5};
+
+void thread_fn() {
+  static OrderChecker fn_static{3};
+  thread_local OrderChecker fn_thread_local{0};
+}
+
+int main() {
+  static OrderChecker fn_static{4};
+
+  std::thread{thread_fn}.join();
+
+  thread_local OrderChecker fn_thread_local{2};
+  thread_local CreatesThreadLocalInDestructor creates_tl{1};
+
+  return 0;
+}
Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,126 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
+namespace {
+  // This implementation is used if the C library does not provide
+  // __cxa_thread_atexit_impl() for us.  It has a number of limitations that are
+  // difficult to impossible to address without ..._impl():
+  //
+  // - dso_symbol is ignored.  This means that a shared library may be unloaded
+  //   (via dlclose()) before its thread_local destructors have run.
+  //
+  // - thread_local destructors for the main thread are run by the destructor of
+  //   a static object.  This is later than expected; they should run before the
+  //   destructors of any objects with static storage duration.
+  //
+  // - thread_local destructors on other thr

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Ben Craig via cfe-commits
bcraig added a comment.

Also, can you add test cases for a lot of these things?  I don't expect test 
cases for the DSO side of things, but a lot of the tricky atexit cases should 
be covered.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Tavian Barnes via cfe-commits
tavianator added inline comments.


Comment at: src/cxa_thread_atexit.cpp:47
@@ +46,3 @@
+  void run_dtors(void* ptr) {
+if (pthread_setspecific(dtors, ptr) != 0) {
+  abort_message("pthread_setspecific() failed during thread_local 
destruction");

bcraig wrote:
> Why are we doing this?  I can see it being a little useful when debugging / 
> developing, so that you get an early warning that something has gone wrong, 
> but it seems like this will always be setting a value to the value it already 
> has.
pthread_key destructors run after the key is set to null.  I re-set it here 
since the loop reads the key.


Comment at: src/cxa_thread_atexit.cpp:54
@@ +53,3 @@
+// __cxa_thread_atexit() is called during the loop.
+while (auto elem = static_cast(pthread_getspecific(dtors))) {
+  if (pthread_setspecific(dtors, elem->next) != 0) {

bcraig wrote:
> Maybe this concern is unfounded, but I'm not overly fond of 
> pthread_getspecific and setspecific in a loop.  I've always been under the 
> impression that those functions are rather slow.  Could we add a layer of 
> indirection so that we don't need to call getspecific and setspecific so 
> often?  Basically make the pointer that is directly stored in TLS an 
> immutable pointer to pointer.
Sure, I can do that.  Would reduce the number of setspecific() calls in 
__cxa_thread_atexit too.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Ben Craig via cfe-commits
bcraig added inline comments.


Comment at: src/cxa_thread_atexit.cpp:47
@@ +46,3 @@
+  void run_dtors(void* ptr) {
+if (pthread_setspecific(dtors, ptr) != 0) {
+  abort_message("pthread_setspecific() failed during thread_local 
destruction");

Why are we doing this?  I can see it being a little useful when debugging / 
developing, so that you get an early warning that something has gone wrong, but 
it seems like this will always be setting a value to the value it already has.


Comment at: src/cxa_thread_atexit.cpp:54
@@ +53,3 @@
+// __cxa_thread_atexit() is called during the loop.
+while (auto elem = static_cast(pthread_getspecific(dtors))) {
+  if (pthread_setspecific(dtors, elem->next) != 0) {

Maybe this concern is unfounded, but I'm not overly fond of pthread_getspecific 
and setspecific in a loop.  I've always been under the impression that those 
functions are rather slow.  Could we add a layer of indirection so that we 
don't need to call getspecific and setspecific so often?  Basically make the 
pointer that is directly stored in TLS an immutable pointer to pointer.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 62394.
tavianator added a comment.

Fix copy-pasta that result in an infinite loop.


http://reviews.llvm.org/D21803

Files:
  cmake/config-ix.cmake
  src/CMakeLists.txt
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in

Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,137 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
+namespace {
+  // This implementation is used if the C library does not provide
+  // __cxa_thread_atexit_impl() for us.  It has a number of limitations that are
+  // difficult to impossible to address without ..._impl():
+  //
+  // - dso_symbol is ignored.  This means that a shared library may be unloaded
+  //   (via dlclose()) before its thread_local destructors have run.
+  //
+  // - thread_local destructors for the main thread are run with __cxa_atexit().
+  //   This is later than expected; they should run before the destructors of
+  //   any objects with static storage duration.
+  //
+  // - thread_local destructors on other threads run on the first iteration
+  //   through the pthread_key destructors.  std::notify_all_at_thread_exit()
+  //   and similar functions must be careful to wait until the second iteration
+  //   to provide their indended ordering guarantees.
+
+  typedef void (*Dtor)(void*);
+
+  struct DtorList {
+Dtor dtor;
+void* obj;
+DtorList* next;
+  };
+
+  pthread_key_t dtors;
+  pthread_once_t dtors_once = PTHREAD_ONCE_INIT;
+  bool dtors_ready = false;
+  bool dtors_atexit = false;
+
+  void run_dtors(void* ptr) {
+if (pthread_setspecific(dtors, ptr) != 0) {
+  abort_message("pthread_setspecific() failed during thread_local destruction");
+}
+
+// Rather than iterate over the list directly, use the pthread_key to get
+// the head of the list every time.  This gives the correct ordering if
+// __cxa_thread_atexit() is called during the loop.
+while (auto elem = static_cast(pthread_getspecific(dtors))) {
+  if (pthread_setspecific(dtors, elem->next) != 0) {
+abort_message("pthread_setspecific() failed during thread_local destruction");
+  }
+  elem->dtor(elem->obj);
+  std::free(elem);
+}
+  }
+
+  void run_dtors_atexit(void*) {
+// Signify that we need to re-register this function if any new
+// thread_locals are created.
+dtors_atexit = false;
+
+auto ptr = pthread_getspecific(dtors);
+run_dtors(ptr);
+  }
+
+  // This is the DSO handle for libc++abi.so itself
+  extern "C" void* __dso_handle;
+
+  void dtors_

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 62388.
tavianator added a comment.

Added missing __dso_handle declaration.


http://reviews.llvm.org/D21803

Files:
  cmake/config-ix.cmake
  src/CMakeLists.txt
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in

Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,137 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
+namespace {
+  // This implementation is used if the C library does not provide
+  // __cxa_thread_atexit_impl() for us.  It has a number of limitations that are
+  // difficult to impossible to address without ..._impl():
+  //
+  // - dso_symbol is ignored.  This means that a shared library may be unloaded
+  //   (via dlclose()) before its thread_local destructors have run.
+  //
+  // - thread_local destructors for the main thread are run with __cxa_atexit().
+  //   This is later than expected; they should run before the destructors of
+  //   any objects with static storage duration.
+  //
+  // - thread_local destructors on other threads run on the first iteration
+  //   through the pthread_key destructors.  std::notify_all_at_thread_exit()
+  //   and similar functions must be careful to wait until the second iteration
+  //   to provide their indended ordering guarantees.
+
+  typedef void (*Dtor)(void*);
+
+  struct DtorList {
+Dtor dtor;
+void* obj;
+DtorList* next;
+  };
+
+  pthread_key_t dtors;
+  pthread_once_t dtors_once = PTHREAD_ONCE_INIT;
+  bool dtors_ready = false;
+  bool dtors_atexit = false;
+
+  void run_dtors(void* ptr) {
+if (pthread_setspecific(dtors, ptr) != 0) {
+  abort_message("pthread_setspecific() failed during thread_local destruction");
+}
+
+// Rather than iterate over the list directly, use the pthread_key to get
+// the head of the list every time.  This gives the correct ordering if
+// __cxa_thread_atexit() is called during the loop.
+while (auto elem = static_cast(pthread_getspecific(dtors))) {
+  if (pthread_setspecific(dtors, ptr) != 0) {
+abort_message("pthread_setspecific() failed during thread_local destruction");
+  }
+  elem->dtor(elem->obj);
+  std::free(elem);
+}
+  }
+
+  void run_dtors_atexit(void*) {
+// Signify that we need to re-register this function if any new
+// thread_locals are created.
+dtors_atexit = false;
+
+auto ptr = pthread_getspecific(dtors);
+run_dtors(ptr);
+  }
+
+  // This is the DSO handle for libc++abi.so itself
+  extern "C" void* __dso_handle;
+
+  void dtors_init() {
+/

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Tavian Barnes via cfe-commits
tavianator marked 3 inline comments as done.
tavianator added a comment.

In http://reviews.llvm.org/D21803#470448, @bcraig wrote:

> What that means for this implementation is that I think that 
> _cxa_thread_atexit is allowed to be called during run_dtors.  If running the 
> dtor for a thread local variable 'cat', we encounter a previously unseen 
> thread_local 'dog', the compiler will call the ctor, then register the dtor 
> with _cxa_thread_atexit.  Since it is the most recently constructed thread 
> local object, I would expect the 'dog' dtor to be the next dtor to be run.  
> You may be able to support this just by moving "elem = elem->next" below the 
> dtor invocation.


It wasn't quite that easy (have to re-look at the pthread_key to get newly 
added thread_locals), but that's done in the latest patch.



Comment at: src/cxa_thread_atexit.cpp:115
@@ +114,3 @@
+if (!dtors_atexit) {
+  if (__cxa_atexit(run_dtors_atexit, NULL, __dso_handle) != 0) {
+return -1;

See http://stackoverflow.com/q/38130185/502399 for a test case that would 
trigger this.  This may not be necessary depending on the answer to that 
question.


Comment at: src/cxa_thread_atexit.cpp:122
@@ +121,3 @@
+auto head = static_cast(std::malloc(sizeof(DtorList)));
+if (!head) {
+  return -1;

This has changed somewhat in the latest patch, but the gist is similar.  If 
libc++abi.so is dlclose()d, there had better not be any still-running threads 
that expect to execute thread_local destructors (or any other C++ code, for 
that matter).  In the usual case (libc++abi.so loaded at startup, not by a 
later dlopen()), the last run_dtors() call happens as the final thread is 
exiting.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 62386.
tavianator added a comment.

Fixed some corner cases regarding destruction order and very-late-initialized 
thread_locals.  Explicitly documented the known limitations compared to 
__cxa_thread_atexit_impl().


http://reviews.llvm.org/D21803

Files:
  cmake/config-ix.cmake
  src/CMakeLists.txt
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in

Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -7,20 +7,134 @@
 //
 //===--===//
 
+#include "abort_message.h"
 #include "cxxabi.h"
+#include 
+#include 
 
 namespace __cxxabiv1 {
+namespace {
+  // This implementation is used if the C library does not provide
+  // __cxa_thread_atexit_impl() for us.  It has a number of limitations that are
+  // difficult to impossible to address without ..._impl():
+  //
+  // - dso_symbol is ignored.  This means that a shared library may be unloaded
+  //   (via dlclose()) before its thread_local destructors have run.
+  //
+  // - thread_local destructors for the main thread are run with __cxa_atexit().
+  //   This is later than expected; they should run before the destructors of
+  //   any objects with static storage duration.
+  //
+  // - thread_local destructors on other threads run on the first iteration
+  //   through the pthread_key destructors.  std::notify_all_at_thread_exit()
+  //   and similar functions must be careful to wait until the second iteration
+  //   to provide their indended ordering guarantees.
+
+  typedef void (*Dtor)(void*);
+
+  struct DtorList {
+Dtor dtor;
+void* obj;
+DtorList* next;
+  };
+
+  pthread_key_t dtors;
+  pthread_once_t dtors_once = PTHREAD_ONCE_INIT;
+  bool dtors_ready = false;
+  bool dtors_atexit = false;
+
+  void run_dtors(void* ptr) {
+if (pthread_setspecific(dtors, ptr) != 0) {
+  abort_message("pthread_setspecific() failed during thread_local destruction");
+}
+
+// Rather than iterate over the list directly, use the pthread_key to get
+// the head of the list every time.  This gives the correct ordering if
+// __cxa_thread_atexit() is called during the loop.
+while (auto elem = static_cast(pthread_getspecific(dtors))) {
+  if (pthread_setspecific(dtors, ptr) != 0) {
+abort_message("pthread_setspecific() failed during thread_local destruction");
+  }
+  elem->dtor(elem->obj);
+  std::free(elem);
+}
+  }
+
+  void run_dtors_atexit(void*) {
+// Signify that we need to re-register this function if any new
+// thread_locals are created.
+dtors_atexit = false;
+
+auto ptr = pthread_getspecific(dtors);
+r

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Dimitry Ivanov via cfe-commits
dimitry added inline comments.


Comment at: src/cxa_thread_atexit.cpp:46
@@ +45,3 @@
+  pthread_key_delete(key_);
+}
+

bcraig wrote:
> dimitry wrote:
> > run_dtors() is called when/if libc++.so gets unloaded... but only for the 
> > thread calling dlclose()?
> Most of the dtor magic is on the pthread_key_create side.  pthreads lets you 
> register a per-thread destructor.
> 
> This destructor is only run on process termination (I think).
I meant the call from ~DtorListHolder()


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-30 Thread Ben Craig via cfe-commits
bcraig added a comment.

In http://reviews.llvm.org/D21803#470564, @joerg wrote:

> On the topic of __cxa_thread_atexit, was it ever specified how it interacts 
> with things like thread cancellation?


I don't think it's officially specified anywhere.  C++ threads don't have a 
cancel method.  The POSIX spec doesn't speak about the C++ ABI.  The Itanium 
ABI could talk about this, but hasn't yet.

I think this implementation does the right thing with regards to cancellation 
though.  POSIX says that first cancellation cleanup handlers are called, then 
thread-specific data destructors are called.  pthread_cancel is still a really 
bad idea due to how it (doesn't) interact with RAII, but at least TLS data 
won't get leaked.



Comment at: src/cxa_thread_atexit.cpp:46
@@ +45,3 @@
+  pthread_key_delete(key_);
+}
+

dimitry wrote:
> run_dtors() is called when/if libc++.so gets unloaded... but only for the 
> thread calling dlclose()?
Most of the dtor magic is on the pthread_key_create side.  pthreads lets you 
register a per-thread destructor.

This destructor is only run on process termination (I think).


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Dimitry Ivanov via cfe-commits
dimitry added a subscriber: dimitry.


Comment at: src/cxa_thread_atexit.cpp:46
@@ +45,3 @@
+  pthread_key_delete(key_);
+}
+

run_dtors() is called when/if libc++.so gets unloaded... but only for the 
thread calling dlclose()?


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Joerg Sonnenberger via cfe-commits
joerg added a subscriber: joerg.
joerg added a comment.

On the topic of __cxa_thread_atexit, was it ever specified how it interacts 
with things like thread cancellation?


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Ben Craig via cfe-commits
bcraig added a comment.

> Hmm, maybe?  If other global destructors run after ~DtorListHolder(), and 
> they cause a thread_local to be initialized for the first time, 
> __cxa_thread_atexit() might be called again.  I was thinking that dtors would 
> get re-initialized in that case but it appears it does not.  So yeah, I think 
> I'll need to leak the pthread_key_t.

> 

> I'm not sure how to avoid leaking the actual thread_local objects that get 
> created in that situation.  There's nothing left to trigger run_dtors() a 
> second time.


I'm not concerned about the loss of memory or pthread_key resources in this 
leak, as it is a very short-lived leak (the process is going away after all).  
We do need to have an idea of what happens with the destructor invocations for 
the other kinds of resources though.

I think the C++14 spec says what should happen.

> 3.6.3 Termination

> 

> 1. [...] The completions of the destructors for all initialized objects with 
> thread storage duration within that thread are sequenced before the 
> initiation of the destructors of any object with static storage duration. If 
> the completion of the constructor or dynamic initialization of an object with 
> thread storage duration is sequenced before that of another, the completion 
> of the destructor of the second is sequenced before the initiation of the 
> destructor of the first. If the completion of the constructor or dynamic 
> initialization of an object with static storage duration is sequenced before 
> that of another, the completion of the destructor of the second is sequenced 
> before the initiation of the destructor of the first.


What that means for this implementation is that I think that 
__cxa_thread_atexit is allowed to be called during run_dtors.  If running the 
dtor for a thread local variable 'cat', we encounter a previously unseen 
thread_local 'dog', the compiler will call the ctor, then register the dtor 
with __cxa_thread_atexit.  Since it is the most recently constructed thread 
local object, I would expect the 'dog' dtor to be the next dtor to be run.  You 
may be able to support this just by moving "elem = elem->next" below the dtor 
invocation.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Tavian Barnes via cfe-commits
tavianator added a comment.

In http://reviews.llvm.org/D21803#470086, @bcraig wrote:

> It also intentionally leaks the pthread key.  Does the __thread_specific_ptr 
> rationale hold for this change as well?


Hmm, maybe?  If other global destructors run after ~DtorListHolder(), and they 
cause a thread_local to be initialized for the first time, 
__cxa_thread_atexit() might be called again.  I was thinking that dtors would 
get re-initialized in that case but it appears it does not.  So yeah, I think 
I'll need to leak the pthread_key_t.

I'm not sure how to avoid leaking the actual thread_local objects that get 
created in that situation.  There's nothing left to trigger run_dtors() a 
second time.



Comment at: src/cxa_thread_atexit.cpp:64-90
@@ -18,8 +63,29 @@
+_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void *obj,
 void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern int __cxa_thread_atexit_impl(Dtor, void *, void *)
+__attribute__((__weak__));
+
+  if (__cxa_thread_atexit_impl) {
+return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
+  } else {
+static DtorListHolder dtors;
+
+auto head = static_cast(std::malloc(sizeof(DtorList)));
+if (!head) {
+  return -1;
+}
+
+head->dtor = dtor;
+head->obj = obj;
+head->next = dtors.get();
+
+if (!dtors.set(head)) {
+  std::free(head);
+  return -1;
+}
 
-#endif // HAVE__CXA_THREAD_ATEXIT_IMPL
+return 0;
+  }
+}
 
 } // extern "C"

majnemer wrote:
> I think that this should be an opt-in mechanism, there are platforms that 
> presumably never need to pay the cost of the unused code (macOS comes to 
> mind).
This file is only built for UNIX AND NOT (APPLE OR CYGWIN).  Other platforms 
use something other than __cxa_thread_atexit() I assume.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread David Majnemer via cfe-commits
majnemer added inline comments.


Comment at: src/cxa_thread_atexit.cpp:64-90
@@ -18,8 +63,29 @@
+_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void *obj,
 void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern int __cxa_thread_atexit_impl(Dtor, void *, void *)
+__attribute__((__weak__));
+
+  if (__cxa_thread_atexit_impl) {
+return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
+  } else {
+static DtorListHolder dtors;
+
+auto head = static_cast(std::malloc(sizeof(DtorList)));
+if (!head) {
+  return -1;
+}
+
+head->dtor = dtor;
+head->obj = obj;
+head->next = dtors.get();
+
+if (!dtors.set(head)) {
+  std::free(head);
+  return -1;
+}
 
-#endif // HAVE__CXA_THREAD_ATEXIT_IMPL
+return 0;
+  }
+}
 
 } // extern "C"

I think that this should be an opt-in mechanism, there are platforms that 
presumably never need to pay the cost of the unused code (macOS comes to mind).


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Asiri Rathnayake via cfe-commits
rmaprath added a comment.

In http://reviews.llvm.org/D21803#470060, @tavianator wrote:

> In http://reviews.llvm.org/D21803#469988, @bcraig wrote:
>
> > @rmaprath has been doing some work to make the threading runtime library 
> > swappable.  I don't recall if his work extended to libcxxabi or not, but 
> > I'll page him anyway.
>
>
> <__threading_support>?  Seems to be libc++-specific.  There's a few other raw 
> uses of pthreads in libc++abi.


Plan to get started with `libc++abi` as soon as I'm done with `libc++`, I've 
hit a couple of bumps with the latter, resolving them at the moment.

I don't see any new `pthread` dependencies introduced in this patch, so it 
sounds OK to me. Thanks for the ping though!

The patch itself looks OK to me. Will need approval from @mclow.lists or 
@ericwf.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Ben Craig via cfe-commits
bcraig added a comment.

In http://reviews.llvm.org/D21803#470060, @tavianator wrote:

> In http://reviews.llvm.org/D21803#469988, @bcraig wrote:
>
> > You should look at __thread_specific_ptr in libcxx's .  It does a 
> > lot of these things in order to satisfy the requirements of 
> > notify_all_at_thread_exit, set_value_at_thread_exit, and 
> > make_ready_at_thread_exit.
>
>
> Had a look at it.  One thing that stands out is that 
> notify_all_at_thread_exit() and friends are supposed to be invoked *after* 
> thread_local destructors.  But the order that pthread_key destructors run in 
> is unspecified.  This could be worked around by waiting for the second 
> iteration through pthread_key destructors before triggering 
> ~__thread_struct_imp().  It looks like libstdc++ has a similar bug if 
> ..._impl() isn't available.


It also intentionally leaks the pthread key.  Does the __thread_specific_ptr 
rationale hold for this change as well?

> > This implementation of __cxa_thread_atexit doesn't interact nicely with 
> > shared libraries.  The following sequence of events causes unloaded code to 
> > get invoked.

> 

> > 

> 

> > - Create thread 42

> 

> > - Load library foo from thread 42

> 

> > - Call a function with a thread_local object with a dtor.

> 

> > - Unload library foo.

> 

> > - Join thread 42

> 

> > 

> 

> >   glibc does some extra work during __cxa_thread_atexit_impl to bump the 
> > reference count of the shared library so that the user's "unload" doesn't 
> > actually unload the library.

> 

> 

> Yep.  This is about as good as libc++abi can do on its own though.  Note that 
> libstdc++ has similar limitations if ..._impl() isn't available.


I was going to tell you that this is implementable with dladdr (which I think 
Android has).  Then I looked more at the "prevent unloading" side of things, 
and it looks like that requires digging into the library structures directly.  
Ugh.

Comment on the limitation in the source, but you don't need to change any code 
for this item.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Tavian Barnes via cfe-commits
tavianator added a comment.

In http://reviews.llvm.org/D21803#469988, @bcraig wrote:

> You should look at __thread_specific_ptr in libcxx's .  It does a lot 
> of these things in order to satisfy the requirements of 
> notify_all_at_thread_exit, set_value_at_thread_exit, and 
> make_ready_at_thread_exit.


Had a look at it.  One thing that stands out is that 
notify_all_at_thread_exit() and friends are supposed to be invoked *after* 
thread_local destructors.  But the order that pthread_key destructors run in is 
unspecified.  This could be worked around by waiting for the second iteration 
through pthread_key destructors before triggering ~__thread_struct_imp().  It 
looks like libstdc++ has a similar bug if ..._impl() isn't available.

> @rmaprath has been doing some work to make the threading runtime library 
> swappable.  I don't recall if his work extended to libcxxabi or not, but I'll 
> page him anyway.


<__threading_support>?  Seems to be libc++-specific.  There's a few other raw 
uses of pthreads in libc++abi.

> This implementation of __cxa_thread_atexit doesn't interact nicely with 
> shared libraries.  The following sequence of events causes unloaded code to 
> get invoked.

> 

> - Create thread 42

> - Load library foo from thread 42

> - Call a function with a thread_local object with a dtor.

> - Unload library foo.

> - Join thread 42

> 

>   glibc does some extra work during __cxa_thread_atexit_impl to bump the 
> reference count of the shared library so that the user's "unload" doesn't 
> actually unload the library.


Yep.  This is about as good as libc++abi can do on its own though.  Note that 
libstdc++ has similar limitations if ..._impl() isn't available.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Ben Craig via cfe-commits
bcraig added subscribers: rmaprath, bcraig.
bcraig added a comment.

You should look at __thread_specific_ptr in libcxx's .  It does a lot 
of these things in order to satisfy the requirements of 
notify_all_at_thread_exit, set_value_at_thread_exit, and 
make_ready_at_thread_exit.

@rmaprath has been doing some work to make the threading runtime library 
swappable.  I don't recall if his work extended to libcxxabi or not, but I'll 
page him anyway.

This implementation of __cxa_thread_atexit doesn't interact nicely with shared 
libraries.  The following sequence of events causes unloaded code to get 
invoked.

- Create thread 42
- Load library foo from thread 42
- Call a function with a thread_local object with a dtor.
- Unload library foo.
- Join thread 42

glibc does some extra work during __cxa_thread_atexit_impl to bump the 
reference count of the shared library so that the user's "unload" doesn't 
actually unload the library.



Comment at: src/cxa_thread_atexit.cpp:40
@@ +39,3 @@
+
+~DtorListHolder() {
+  run_dtors(get());

I think this is correct, but it needs some comments because it is not obvious 
what (or why) this is implemented this way.

More specifically, document the cases where run_dtors is run because of 
~DtorListHolder vs. the cases where run_dtors is run because of the callback 
registered at pthread_key_create.


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-29 Thread Tavian Barnes via cfe-commits
tavianator updated this revision to Diff 62218.
tavianator added a comment.

Added error handling for pthread_key uses


http://reviews.llvm.org/D21803

Files:
  cmake/config-ix.cmake
  src/CMakeLists.txt
  src/cxa_thread_atexit.cpp
  test/CMakeLists.txt
  test/cxa_thread_atexit_test.pass.cpp
  test/libcxxabi/test/config.py
  test/lit.site.cfg.in

Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -13,7 +13,6 @@
 config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@"
 config.target_info  = "@LIBCXXABI_TARGET_INFO@"
 config.executor = "@LIBCXXABI_EXECUTOR@"
-config.thread_atexit= "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@"
 config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
 config.enable_shared= "@LIBCXX_ENABLE_SHARED@"
 config.enable_exceptions= "@LIBCXXABI_ENABLE_EXCEPTIONS@"
Index: test/libcxxabi/test/config.py
===
--- test/libcxxabi/test/config.py
+++ test/libcxxabi/test/config.py
@@ -37,8 +37,6 @@
 super(Configuration, self).configure_features()
 if not self.get_lit_bool('enable_exceptions', True):
 self.config.available_features.add('libcxxabi-no-exceptions')
-if self.get_lit_bool('thread_atexit', True):
-self.config.available_features.add('thread_atexit')
 
 def configure_compile_flags(self):
 self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']
Index: test/cxa_thread_atexit_test.pass.cpp
===
--- test/cxa_thread_atexit_test.pass.cpp
+++ test/cxa_thread_atexit_test.pass.cpp
@@ -8,7 +8,6 @@
 //===--===//
 
 // REQUIRES: linux
-// REQUIRES: thread_atexit
 
 #include 
 #include 
Index: test/CMakeLists.txt
===
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -16,7 +16,6 @@
 pythonize_bool(LIBCXXABI_ENABLE_THREADS)
 pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
 pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
-pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
 set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
 "TargetInfo to use when setting up test environment.")
 set(LIBCXXABI_EXECUTOR "None" CACHE STRING
Index: src/cxa_thread_atexit.cpp
===
--- src/cxa_thread_atexit.cpp
+++ src/cxa_thread_atexit.cpp
@@ -8,19 +8,85 @@
 //===--===//
 
 #include "cxxabi.h"
+#include 
+#include 
+#include "abort_message.h"
 
 namespace __cxxabiv1 {
-extern "C" {
+namespace {
+  typedef void (*Dtor)(void *);
+
+  struct DtorList {
+Dtor dtor;
+void* obj;
+DtorList* next;
+  };
+
+  void run_dtors(void* ptr) {
+auto elem = static_cast(ptr);
+while (elem) {
+  auto saved = elem;
+  elem = elem->next;
+  saved->dtor(saved->obj);
+  std::free(saved);
+}
+  }
+
+  class DtorListHolder {
+  public:
+DtorListHolder() {
+  if (pthread_key_create(&key_, run_dtors) != 0) {
+abort_message("cannot create pthread key for __cxa_thread_atexit()");
+  }
+}
+
+~DtorListHolder() {
+  run_dtors(get());
+  pthread_key_delete(key_);
+}
+
+DtorList* get() {
+  return static_cast(pthread_getspecific(key_));
+}
+
+bool set(DtorList* list) {
+  return pthread_setspecific(key_, list) == 0;
+}
+
+  private:
+pthread_key_t key_;
+  };
+} // namespace
 
-#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+extern "C" {
 
-_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj,
+_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void *obj,
 void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern int __cxa_thread_atexit_impl(Dtor, void *, void *)
+__attribute__((__weak__));
+
+  if (__cxa_thread_atexit_impl) {
+return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
+  } else {
+static DtorListHolder dtors;
+
+auto head = static_cast(std::malloc(sizeof(DtorList)));
+if (!head) {
+  return -1;
+}
+
+head->dtor = dtor;
+head->obj = obj;
+head->next = dtors.get();
+
+if (!dtors.set(head)) {
+  std::free(head);
+  return -1;
+}
 
-#endif // HAVE__CXA_THREAD_ATEXIT_IMPL
+return 0;
+  }
+}
 
 } // extern "C"
 } // namespace __cxxabiv1
Index: src/CMakeLists.txt
===
--- src/CMakeLists.txt
+++ src/CMakeLists.txt
@@ -41,10 +41,6 @@
 
 include_directories("${LIBCXXABI_LIBCXX_INCLUDES}")
 
-if (LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
-

Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-28 Thread Tavian Barnes via cfe-commits
tavianator added inline comments.


Comment at: src/cxa_thread_atexit.cpp:36-47
@@ +35,14 @@
+  public:
+DtorListHolder() {
+  pthread_key_create(&key_, run_dtors);
+}
+
+~DtorListHolder() {
+  run_dtors(get());
+  pthread_key_delete(key_);
+}
+
+DtorList* get() {
+  return static_cast(pthread_getspecific(key_));
+}
+

majnemer wrote:
> What happens if `pthread_key_create` fails?
Nothing good!  I'll add the necessary error handling.


Comment at: src/cxa_thread_atexit.cpp:61-67
@@ -18,6 +60,9 @@
+_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void *obj,
 void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern int __cxa_thread_atexit_impl(Dtor, void *, void *)
+__attribute__((__weak__));
 
-#endif // HAVE__CXA_THREAD_ATEXIT_IMPL
+  if (__cxa_thread_atexit_impl) {
+return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
+  } else {
+static DtorListHolder dtors;

majnemer wrote:
> Is there a reason to use the weak symbol on non-Android platforms?
Just simplicity.  (There are some fringe benefits, like the ability to build 
against pre-2.18 glibc but have it detect ..._impl() support when run with 
newer libraries.  Or magically supporting musl etc. if they add it, without 
having to recompile.)

Would you rather keep the build-time checks for non-Android platforms?


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21803: [libcxxabi] Provide a fallback __cxa_thread_atexit() implementation

2016-06-28 Thread David Majnemer via cfe-commits
majnemer added a subscriber: majnemer.


Comment at: src/cxa_thread_atexit.cpp:36-47
@@ +35,14 @@
+  public:
+DtorListHolder() {
+  pthread_key_create(&key_, run_dtors);
+}
+
+~DtorListHolder() {
+  run_dtors(get());
+  pthread_key_delete(key_);
+}
+
+DtorList* get() {
+  return static_cast(pthread_getspecific(key_));
+}
+

What happens if `pthread_key_create` fails?


Comment at: src/cxa_thread_atexit.cpp:61-67
@@ -18,6 +60,9 @@
+_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void *obj,
 void *dso_symbol) throw() {
-  extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *);
-  return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-}
+  extern int __cxa_thread_atexit_impl(Dtor, void *, void *)
+__attribute__((__weak__));
 
-#endif // HAVE__CXA_THREAD_ATEXIT_IMPL
+  if (__cxa_thread_atexit_impl) {
+return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
+  } else {
+static DtorListHolder dtors;

Is there a reason to use the weak symbol on non-Android platforms?


http://reviews.llvm.org/D21803



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits