[libunwind] r314632 - SjLj: make the SjLj implementation more portable

Saleem Abdulrasool via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 1 13:06:48 PDT 2017


Author: compnerd
Date: Sun Oct  1 13:06:48 2017
New Revision: 314632

URL: http://llvm.org/viewvc/llvm-project?rev=314632&view=rev
Log:
SjLj: make the SjLj implementation more portable

This moves the definition of the internal helpers
`__Unwind_SjLj_GetTopOfFunctionStack` and
`__Unwind_SjLj_SetTopOfFunctionStack` into `Unwind-sjlj.c`.  These are
not extra functions specific to Apple, but rather are internal
implementation details of SjLj support in the LLVM libunwind
implementation.

This allows us to remove the internal header unwind_ext.h, as these
functions are not meant to be used as SPI either.  Because they are
static, they will be given implicit hidden visibility, but due to the
simplicity should get fully inlined into the actual use.

Use the C11 standard static TLS annotation (`_Thread_local`) if
possible, otherwise, use the Windows specific `__declspec(thread)` when
targeting Windows or the GNU `__thread` extension.  In theory, it should
be possible for this implementation to use a `pthread_setspecific` and
`pthread_getspecific` on platforms with pthreads or `SetFlsValue` and
`GetFlsValue` on Windows for non-static TLS.  However, static TLS tends
to be significantly faster, so we really should prefer that over the
dynamic TLS approach.  On Apple environments, when not building for the
loader (dyld), use the pre-allocated TLS slot in the loader rather than
the local static TLS variable.

Note that the un-threaded support of libunwind is still present as
before, however, it is unsafe to use in a threaded environment as the
cleanup stack may be mutated incorrectly due to lack of locking across
threads.  In the static TLS model, the lock is unneeded as each thread
of execution retains its own copy of the cleanup stack.

Take the opportunity to clean up the comment block, removing the iOS
specific note as the SjLj implementation can be used outside of the
context of iOS.  Convert the rest of the explanation to a doxygen style
comment block.

Removed:
    libunwind/trunk/src/unwind_ext.h
Modified:
    libunwind/trunk/src/CMakeLists.txt
    libunwind/trunk/src/Unwind-sjlj.c
    libunwind/trunk/src/Unwind_AppleExtras.cpp

Modified: libunwind/trunk/src/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/CMakeLists.txt?rev=314632&r1=314631&r2=314632&view=diff
==============================================================================
--- libunwind/trunk/src/CMakeLists.txt (original)
+++ libunwind/trunk/src/CMakeLists.txt Sun Oct  1 13:06:48 2017
@@ -31,7 +31,6 @@ set(LIBUNWIND_HEADERS
     libunwind_ext.h
     Registers.hpp
     UnwindCursor.hpp
-    unwind_ext.h
     ${CMAKE_CURRENT_SOURCE_DIR}/../include/libunwind.h
     ${CMAKE_CURRENT_SOURCE_DIR}/../include/unwind.h)
 

Modified: libunwind/trunk/src/Unwind-sjlj.c
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/Unwind-sjlj.c?rev=314632&r1=314631&r2=314632&view=diff
==============================================================================
--- libunwind/trunk/src/Unwind-sjlj.c (original)
+++ libunwind/trunk/src/Unwind-sjlj.c Sun Oct  1 13:06:48 2017
@@ -17,20 +17,14 @@
 #include <stdlib.h>
 
 #include "config.h"
-#include "unwind_ext.h"
 
-//
-// 32-bit iOS uses setjump/longjump based C++ exceptions.
-// Other architectures use "zero cost" exceptions.
-//
-// With SJLJ based exceptions, any function that has a catch clause or needs to
-// do any clean up when an exception propagates through it, needs to call 
-// _Unwind_SjLj_Register() at the start of the function and 
-// _Unwind_SjLj_Unregister() at the end.  The register function is called with 
-// the address of a block of memory in the function's stack frame.  The runtime
-// keeps a linked list (stack) of these blocks - one per thread.  The calling 
-// function also sets the personality and lsda fields of the block.
-//
+/// With SJLJ based exceptions, any function that has a catch clause or needs to
+/// do any clean up when an exception propagates through it, needs to call
+/// \c _Unwind_SjLj_Register at the start of the function and
+/// \c _Unwind_SjLj_Unregister at the end.  The register function is called with
+/// the address of a block of memory in the function's stack frame.  The runtime
+/// keeps a linked list (stack) of these blocks - one per thread.  The calling
+/// function also sets the personality and lsda fields of the block.
 
 #if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
 
@@ -53,6 +47,48 @@ struct _Unwind_FunctionContext {
   void                           *jbuf[];
 };
 
+#if defined(_LIBUNWIND_HAS_NO_THREADS)
+# define _LIBUNWIND_THREAD_LOCAL
+#else
+# if __STDC_VERSION__ >= 201112L
+#  define _LIBUNWIND_THREAD_LOCAL _Thread_local
+# elif defined(_WIN32)
+#  define _LIBUNWIND_THREAD_LOCAL __declspec(thread)
+# elif defined(__GNUC__) || defined(__clang__)
+#  define _LIBUNWIND_THREAD_LOCAL __thread
+# else
+#  error Unable to create thread local storage
+# endif
+#endif
+
+
+#if !defined(FOR_DYLD)
+
+#if defined(__APPLE__)
+#include <System/pthread_machdep.h>
+#else
+static _LIBUNWIND_THREAD_LOCAL _Unwind_FunctionContext *stack = nullptr;
+#endif
+
+static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
+#if defined(__APPLE__)
+  return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
+#else
+  return stack;
+#endif
+}
+
+static void
+__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
+#if defined(__APPLE__)
+  _pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
+#else
+  stack = fc;
+#endif
+}
+
+#endif
+
 
 /// Called at start of each function that catches exceptions
 _LIBUNWIND_EXPORT void

Modified: libunwind/trunk/src/Unwind_AppleExtras.cpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/Unwind_AppleExtras.cpp?rev=314632&r1=314631&r2=314632&view=diff
==============================================================================
--- libunwind/trunk/src/Unwind_AppleExtras.cpp (original)
+++ libunwind/trunk/src/Unwind_AppleExtras.cpp Sun Oct  1 13:06:48 2017
@@ -11,7 +11,6 @@
 #include "config.h"
 #include "AddressSpace.hpp"
 #include "DwarfParser.hpp"
-#include "unwind_ext.h"
 
 
 // private keymgr stuff
@@ -183,32 +182,3 @@ bool checkKeyMgrRegisteredFDEs(uintptr_t
 
 }
 
-
-#if !defined(FOR_DYLD) && defined(_LIBUNWIND_BUILD_SJLJ_APIS)
-
-#ifndef _LIBUNWIND_HAS_NO_THREADS
-  #include <System/pthread_machdep.h>
-#else
-  _Unwind_FunctionContext *fc_ = nullptr;
-#endif
-
-// Accessors to get get/set linked list of frames for sjlj based execeptions.
-_LIBUNWIND_HIDDEN
-struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
-#ifndef _LIBUNWIND_HAS_NO_THREADS
-  return (struct _Unwind_FunctionContext *)
-    _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
-#else
-  return fc_;
-#endif
-}
-
-_LIBUNWIND_HIDDEN
-void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
-#ifndef _LIBUNWIND_HAS_NO_THREADS
-  _pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
-#else
-  fc_ = fc;
-#endif
-}
-#endif

Removed: libunwind/trunk/src/unwind_ext.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/unwind_ext.h?rev=314631&view=auto
==============================================================================
--- libunwind/trunk/src/unwind_ext.h (original)
+++ libunwind/trunk/src/unwind_ext.h (removed)
@@ -1,37 +0,0 @@
-//===-------------------------- unwind_ext.h ------------------------------===//
-//
-//                     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.
-//
-//
-//  Extensions to unwind API.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __UNWIND_EXT__
-#define __UNWIND_EXT__
-
-#include "unwind.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// These platform specific functions to get and set the top context are
-// implemented elsewhere.
-
-extern struct _Unwind_FunctionContext *
-__Unwind_SjLj_GetTopOfFunctionStack();
-
-extern void
-__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __UNWIND_EXT__
-
-




More information about the cfe-commits mailing list