Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Making HPC-GAP work with Julia #3734

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 0 additions & 2 deletions Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ SOURCES += src/intfuncs.c
SOURCES += src/intrprtr.c
SOURCES += src/io.c
SOURCES += src/iostream.c
ifeq ($(HPCGAP),no) # we don't support a kernel API in HPC-GAP atm
SOURCES += src/libgap-api.c
endif
SOURCES += src/listfunc.c
SOURCES += src/listoper.c
SOURCES += src/lists.c
Expand Down
26 changes: 26 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,29 @@ 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 Check: --enable-guards requires --enable-hpcgap
dnl

AS_IF([[test "x$enable_guards" == "xyes" && test "x$enable_hpcgap" == "xno"]],
[AC_MSG_ERROR([Option --enable-guards requires --enable-hpcgap])])

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 @@ -915,6 +938,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
4 changes: 0 additions & 4 deletions lib/oper.g
Original file line number Diff line number Diff line change
Expand Up @@ -1983,8 +1983,6 @@ BIND_GLOBAL( "InstallGlobalFunction", function( arg )
od;
end );

if not IsHPCGAP then

BIND_GLOBAL( "FLUSH_ALL_METHOD_CACHES", function()
local oper,j;
for oper in OPERATIONS do
Expand All @@ -1994,8 +1992,6 @@ BIND_GLOBAL( "FLUSH_ALL_METHOD_CACHES", function()
od;
end);

fi;

if BASE_SIZE_METHODS_OPER_ENTRY <> 6 then
Error("MethodsOperation must be updated for new BASE_SIZE_METHODS_OPER_ENTRY");
fi;
Expand Down
6 changes: 6 additions & 0 deletions src/boehm_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ void RetypeBagIntern(Bag bag, UInt new_type)
if (old_type == new_type)
return;

#if defined(HPCGAP) && defined(USE_HPC_GUARDS)
WriteGuard(bag);
#endif
/* change the size-type word */
header->type = new_type;
{
Expand Down Expand Up @@ -456,6 +459,9 @@ UInt ResizeBag(Bag bag, UInt new_size)
CollectBags(0, 0);
#endif

#if defined(HPCGAP) && defined(USE_HPC_GUARDS)
WriteGuard(bag);
#endif
BagHeader * header = BAG_HEADER(bag);

/* get type and old size of the bag */
Expand Down
73 changes: 73 additions & 0 deletions src/gasman.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@

#include "common.h"

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


/****************************************************************************
**
Expand Down Expand Up @@ -139,6 +144,46 @@ EXPORT_INLINE UInt TNUM_BAG(Bag bag)
return BAG_HEADER(bag)->type;
}

/****************************************************************************
**
*F ReadCheck(<bag>) . . . . . . . . . . . . . is the bag readable in HPCGAP?
*F WriteCheck(<bag>) . . . . . . . . . . . . is the bag writable in HPCGAP?
*F HandleReadGuardError(<bag>) . . . . . . . . . . signal read access error
*F HandleWriteGuardError(<bag>) . . . . . . . . . signal write access error
**
** These funtion handle access checks in HPCGAP, i.e. whether a bag can
** safely be read or modified without causing race conditions. These are
** called in functions such as PTR_BAG() and CONST_PTR_BAG(), which should
** implicitly or explicitly guard all object accesses. In order to access
** objects without triggering checks, alternative functions UNSAFE_PTR_BAG()
** and UNSAFE_CONST_PTR_BAG() are provided.
*/
#ifdef HPCGAP
extern int ExtendedGuardCheck(Bag) PURE_FUNC;

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 ExtendedGuardCheck(bag);
}

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

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

/****************************************************************************
**
Expand Down Expand Up @@ -296,15 +341,43 @@ EXPORT_INLINE UInt SIZE_BAG_CONTENTS(const void *ptr) {
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
2 changes: 0 additions & 2 deletions src/gvars.c
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,6 @@ Obj GVarFunction(GVarDescriptor *gvar)
ErrorQuit("Global variable '%s' not initialized", (UInt)(gvar->name), 0);
if (REGION(result))
ErrorQuit("Global variable '%s' is not a function", (UInt)(gvar->name), 0);
ImpliedWriteGuard(result);
if (TNUM_OBJ(result) != T_FUNCTION)
ErrorQuit("Global variable '%s' is not a function", (UInt)(gvar->name), 0);
MEMBAR_READ();
Expand All @@ -1499,7 +1498,6 @@ Obj GVarOptFunction(GVarDescriptor *gvar)
return (Obj) 0;
if (REGION(result))
return (Obj) 0;
ImpliedWriteGuard(result);
if (TNUM_OBJ(result) != T_FUNCTION)
return (Obj) 0;
MEMBAR_READ();
Expand Down
114 changes: 42 additions & 72 deletions src/hpc/guards.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,108 +11,78 @@
#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))
return bag;
region = REGION(bag);
if (region && region->owner != GetTLS() && region->alt_owner != GetTLS())
WriteGuardError(bag
#ifdef VERBOSE_GUARDS
, file, line, func, expr
#ifdef USE_HPC_GUARDS
if (!WriteCheck(bag))
HandleWriteGuardError(bag);
#endif
);
return bag;
return bag;
}

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

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

EXPORT_INLINE int CheckExclusiveWriteAccess(Bag bag)
{
Region *region;
if (!IS_BAG_REF(bag))
#ifdef USE_HPC_GUARDS
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;
#else
return 1;
region = REGION(bag);
if (!region)
return 0;
return region->owner == GetTLS() || region->alt_owner == GetTLS()
|| TLS(DisableGuards) >= 2;
#endif
}

#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))
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
#ifdef USE_HPC_GUARDS
if (!ReadCheck(bag))
HandleReadGuardError(bag);
#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))
#ifdef USE_HPC_GUARDS
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;
#else
return 1;
region = REGION(bag);
return !(region && region->owner != GetTLS() &&
!region->readers[TLS(threadID)] && region->alt_owner != GetTLS())
|| TLS(DisableGuards) >= 2;
#endif
}

#endif // GAP_HPC_GUARD_H
#endif // GAP_HPC_GUARD_H
2 changes: 1 addition & 1 deletion src/hpc/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ UInt SyNumGCThreads = 0;
*V SingleThreadStartup . . . . . . . . . start HPC-GAP with just one thread
**
*/
UInt SingleThreadStartup = 0;
UInt SingleThreadStartup = 1;

/****************************************************************************
**
Expand Down
Loading