Skip to content

Commit

Permalink
Collapsed revision
Browse files Browse the repository at this point in the history
* Unward changes.
* HACK: run unward automatically for HPC-GAP builds
* Initial support for pthread-based thread-local storage.
* Support native TLS option in configure script.
* Update .gitignore and .travis.yml files from master.

Also fix unward build.
* Configure pure & constructor attributes.
* Improve macOS asm-based TLS implementation.
* Add option to disable HPC-GAP guards.
* Document TLS better.
* Remove pure function hack from guard implementation.
  • Loading branch information
rbehrends committed Oct 7, 2019
1 parent 712a56f commit 791ac67
Show file tree
Hide file tree
Showing 13 changed files with 593 additions and 151 deletions.
149 changes: 149 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ AX_GCC_FUNC_ATTRIBUTE([always_inline])
AX_GCC_FUNC_ATTRIBUTE([format])
AX_GCC_FUNC_ATTRIBUTE([noinline])
AX_GCC_FUNC_ATTRIBUTE([noreturn])
AX_GCC_FUNC_ATTRIBUTE([constructor])
AX_GCC_FUNC_ATTRIBUTE([pure])

dnl compiler builtins
AC_DEFUN([CHECK_COMPILER_BUILTIN],
Expand Down Expand Up @@ -202,6 +204,149 @@ AS_CASE([$with_gc],
)
AC_MSG_RESULT([$with_gc])

dnl
dnl User setting: disable guards (race protection)
dnl

AC_ARG_ENABLE([guards],
[AS_HELP_STRING([--disable-guards],
[disable race protection in HPC-GAP])],
[enable_guards=$enableval],
[enable_guards=yes])

AS_IF([[test "x$enable_guards" == "xyes"]], [
AC_DEFINE([USE_HPC_GUARDS], [1], [define as 1 if guards should be checked])
])
AC_MSG_CHECKING([whether to use race protection in HPC-GAP])
AC_MSG_RESULT([$enable_guards])

dnl
dnl User setting: native thread-local storage (off by default)
dnl See src/hpc/tls.h for more details on thread-local storage options.
dnl

AC_ARG_ENABLE([native-tls],
[AS_HELP_STRING([--enable-native-tls],
[use native thread-local storage implementation])],
[enable_native_tls=$enableval],
[enable_native_tls=no])
AC_MSG_CHECKING([whether to use native tls])
dnl
dnl Distinguish between cases where we support __thread declarations
dnl and situations where we use a pthread_getspecific() implementation.
dnl Right now, we only do the latter for 64-bit macOS. See src/hpc/tls.h
dnl for details.
dnl
enable_macos_tls_asm=default
AS_IF([[test "x$enable_native_tls" == "xyes"]], [
case "$host" in
x86_64-apple-darwin*)
AC_DEFINE([USE_PTHREAD_TLS], [1], [define as 1 if using pthread_getspecific])
dnl
dnl Test if we can optimize pthread_getspecific() calls via
dnl inline assembly on macOS.
dnl
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <pthread.h>
#include <string.h>
#define OFFS 0x100
#define END (-1)
int cmpOpCode(unsigned char *code, int *with) {
int result = 0;
while (*with >= 0) {
if (*with == OFFS) {
result = *code;
} else {
if (*code != *with)
return -1;
}
code++;
with++;
}
return result;
}
int main() {
// This is an idea borrowed from Mono. We test if the implementation
// of pthread_getspecific() uses the assembly code below. If that is
// true, we can replace calls to pthread_getspecific() with the
// matching inline assembly, allowing a significant performance boost.
#if defined(__APPLE__) && defined(__x86_64__)
// There are two possible implementations.
static int asm_code[] = {
// movq %gs:[OFFS](,%rdi,8), %rax
// retq
0x65, 0x48, 0x8b, 0x04, 0xfd, OFFS, 0x00, 0x00, 0x00, 0xc3, END
};
static int asm_code2[] = {
// pushq %rbp
// movq %rsp, %rbp
// movq %gs:[OFFS](,%rdi,8),%rax
// popq %rbp
// retq
0x55, 0x48, 0x89, 0xe5, 0x65, 0x48, 0x8b, 0x04, 0xfd, OFFS,
0x00, 0x00, 0x00, 0x5d, 0xc3, END
};
if (cmpOpCode((unsigned char *)pthread_getspecific, asm_code) >= 0) {
return 0;
}
if (cmpOpCode((unsigned char *)pthread_getspecific, asm_code2) >= 0) {
return 0;
}
return 1;
#else
#error FAIL
#endif
}
]])],
dnl => Test succeeded
[AC_DEFINE([USE_MACOS_PTHREAD_TLS_ASM], [1],
[define as 1 if macOS assembly implementation supported])
AC_MSG_RESULT([[yes (macOS assembly)]])
enable_macos_tls_asm=yes
],
dnl => Test failed
[AC_MSG_RESULT([[yes (pthread-based)]])
enable_macos_tls_asm=no
],
dnl => Cross-compilation, test impossible
[AC_MSG_RESULT([[yes (pthread-based)]])
enable_macos_tls_asm=no
])
;;
*)
dnl => Any other OS, --with-native-tls specified
AC_DEFINE([USE_NATIVE_TLS], [1], [define as 1 if using native TLS])
AC_MSG_RESULT([yes])
;;
esac
],
[
dnl => --without-native-tls
AC_MSG_RESULT([no])
]
)
dnl
dnl Test if pthread_getspecific() can be overridden as
dnl __attribute__((pure)).
dnl
AC_MSG_CHECKING([[whether pthread_getspecific() can be made pure]])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([[
#include <pthread.h>
__attribute__((pure))
void * pthread_getspecific(pthread_key_t key);
]])], [
AC_MSG_RESULT(yes)
AC_DEFINE([ALLOW_PURE_PTHREAD_GETSPECIFIC], [1],
[define as 1 if pthread_getspecific() can be declared pure])
], [
AC_MSG_RESULT(no)
])

dnl
dnl User setting: Debug mode (off by default)
dnl
Expand Down Expand Up @@ -762,6 +907,10 @@ AS_IF([test "x$enable_hpcgap" = xyes],[
AC_DEFINE([GAP_PRINT_BACKTRACE], [1], [to enable backtraces upon crashes])
])

AS_IF([test "x$enable_macos_tls_asm" = xno],[
AS_BOX([WARNING: macOS fast thread-local storage not available])
])

dnl
dnl Output everything
dnl
Expand Down
16 changes: 15 additions & 1 deletion etc/ci-prepare.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,22 @@ then
fi


# configure and make GAP
# configure
time "$SRCDIR/configure" --enable-Werror $CONFIGFLAGS

if [[ $HPCGAP = yes ]]
then
git clone https://github.com/rbehrends/unward
cd unward
./configure CC=gcc CXX=g++ CFLAGS=-O2 CXXFLAGS=-O2
make
cd ..
unward/bin/unward --inplace src
# commit the result to prevent the docomp test from triggering
git commit -m "Unward" src
fi

# build GAP
time make V=1 -j4

# download packages; instruct wget to retry several times if the
Expand Down
58 changes: 58 additions & 0 deletions src/gasman.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@

#include "system.h"

#ifdef HPCGAP
#include "hpc/region.h"
#include "hpc/tls.h"
#endif


/****************************************************************************
**
Expand Down Expand Up @@ -293,18 +298,71 @@ EXPORT_INLINE UInt SIZE_BAG_CONTENTS(const void *ptr) {
** the application must inform {\Gasman} that it has changed the bag, by
** calling 'CHANGED_BAG(old)' in the above example (see "CHANGED_BAG").
*/
#ifdef HPCGAP
EXPORT_INLINE int ReadCheck(Bag bag)
{
Region *region;
region = REGION(bag);
if (!region)
return 1;
if (region->owner == GetTLS())
return 1;
if (region->readers[TLS(threadID)])
return 1;
return 0;
}

EXPORT_INLINE int WriteCheck(Bag bag)
{
Region *region;
region = REGION(bag);
return !region || region->owner == GetTLS();
}

extern void HandleReadGuardError(Bag);
extern void HandleWriteGuardError(Bag);
#endif // HPCGAP

EXPORT_INLINE Bag *PTR_BAG(Bag bag)
{
GAP_ASSERT(bag != 0);
#ifdef USE_HPC_GUARDS
if (!WriteCheck(bag))
HandleWriteGuardError(bag);
#endif
return *(Bag**)bag;
}

#ifdef USE_HPC_GUARDS
EXPORT_INLINE Bag *UNSAFE_PTR_BAG(Bag bag)
{
GAP_ASSERT(bag != 0);
return *(Bag**)bag;
}
#else
#define UNSAFE_PTR_BAG PTR_BAG
#endif

EXPORT_INLINE const Bag *CONST_PTR_BAG(Bag bag)
{
GAP_ASSERT(bag != 0);
#ifdef USE_HPC_GUARDS
if (!ReadCheck(bag))
HandleReadGuardError(bag);
#endif
return *(const Bag * const *)bag;
}

#ifdef USE_HPC_GUARDS
EXPORT_INLINE const Bag *UNSAFE_CONST_PTR_BAG(Bag bag)
{
GAP_ASSERT(bag != 0);
return *(const Bag * const *)bag;
}
#else
#define UNSAFE_CONST_PTR_BAG CONST_PTR_BAG
#endif

EXPORT_INLINE void SET_PTR_BAG(Bag bag, Bag *val)
{
GAP_ASSERT(bag != 0);
Expand Down
Loading

0 comments on commit 791ac67

Please sign in to comment.