Skip to content

Commit

Permalink
Make HPC-GAP guards work without Ward.
Browse files Browse the repository at this point in the history
  • Loading branch information
rbehrends committed Nov 15, 2019
1 parent 012238d commit 6b6c396
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 123 deletions.
19 changes: 19 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,22 @@ 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([--enable-guards],
[enable guards for race protection in HPC-GAP])],
[enable_guards=$enableval],
[enable_guards=no])

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 guards for 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.
Expand Down Expand Up @@ -891,6 +907,9 @@ AS_IF([test "x$enable_hpcgap" = xyes],[
AS_BOX([WARNING: Experimental HPC-GAP mode enabled])
dnl also enable backtrace, to help debug spurious crashes
AC_DEFINE([GAP_PRINT_BACKTRACE], [1], [to enable backtraces upon crashes])
AS_IF([test "x$enable_guards" = xno], [
AS_BOX([WARNING: HPC-GAP guards (race condition protection) are disabled.])
])
])

AS_IF([test "x$enable_macos_tls_asm" = xno],[
Expand Down
18 changes: 16 additions & 2 deletions etc/ci-prepare.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ BUILDDIR=$PWD

if [[ $HPCGAP = yes ]]
then
CONFIGFLAGS="--enable-hpcgap $CONFIGFLAGS"
CONFIGFLAGS="--enable-hpcgap --enable-guards $CONFIGFLAGS"
fi


Expand All @@ -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
100 changes: 32 additions & 68 deletions src/hpc/guards.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,108 +11,72 @@
#ifndef GAP_HPC_GUARD_H
#define GAP_HPC_GUARD_H

#include "gasman.h"
#include "hpc/region.h"
#include "hpc/tls.h"

#ifndef HPCGAP
#error This header is only meant to be used with HPC-GAP
#endif

#ifdef VERBOSE_GUARDS
void WriteGuardError(Bag bag,
const char *file, unsigned line, const char *func, const char *expr);
void ReadGuardError(Bag bag,
const char *file, unsigned line, const char *func, const char *expr);
#else
void WriteGuardError(Bag bag);
void ReadGuardError(Bag bag);
#endif

#ifdef VERBOSE_GUARDS
#define WriteGuard(bag) WriteGuardFull(bag, __FILE__, __LINE__, __FUNCTION__, #bag)
static ALWAYS_INLINE Bag WriteGuardFull(Bag bag,
const char *file, unsigned line, const char *func, const char *expr)
#else
static ALWAYS_INLINE Bag WriteGuard(Bag bag)
#endif
{
Region *region;
if (!IS_BAG_REF(bag))
if (!WriteCheck(bag))
HandleWriteGuardError(bag);
return bag;
region = REGION(bag);
if (region && region->owner != GetTLS() && region->alt_owner != GetTLS())
WriteGuardError(bag
#ifdef VERBOSE_GUARDS
, file, line, func, expr
#endif
);
return bag;
}


EXPORT_INLINE Bag ImpliedWriteGuard(Bag bag)
{
return bag;
return bag;
}

EXPORT_INLINE int CheckWriteAccess(Bag bag)
{
Region *region;
if (!IS_BAG_REF(bag))
return 1;
region = REGION(bag);
return !(region && region->owner != GetTLS() && region->alt_owner != GetTLS())
|| TLS(DisableGuards) >= 2;
Region * region;
if (!IS_BAG_REF(bag))
return 1;
region = REGION(bag);
return !(region && region->owner != GetTLS() &&
region->alt_owner != GetTLS()) ||
TLS(DisableGuards) >= 2;
}

EXPORT_INLINE int CheckExclusiveWriteAccess(Bag bag)
{
Region *region;
if (!IS_BAG_REF(bag))
return 1;
region = REGION(bag);
if (!region)
return 0;
return region->owner == GetTLS() || region->alt_owner == GetTLS()
|| TLS(DisableGuards) >= 2;
Region * region;
if (!IS_BAG_REF(bag))
return 1;
region = REGION(bag);
if (!region)
return 0;
return region->owner == GetTLS() || region->alt_owner == GetTLS() ||
TLS(DisableGuards) >= 2;
}

#ifdef VERBOSE_GUARDS
#define ReadGuard(bag) ReadGuardFull(bag, __FILE__, __LINE__, __FUNCTION__, #bag)
static ALWAYS_INLINE Bag ReadGuardFull(Bag bag,
const char *file, unsigned line, const char *func, const char *expr)
#else
static ALWAYS_INLINE Bag ReadGuard(Bag bag)
#endif
{
Region *region;
if (!IS_BAG_REF(bag))
if (!ReadCheck(bag))
HandleReadGuardError(bag);
return bag;
region = REGION(bag);
if (region && region->owner != GetTLS() &&
!region->readers[TLS(threadID)] && region->alt_owner != GetTLS())
ReadGuardError(bag
#ifdef VERBOSE_GUARDS
, file, line, func, expr
#endif
);
return bag;
}


static ALWAYS_INLINE Bag ImpliedReadGuard(Bag bag)
{
return bag;
return bag;
}

static ALWAYS_INLINE int CheckReadAccess(Bag bag)
{
Region *region;
if (!IS_BAG_REF(bag))
return 1;
region = REGION(bag);
return !(region && region->owner != GetTLS() &&
!region->readers[TLS(threadID)] && region->alt_owner != GetTLS())
|| TLS(DisableGuards) >= 2;
Region * region;
if (!IS_BAG_REF(bag))
return 1;
region = REGION(bag);
return !(region && region->owner != GetTLS() &&
!region->readers[TLS(threadID)] &&
region->alt_owner != GetTLS()) ||
TLS(DisableGuards) >= 2;
}

#endif // GAP_HPC_GUARD_H
#endif // GAP_HPC_GUARD_H
Loading

0 comments on commit 6b6c396

Please sign in to comment.