]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Remove fake pthreads
authorVMware, Inc <>
Wed, 18 Sep 2013 03:16:56 +0000 (20:16 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 23 Sep 2013 05:01:53 +0000 (22:01 -0700)
A while ago, we decided to always compile with pthreads; optimizing for
single-threaded programs no longer makes sense.

Which means vthreadBase.c can get cleaned up.  (Notice that this
implements the "best thing to do" comment on lines 195-6).

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/misc/vthreadBase.c

index c4c309769d643366d08a11c7ddbaebc197ecfd5f..84964a7e1e43a76384bdaf89acc97e0e1ca680ba 100644 (file)
  *      threads.  If lib/thread is used on top of this library, the lib/thread
  *      NoID function may introduce a smaller limit.
  *
- *      On Windows and Mac, there is no way to compile single-threaded,
- *      so just make all the multi-threaded calls.
- *
- *      On Linux, use some more complex logic to operate in two modes:
- *      - if _REENTRANT is defined (or implied by -pthread), link
- *        directly to all multithreaded symbols.
- *      - otherwise, compile in fake-pthread functions and choose at
- *        runtime whether to use them, depending on if pthreads are loaded.
+ *      On Windows and Mac, native OS TLS support is available.
+ *      On Linux, require pthreads. (Generally this implies -pthread and _REENTRANT)
  */
 
-#if defined __linux__ && !defined _REENTRANT
-#  define FAKE_PTHREADS
-#endif
-
 #if defined _WIN32
 #  include <windows.h>
 #else
@@ -149,183 +139,6 @@ static struct {
 };
 
 
-#if defined FAKE_PTHREADS
-/*
- * glibc can either be used with pthreads or without.
- *
- * Nominally, glibc-without-pthreads is useful in cases like embedded systems
- * where the overhead of libpthread (in terms of memory or CPU time) is not
- * justified.  Unfortunately for us, ESX userworlds are close enough to
- * embedded systems that it's easier to navigate the pain than argue in favor
- * of linking extraneous libraries.  (Eventually, we should just link.)
- *
- * A quick run-through of all the different ways to run a Linux program:
- *
- * Compile with -pthread: (best, but uncommon)
- * Compiler passes -pthread to gcc, which implicitly defines _REENTRANT.
- * If this constant is defined, it is OK to link directly to all pthread
- * symbols: the program is known multithreaded at compile-time.  We will
- * also accept somebody passing -D_REENTRANT as an indication they know
- * what they are doing and want compile-time threading support.
- *
- * Compile without -pthread, link with -lpthread (common)
- * Running multi-threaded, but this cannot be distinguised from running
- * single-threaded without peeking into the dynamic linker.
- * at run-time.
- *
- * Compile without -pthread, link without -lpthread, dlopen("libpthread.so")
- * This is broken.  libc starts using a simplified pthread implementation,
- * then the dynamic load changes the implementation mid-stream.  Any locks
- * created before the dynamic open are thus unsafe.  DO NOT DO THIS.
- *
- * Compile without -pthread, link without -lpthread, no dlopen() (common)
- * Running single-threaded.
- *
- *
- * After much experimentation, the only sane way to construct VThreadBase is
- * with weak symbols, and require a ((sym != NULL) ? pthread_sym : fake_sym)
- * construct for all pthread symbols used herein.  This approach has two
- * downsides:
- * - extra branch on all TLS lookups (though easily predicted)
- * - some compilers (gcc-4.1.0, gcc-4.1.1) have a buggy weak-symbol
- *   optimizer.
- * Both of these downsides can be avoided by passing -D_REENTRANT to
- * the compilation of this environment and supplying -lpthread at link time.
- *
- * Rejected approaches:
- * - use dl_xxx to detect libpthread and link at runtime.  This adds a libdl
- *   dependency that is as bad as the libpthread dependency in the first place.
- * - use __libc_dlxxx@_GLIBC_PRIVATE symbols to detect libpthread and link
- *   at runtime.  This works; however, 'rpm' refuses to package binaries
- *   with @_GLIBC_PRIVATE symbols and so builds break.
- * - use a fake TLS backed by a locked hash table.  Unfortunately,
- *   pthread_mutex_lock isn't async-signal-safe and we do read TLS within
- *   our signal handlers.  (Oddly enough, pthread_getspecific is not marked
- *   as async-signal-safe either, but it happens to work fine.)
- * - use a fake TLS backed by an atomic hash table.  Alas, our atomic
- *   hash tables are insert-only, which causes a memory leak even if threads
- *   exit cleanly.
- *
- * If anything here ever breaks, the best thing to do is simply admit that
- * this is the 21st century and always compile with -pthread.
- */
-
-#if defined __GNUC__
-/* gcc-4.1.0 and gcc-4.1.1 have buggy weak-symbol optimization. */
-#  if __GNUC__ == 4 && __GNUC_MINOR__ == 1 && \
-     (__GNUC_PATCHLEVEL__ == 0 || __GNUC_PATCHLEVEL__ == 1)
-#  error Cannot build VThreadBase with weak symbols: buggy gcc version
-#  endif
-#endif
-
-extern int pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
-   __attribute__ ((weak));
-extern int pthread_key_delete(pthread_key_t key)
-   __attribute__ ((weak));
-extern int pthread_setspecific(pthread_key_t key, const void *pointer)
-   __attribute__ ((weak));
-extern void * pthread_getspecific(pthread_key_t key)
-   __attribute__ ((weak));
-extern int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask)
-   __attribute__ ((weak));
-
-
-static const pthread_key_t nothreadTLSKey = 0x12345;  /* Chosen to be obvious */
-static void *nothreadTLSData;
-
-/*
- *-----------------------------------------------------------------------------
- *
- * fake_key_create --
- * fake_key_delete --
- * fake_setspecific --
- * fake_getspecific --
- * fake_sigmask --
- *
- *      Trivial implementations of equivalent pthread functions, to be used
- *      when the weak pthread_xxx symbols are not defined (e.g. when
- *      libpthread.so is not loaded).
- *
- *      These versions always succeed and are hard-coded to assume one thread.
- *
- *      NOTE: These functions will not work if libpthread is dlopen()ed.
- *      That said, any pthread functions (like pthread_mutex_lock) also
- *      will not work, so we have lost nothing.
- *
- * Results:
- *      See pthread_xxx; these versions always succeed.
- *
- * Side effects:
- *      See pthread_xxx.
- *
- *-----------------------------------------------------------------------------
- */
-
-static int
-fake_key_create(pthread_key_t *key,
-                void (*destr_function)(void *))
-{
-   *key = nothreadTLSKey;
-   return 0;
-}
-
-static int
-fake_key_delete(pthread_key_t key)
-{
-   /*
-    * fake_key_delete will not be called if there are no threads because:
-    * - fake_key_create does not fail with no threads
-    * - single threads cannot race with themselves in VThreadBaseGetKey
-    *   (a race requires deleting extra keys)
-    */
-   NOT_REACHED();
-}
-
-static int
-fake_setspecific(pthread_key_t key,
-                 const void *pointer)
-{
-   ASSERT(key == nothreadTLSKey);
-   ASSERT(Atomic_Read(&vthreadBaseGlobals.numThreads) <= 1);
-   nothreadTLSData = (void *)pointer;
-   return 0;
-}
-
-static void *
-fake_getspecific(pthread_key_t key)
-{
-   ASSERT(key == nothreadTLSKey);
-   ASSERT(Atomic_Read(&vthreadBaseGlobals.numThreads) <= 1);
-   return nothreadTLSData;
-}
-
-static int
-fake_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask)
-{
-   /*
-    * Verified against glibc sources: pthread_sigmask and sigprocmask
-    * use the same implementation for any kernel that supports
-    * the rt_sigprocmask syscall (and all kernels we support do).
-    */
-   return sigprocmask(how, newmask, oldmask);
-}
-
-
-/*
- * Replace all pthread_xxx calls with a runtime choice.  This
- * code is not quite optimal; if perfection is necessary,
- * compile with -D_REENTRANT to link directly to pthreads.
- */
-#define WRAP_WEAK(_fn)   \
-   ((pthread_##_fn != NULL) ? pthread_##_fn : fake_##_fn)
-#define pthread_key_create   WRAP_WEAK(key_create)
-#define pthread_key_delete   WRAP_WEAK(key_delete)
-#define pthread_getspecific  WRAP_WEAK(getspecific)
-#define pthread_setspecific  WRAP_WEAK(setspecific)
-#define pthread_sigmask      WRAP_WEAK(sigmask)
-
-#endif  /* FAKE_PTHREADS */
-
 /*
  * Code to mask all asynchronous signals
  *