diff options
author | Emil Velikov <emil.velikov@collabora.com> | 2017-02-20 11:18:58 +0000 |
---|---|---|
committer | Uli Schlachter <psychon@znc.in> | 2017-03-01 17:42:40 +0100 |
commit | 8340ebd656c7e1a5b6d31170c1f3c87df043e793 (patch) | |
tree | 0da84379a074c2e047c9c7cf2ea3c8331223d6a6 | |
parent | 816ca2affbd5a9d2e551851de4d0a26ec080d948 (diff) | |
download | xcb-pthread-stubs-8340ebd656c7e1a5b6d31170c1f3c87df043e793.tar.gz |
Rework the pthread-stub design
The current design handles the most common use-cases, although it causes
breakage on others (when a pthreads liked library is dlopened). Refer to
the README for further details.
The new design, makes pthread-stubs a "meta" package which _never_
provides a library but only a .pc file.
pthread-stubs checks if the run-time (libc or otherwise) expose
lightweight pthread symbols to link against and defaults to a full blown
pthread.
This way projects can use the Cflags/Libs without having to know the
details. Alternatively they can directly link against the pthread
implementation, although that might bring unwarranted overhead.
v2:
- Remove m4 macro, always use -pthread and document why.
- Sort the symbol list, document how it's derived what is allowed and
what not.
- Rework the README to start from current state of afairs to past ones.
- Document platforms that are 'safe' and ones that are not.
v3:
- Add SVN note about -pthread + Cygwin/mingw/mingw-w64
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
Acked-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Uli Schlachter <psychon@znc.in>
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | README | 114 | ||||
-rw-r--r-- | configure.ac | 60 | ||||
-rw-r--r-- | pthread-stubs.pc.in | 3 | ||||
-rw-r--r-- | stubs.c.m4 | 91 |
5 files changed, 137 insertions, 141 deletions
diff --git a/Makefile.am b/Makefile.am index 2329572..93123a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,12 +1,2 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = pthread-stubs.pc - -if BUILD_LIB -stubs.c: list.m4 stubs.c.m4 - m4 -P -I $(srcdir) stubs.c.m4 > $@ - -lib_LTLIBRARIES = libpthread-stubs.la -nodist_libpthread_stubs_la_SOURCES = stubs.c -CLEANFILES = stubs.c -endif -EXTRA_libpthread_stubs_la_SOURCES = stubs.c.m4 @@ -1,9 +1,105 @@ -This library provides weak aliases for pthread functions not provided in libc -or otherwise available by default. Libraries like libxcb rely on pthread -stubs to use pthreads optionally, becoming thread-safe when linked to -libpthread, while avoiding any performance hit when running single-threaded. -libpthread-stubs supports this behavior even on platforms which do not supply -all the necessary pthread stubs. On platforms which already supply all the -necessary pthread stubs, this package ships only the pkg-config file -pthread-stubs.pc, to allow libraries to unconditionally express a dependency -on pthread-stubs and still obtain correct behavior. +Project description +------------------- + +Currently the project provides only a pkg-config [.pc] file, pthread-stubs.pc. +The latter contains the Cflags/Libs flags applicable to programs/libraries +that use only lightweight pthread API. See the next sections for the reasoning +and implementation details. + +Historically this project used to provide either: + - a .pc file, when the C runtime was providing the pthread symbols +or + - a .pc file and a library which implements weak stubs for the pthread symbols, +which are not available in the C runtime. + +Since then, the latter case was found to have a fundamental design issue. + + +Design +------ + +On platforms where the lightweight pthread symbols are provided by the runtime, +the .pc files provides empty Cflags/Libs flags. + +Currently the following platforms fit the above category: + - GNU/Linux - GCC/Clang/GLibC/Musl + - Solaris 10 and later + - Cygwin + - GNU/Hurd + - GNU/kFreeBSD + +For others, each of Cflags/Libs expands to full blown pthread. + +For example: + - FreeBSD and derivatives + - OpenBSD - uses a heavily patched copy of pthread-stubs to workaround this + - other BSD platforms ? + +Unchecked: + - MSYS/MINGW + - Darwin - GCC/Clang - should be the same as their Linux counter part + + +Many platforms have their own eccentric way of managing pthread compilation and +linkage. The ones realistically supported by pthread-stubs [and projects that +depend on it] work with '-pthread'. + +GCC supports -pthread for: +Aarch64, ARM, Darwin, IA-64, MIPS, PowerPC, SPARC, x86 +Cygwin and x86 Windows may need a trivial patch for older GCC versions. +See SVN rev 214161 and 171833/171834 respectively. + + +Clang: +Aarch64, ARM, x86 and likely others. + +SunCC/Oracle compiler: +Requires -mt -lpthread. As of Solaris 10 (oldest currently supported version) +all the pthread API lives in libc. Thus we'll _never_ get here. + + +With previous design, one could get mismatched calls to the pthreads API. +Consider the following scenario: + - Program and/or its dependencies links only against libpthread-stubs, +since it uses lightweight API. Say pthread_mutex_lock. + - At a later stage the program and/or its dependencies dlopens a library +which effectively [either directly or via any of its own dependencies] pulls a +full blown pthread. Let's call that libB. + - The libpthread-stubs weak symbols get overridden by the libB ones. + - pthread_mutex_unlock is executed (which now originates from libB) and BOOM. + +Amount and severity of issues depend on a number of factors. In either case +things go horribly wrong sooner on later. + + +The symbols +----------- + +The following list of symbols is taken from the libc provided by GLibC. + +It is deemed sufficient and reasonably accurate of what the 'lightweight' +pthread symbols are, since GLibC is one of the few (the only) implementations +which has the distinct split. + +Most/all other C runtime implementations provide all the pthread API in a +single library. + +Note that the following list is incomplete wrt libc-2.24.so and that further +symbols may be added in the future to bring the two closer. Adding symbols +which are not available in GLibC libc is NOT allowed. + + pthread_condattr_destroy + pthread_condattr_init + pthread_cond_broadcast + pthread_cond_destroy + pthread_cond_init + pthread_cond_signal + pthread_cond_timedwait + pthread_cond_wait + pthread_equal + pthread_exit + pthread_mutex_destroy + pthread_mutex_init + pthread_mutex_lock + pthread_mutex_unlock + pthread_self diff --git a/configure.ac b/configure.ac index ef300ad..09d3b78 100644 --- a/configure.ac +++ b/configure.ac @@ -9,39 +9,39 @@ AC_CONFIG_HEADERS([config.h]) AC_PROG_LIBTOOL AC_PROG_CC - -dnl Detection code for compilers supporting the __attribute__((weak, alias)) -dnl feature. Original code present in unieject's repository -dnl Diego Pettenò <flameeyes@gentoo.org> -ac_save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -Werror" -AC_CACHE_CHECK([if compiler supports __attribute__((weak, alias))], - [cc_cv_attribute_alias], - [AC_COMPILE_IFELSE([ - void other_function(void *foo) { } - void some_function(void *foo) __attribute__((weak, alias("other_function"))); - ], - [cc_cv_attribute_alias=yes], - [cc_cv_attribute_alias=no]) - ]) -CFLAGS="$ac_save_CFLAGS" -if test "x$cc_cv_attribute_alias" = "xyes"; then - AC_DEFINE([SUPPORT_ATTRIBUTE_ALIAS], 1, [Define this if the compiler supports the alias attribute]) +dnl Check if the following functions have stubs. +dnl See the README for specifics about the list. +funclist="\ +pthread_condattr_destroy \ +pthread_condattr_init \ +pthread_cond_broadcast \ +pthread_cond_destroy \ +pthread_cond_init \ +pthread_cond_signal \ +pthread_cond_timedwait \ +pthread_cond_wait \ +pthread_equal \ +pthread_exit \ +pthread_mutex_destroy \ +pthread_mutex_init \ +pthread_mutex_lock \ +pthread_mutex_unlock \ +pthread_self" + +AC_CHECK_FUNCS($funclist, [], [HAVE_STUBS=no]) + + +if test "x$HAVE_STUBS" != xno; then + PKG_CONFIG_CFLAGS= + PKG_CONFIG_LIBS= +else + dnl See the README why '-pthread' is deemed sufficient. + PKG_CONFIG_CFLAGS="-pthread" + PKG_CONFIG_LIBS="-pthread" fi -dnl Grab the list of functions to test for from our template file. -m4_define([funclist], []) -m4_define([alias], [m4_if([$1],[na],[], [m4_append([funclist], [$3 ])])]) -m4_divert_push([KILL]) -m4_include([list.m4]) -m4_divert_pop([KILL]) - -dnl Check which functions we need to provide aliases for. -PKG_CONFIG_LIBS= -AC_CHECK_FUNCS(funclist, [], [PKG_CONFIG_LIBS='-L${libdir} -lpthread-stubs']) - +AC_SUBST([PKG_CONFIG_CFLAGS]) AC_SUBST([PKG_CONFIG_LIBS]) -AM_CONDITIONAL(BUILD_LIB, test "x$PKG_CONFIG_LIBS" != x) AC_CONFIG_FILES([Makefile pthread-stubs.pc]) AC_OUTPUT diff --git a/pthread-stubs.pc.in b/pthread-stubs.pc.in index 6900598..d256d77 100644 --- a/pthread-stubs.pc.in +++ b/pthread-stubs.pc.in @@ -3,6 +3,7 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ Name: pthread stubs -Description: Stubs missing from libc for standard pthread functions +Description: Meta package for pthread symbols - defaults to heavyweight ones if the C runtime does not provide lightweight ones. Version: @PACKAGE_VERSION@ +Cflags: @PKG_CONFIG_CFLAGS@ Libs: @PKG_CONFIG_LIBS@ diff --git a/stubs.c.m4 b/stubs.c.m4 deleted file mode 100644 index e069b9e..0000000 --- a/stubs.c.m4 +++ /dev/null @@ -1,91 +0,0 @@ -m4_divert(-1)m4_dnl -*- c -*- -m4_changequote(`[',`]') -m4_changecom() - -m4_define([upcase], [m4_translit([$*], [a-z], [A-Z])]) - -m4_define([alias], [m4_dnl -#ifndef upcase(HAVE_[$3]) -#define upcase(NEED_[$1]_STUB) -# ifdef SUPPORT_ATTRIBUTE_ALIAS -[$2] [$3]() __attribute__ ((weak, [alias] ("__pthread_[$1]_stub"))); -# else -# pragma weak [$3] = __pthread_[$1]_stub -# endif -#endif -]) - -m4_divert(0)m4_dnl -/* Copyright (C) 2006 Diego Pettenò - * Copyright (C) 2010 M Joonas Pihlaja - * Inspired by libX11 code copyright (c) 1995 David E. Wexelblat. - * - * This is an automatically created file from stubs.c.m4. Do not edit. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the names of the authors or their - * institutions shall not be used in advertising or otherwise to promote the - * sale, use or other dealings in this Software without prior written - * authorization from the authors. - */ - -#include <pthread.h> -#include <stdlib.h> -#include <string.h> -#include "config.h" - -m4_include([list.m4]) - -#ifdef NEED_ZERO_STUB -static int __pthread_zero_stub() -{ - return 0; -} -#endif - -#ifdef NEED_ABORT_STUB -static int __pthread_abort_stub() -{ - abort(); -} -#endif - -#ifdef NEED_SELF_STUB -static pthread_t __pthread_self_stub(void) -{ - pthread_t th; - - memset(&th, 0, sizeof (th)); - return th; -} -#endif - -#ifdef NEED_EQUAL_STUB -static int __pthread_equal_stub(pthread_t t1, pthread_t t2) -{ - return 1; -} -#endif - -#ifdef NEED_EXIT_STUB -static void __pthread_exit_stub(void *ret) -{ - exit(EXIT_SUCCESS); -} -#endif |