diff --git a/src/hpc/thread.c b/src/hpc/thread.c index fd11baaddf..5dd726b679 100644 --- a/src/hpc/thread.c +++ b/src/hpc/thread.c @@ -231,8 +231,6 @@ void RunThreadedMain(int (*mainFunction)(int, char **, char **), RunThreadedMain2(mainFunction, argc, argv, environ); } -extern void InitTraversalModule(); - static void RunThreadedMain2(int (*mainFunction)(int, char **, char **), int argc, char ** argv, @@ -266,9 +264,6 @@ static void RunThreadedMain2(int (*mainFunction)(int, char **, char **), InitSignals(); if (sySetjmp(TLS(threadExit))) exit(0); - /* Traversal functionality may be needed during the initialization - * of some modules, so we set it up now. */ - InitTraversalModule(); exit((*mainFunction)(argc, argv, environ)); } diff --git a/src/hpc/traverse.c b/src/hpc/traverse.c index ad3db9354b..332d63d14a 100644 --- a/src/hpc/traverse.c +++ b/src/hpc/traverse.c @@ -6,20 +6,12 @@ #include #include #include -#include +#include #include -#include #include #include -#ifdef BOEHM_GC -# ifdef HPCGAP -# define GC_THREADS -# endif -# include -#endif - #ifndef WARD_ENABLED typedef struct TraversalState { @@ -52,52 +44,13 @@ static Obj NewList(UInt size) } -void QueueForTraversal(Obj obj); - -typedef enum { - TRAVERSE_BY_FUNCTION, - TRAVERSE_NONE, - TRAVERSE_ALL, - TRAVERSE_ALL_BUT_FIRST, -} TraversalMethodEnum; - -typedef void (*TraversalCopyFunction)(Obj copy, Obj original); - TraversalFunction TraversalFunc[LAST_REAL_TNUM + 1]; TraversalCopyFunction TraversalCopyFunc[LAST_REAL_TNUM + 1]; TraversalMethodEnum TraversalMethod[LAST_REAL_TNUM + 1]; -void TraversePList(Obj obj) -{ - UInt len = LEN_PLIST(obj); - const Obj * ptr = CONST_ADDR_OBJ(obj) + 1; - while (len) { - QueueForTraversal(*ptr++); - len--; - } -} - -void TraverseWPObj(Obj obj) -{ - /* This is a hack, we rely on weak pointer objects - * having the same layout as plain lists, so we don't - * have to replicate the macro here. - */ - UInt len = LEN_PLIST(obj); - const Obj * ptr = CONST_ADDR_OBJ(obj) + 1; - while (len) { - volatile Obj tmp = *ptr; - MEMBAR_READ(); - if (tmp && *ptr) - QueueForTraversal(*ptr); - ptr++; - len--; - } -} - static UInt FindTraversedObj(Obj); -static inline Obj ReplaceByCopy(Obj obj) +inline Obj ReplaceByCopy(Obj obj) { TraversalState * traversal = currentTraversal(); UInt found = FindTraversedObj(obj); @@ -114,136 +67,15 @@ static inline Obj ReplaceByCopy(Obj obj) return obj; } -void CopyPList(Obj copy, Obj original) +void SetTraversalMethod(UInt tnum, + TraversalMethodEnum meth, + TraversalFunction tf, + TraversalCopyFunction cf) { - UInt len = LEN_PLIST(original); - const Obj * ptr = CONST_ADDR_OBJ(original) + 1; - Obj * copyptr = ADDR_OBJ(copy) + 1; - while (len) { - *copyptr++ = ReplaceByCopy(*ptr++); - len--; - } -} - -void CopyWPObj(Obj copy, Obj original) -{ - /* This is a hack, we rely on weak pointer objects - * having the same layout as plain lists, so we don't - * have to replicate the macro here. - */ - UInt len = LEN_PLIST(original); - const Obj * ptr = CONST_ADDR_OBJ(original) + 1; - Obj * copyptr = ADDR_OBJ(copy) + 1; - while (len) { - volatile Obj tmp = *ptr; - MEMBAR_READ(); - if (tmp && *ptr) - *copyptr = ReplaceByCopy(tmp); - REGISTER_WP(copyptr, tmp); - ptr++; - copyptr++; - } -} - -void TraversePRecord(Obj obj) -{ - UInt i, len = LEN_PREC(obj); - for (i = 1; i <= len; i++) - QueueForTraversal((Obj)GET_ELM_PREC(obj, i)); -} - -void CopyPRecord(Obj copy, Obj original) -{ - UInt i, len = LEN_PREC(original); - for (i = 1; i <= len; i++) - SET_ELM_PREC(copy, i, ReplaceByCopy(GET_ELM_PREC(original, i))); -} - -void TraverseObjSet(Obj obj) -{ - UInt i, len = *(UInt *)(CONST_ADDR_OBJ(obj) + OBJSET_SIZE); - for (i = 0; i < len; i++) { - Obj item = CONST_ADDR_OBJ(obj)[OBJSET_HDRSIZE + i]; - if (item && item != Undefined) - QueueForTraversal(item); - } -} - -void CopyObjSet(Obj copy, Obj original) -{ - UInt i, len = *(UInt *)(CONST_ADDR_OBJ(original) + OBJSET_SIZE); - for (i = 0; i < len; i++) { - Obj item = CONST_ADDR_OBJ(original)[OBJSET_HDRSIZE + i]; - ADDR_OBJ(copy)[OBJSET_HDRSIZE + i] = ReplaceByCopy(item); - } -} - -void TraverseObjMap(Obj obj) -{ - UInt i, len = *(UInt *)(CONST_ADDR_OBJ(obj) + OBJSET_SIZE); - for (i = 0; i < len; i++) { - Obj key = CONST_ADDR_OBJ(obj)[OBJSET_HDRSIZE + 2 * i]; - Obj val = CONST_ADDR_OBJ(obj)[OBJSET_HDRSIZE + 2 * i + 1]; - if (key && key != Undefined) { - QueueForTraversal(key); - QueueForTraversal(val); - } - } -} - -void CopyObjMap(Obj copy, Obj original) -{ - UInt i, len = *(UInt *)(CONST_ADDR_OBJ(original) + OBJSET_SIZE); - for (i = 0; i < len; i++) { - Obj key = CONST_ADDR_OBJ(original)[OBJSET_HDRSIZE + 2 * i]; - Obj val = CONST_ADDR_OBJ(original)[OBJSET_HDRSIZE + 2 * i + 1]; - ADDR_OBJ(copy)[OBJSET_HDRSIZE + 2 * i] = ReplaceByCopy(key); - ADDR_OBJ(copy)[OBJSET_HDRSIZE + 2 * i + 1] = ReplaceByCopy(val); - } -} - -void InitTraversalModule(void) -{ - int i; - for (i = FIRST_REAL_TNUM; i <= LAST_REAL_TNUM; i++) { - assert(TraversalMethod[i] == 0); - TraversalMethod[i] = TRAVERSE_NONE; - } - TraversalMethod[T_PREC ] = TRAVERSE_BY_FUNCTION; - TraversalMethod[T_PREC +IMMUTABLE] = TRAVERSE_BY_FUNCTION; - TraversalFunc[T_PREC ] = TraversePRecord; - TraversalFunc[T_PREC +IMMUTABLE] = TraversePRecord; - TraversalCopyFunc[T_PREC ] = CopyPRecord; - TraversalCopyFunc[T_PREC +IMMUTABLE] = CopyPRecord; - for (i = FIRST_PLIST_TNUM; i <= LAST_PLIST_TNUM; i++) { - TraversalMethod[i] = TRAVERSE_BY_FUNCTION; - TraversalFunc[i] = TraversePList; - TraversalCopyFunc[i] = CopyPList; - } - TraversalMethod[T_PLIST_CYC] = TRAVERSE_NONE; - TraversalMethod[T_PLIST_CYC_NSORT] = TRAVERSE_NONE; - TraversalMethod[T_PLIST_CYC_SSORT] = TRAVERSE_NONE; - TraversalMethod[T_PLIST_FFE] = TRAVERSE_NONE; - - TraversalMethod[T_POSOBJ] = TRAVERSE_ALL_BUT_FIRST; - - TraversalMethod[T_COMOBJ] = TRAVERSE_BY_FUNCTION; - TraversalFunc[T_COMOBJ] = TraversePRecord; - TraversalCopyFunc[T_COMOBJ] = CopyPRecord; - - // FIXME: no TraversalMethod for T_WPOBJ ?! - TraversalFunc[T_WPOBJ] = TraverseWPObj; - TraversalCopyFunc[T_WPOBJ] = CopyWPObj; - - TraversalMethod[T_DATOBJ] = TRAVERSE_NONE; - - TraversalMethod[T_OBJSET] = TRAVERSE_BY_FUNCTION; - TraversalFunc[T_OBJSET] = TraverseObjSet; - TraversalCopyFunc[T_OBJSET] = CopyObjSet; - - TraversalMethod[T_OBJMAP] = TRAVERSE_BY_FUNCTION; - TraversalFunc[T_OBJMAP] = TraverseObjMap; - TraversalCopyFunc[T_OBJMAP] = CopyObjMap; + GAP_ASSERT(tnum < ARRAY_SIZE(TraversalMethod)); + TraversalMethod[tnum] = meth; + TraversalFunc[tnum] = tf; + TraversalCopyFunc[tnum] = cf; } static void BeginTraversal(TraversalState * traversal) @@ -576,4 +408,38 @@ Obj CopyTraversed(Obj traversedList) return copies[1]; } + +/**************************************************************************** +** +*F InitKernel( ) . . . . . . . . initialise kernel data structures +*/ +static Int InitKernel ( StructInitInfo * module ) +{ + int i; + for (i = FIRST_REAL_TNUM; i <= LAST_REAL_TNUM; i++) { + assert(TraversalMethod[i] == 0); + TraversalMethod[i] = TRAVERSE_NONE; + } + + return 0; +} + + +/**************************************************************************** +** +*F InitInfoGVars() . . . . . . . . . . . . . . . . . table of init functions +*/ +static StructInitInfo module = { + // init struct using C99 designated initializers; for a full list of + // fields, please refer to the definition of StructInitInfo + .type = MODULE_BUILTIN, + .name = "traverse", + .initKernel = InitKernel, +}; + +StructInitInfo * InitInfoTraverse ( void ) +{ + return &module; +} + #endif diff --git a/src/hpc/traverse.h b/src/hpc/traverse.h index 0447ad9aab..9cccdd516d 100644 --- a/src/hpc/traverse.h +++ b/src/hpc/traverse.h @@ -8,12 +8,47 @@ */ typedef void (*TraversalFunction)(Obj); +typedef void (*TraversalCopyFunction)(Obj copy, Obj original); + +typedef enum { + TRAVERSE_NONE, + TRAVERSE_BY_FUNCTION, + TRAVERSE_ALL, + TRAVERSE_ALL_BUT_FIRST, +} TraversalMethodEnum; + +// set the traversal method (and optionally, helper functions) +// for all objects with the specified tnum. +extern void SetTraversalMethod(UInt tnum, + TraversalMethodEnum meth, + TraversalFunction tf, + TraversalCopyFunction cf); + + +// helper to be called from traverse functions +extern void QueueForTraversal(Obj obj); + +// helper to be called from copy functions +extern Obj ReplaceByCopy(Obj obj); -extern TraversalFunction TraversalFunc[]; Obj ReachableObjectsFrom(Obj obj); Obj CopyReachableObjectsFrom(Obj obj, int delimited, int asList, int imm); Obj CopyTraversed(Obj traversed); int PreMakeImmutableCheck(Obj obj); + +/**************************************************************************** +** +*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * * +*/ + + +/**************************************************************************** +** +*F InitInfoTraverse() . . . . . . . . . . . . . . . table of init functions +*/ +StructInitInfo * InitInfoTraverse( void ); + + #endif // GAP_TRAVERSE_H diff --git a/src/modules-builtin.c b/src/modules-builtin.c index 909167f76b..f3d489cc7e 100644 --- a/src/modules-builtin.c +++ b/src/modules-builtin.c @@ -14,6 +14,7 @@ #include #include #include +#include #endif extern StructInitInfo * InitInfoGap ( void ); @@ -24,6 +25,12 @@ extern StructInitInfo * InitInfoGap ( void ); */ const InitInfoFunc InitFuncsBuiltinModules[] = { +#ifdef HPCGAP + // Traversal functionality may be needed during the initialization + // of some modules, so set it up as early as possible + InitInfoTraverse, +#endif + /* global variables */ InitInfoGVars, diff --git a/src/objects.c b/src/objects.c index 8fcf5427a2..7606be3176 100644 --- a/src/objects.c +++ b/src/objects.c @@ -29,6 +29,7 @@ #include #include #include +#include #endif #if defined(USE_THREADSAFE_COPYING) @@ -2077,8 +2078,12 @@ static Int InitKernel ( for ( t = FIRST_EXTERNAL_TNUM; t <= LAST_EXTERNAL_TNUM; t++ ) ShallowCopyObjFuncs[ t ] = ShallowCopyObjObject; +#ifdef USE_THREADSAFE_COPYING + SetTraversalMethod(T_POSOBJ, TRAVERSE_ALL_BUT_FIRST, 0, 0); + SetTraversalMethod(T_COMOBJ, TRAVERSE_BY_FUNCTION, TraversePRecord, CopyPRecord); + SetTraversalMethod(T_DATOBJ, TRAVERSE_NONE, 0, 0); +#else /* make and install the 'COPY_OBJ' function */ -#if !defined(USE_THREADSAFE_COPYING) for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) { assert(CopyObjFuncs [ t ] == 0); CopyObjFuncs [ t ] = CopyObjError; diff --git a/src/objset.c b/src/objset.c index 5281ebfbe9..e9fa3add8a 100644 --- a/src/objset.c +++ b/src/objset.c @@ -21,6 +21,9 @@ #include #include +#ifdef HPCGAP +#include +#endif Obj TYPE_OBJSET; Obj TYPE_OBJMAP; @@ -380,6 +383,28 @@ void LoadObjSet(Obj set) } } +#ifdef USE_THREADSAFE_COPYING +void TraverseObjSet(Obj obj) +{ + UInt i, len = *(UInt *)(CONST_ADDR_OBJ(obj) + OBJSET_SIZE); + for (i = 0; i < len; i++) { + Obj item = CONST_ADDR_OBJ(obj)[OBJSET_HDRSIZE + i]; + if (item && item != Undefined) + QueueForTraversal(item); + } +} + +void CopyObjSet(Obj copy, Obj original) +{ + UInt i, len = *(UInt *)(CONST_ADDR_OBJ(original) + OBJSET_SIZE); + for (i = 0; i < len; i++) { + Obj item = CONST_ADDR_OBJ(original)[OBJSET_HDRSIZE + i]; + ADDR_OBJ(copy)[OBJSET_HDRSIZE + i] = ReplaceByCopy(item); + } +} +#endif + + /** * `NewObjMap()` * ------------- @@ -665,6 +690,32 @@ void LoadObjMap(Obj map) } } +#ifdef USE_THREADSAFE_COPYING +void TraverseObjMap(Obj obj) +{ + UInt i, len = *(UInt *)(CONST_ADDR_OBJ(obj) + OBJSET_SIZE); + for (i = 0; i < len; i++) { + Obj key = CONST_ADDR_OBJ(obj)[OBJSET_HDRSIZE + 2 * i]; + Obj val = CONST_ADDR_OBJ(obj)[OBJSET_HDRSIZE + 2 * i + 1]; + if (key && key != Undefined) { + QueueForTraversal(key); + QueueForTraversal(val); + } + } +} + +void CopyObjMap(Obj copy, Obj original) +{ + UInt i, len = *(UInt *)(CONST_ADDR_OBJ(original) + OBJSET_SIZE); + for (i = 0; i < len; i++) { + Obj key = CONST_ADDR_OBJ(original)[OBJSET_HDRSIZE + 2 * i]; + Obj val = CONST_ADDR_OBJ(original)[OBJSET_HDRSIZE + 2 * i + 1]; + ADDR_OBJ(copy)[OBJSET_HDRSIZE + 2 * i] = ReplaceByCopy(key); + ADDR_OBJ(copy)[OBJSET_HDRSIZE + 2 * i + 1] = ReplaceByCopy(val); + } +} +#endif + /** * `FuncOBJ_SET()` * --------------- @@ -991,6 +1042,11 @@ static Int InitKernel ( IsMutableObjFuncs [ T_OBJMAP ] = AlwaysYes; IsMutableObjFuncs [ T_OBJMAP+IMMUTABLE ] = AlwaysNo; +#ifdef USE_THREADSAFE_COPYING + SetTraversalMethod(T_OBJSET, TRAVERSE_BY_FUNCTION, TraverseObjSet, CopyObjSet); + SetTraversalMethod(T_OBJMAP, TRAVERSE_BY_FUNCTION, TraverseObjMap, CopyObjMap); +#endif + // Install saving functions SaveObjFuncs[ T_OBJSET ] = SaveObjSet; SaveObjFuncs[ T_OBJSET +IMMUTABLE ] = SaveObjSet; diff --git a/src/plist.c b/src/plist.c index 565c8f4a93..c7b135e508 100644 --- a/src/plist.c +++ b/src/plist.c @@ -52,6 +52,7 @@ #ifdef HPCGAP #include +#include #endif @@ -932,7 +933,30 @@ Obj FuncIS_PLIST_REP ( } -#if !defined(USE_THREADSAFE_COPYING) +#ifdef USE_THREADSAFE_COPYING + +void TraversePList(Obj obj) +{ + UInt len = LEN_PLIST(obj); + const Obj * ptr = CONST_ADDR_OBJ(obj) + 1; + while (len) { + QueueForTraversal(*ptr++); + len--; + } +} + +void CopyPList(Obj copy, Obj original) +{ + UInt len = LEN_PLIST(original); + const Obj * ptr = CONST_ADDR_OBJ(original) + 1; + Obj * copyptr = ADDR_OBJ(copy) + 1; + while (len) { + *copyptr++ = ReplaceByCopy(*ptr++); + len--; + } +} + +#else /**************************************************************************** ** @@ -3822,7 +3846,14 @@ static Int InitKernel ( ShallowCopyObjFuncs[ t1 +IMMUTABLE ] = ShallowCopyPlist; } -#if !defined(USE_THREADSAFE_COPYING) +#ifdef USE_THREADSAFE_COPYING + for (t1 = FIRST_PLIST_TNUM; t1 <= LAST_PLIST_TNUM; t1++) { + SetTraversalMethod(t1, TRAVERSE_BY_FUNCTION, TraversePList, CopyPList); + } + for (t1 = T_PLIST_CYC; t1 <= T_PLIST_FFE+IMMUTABLE; t1++) { + SetTraversalMethod(t1, TRAVERSE_NONE, 0, 0); + } +#else /* install the copy list methods */ for ( t1 = T_PLIST; t1 <= LAST_PLIST_TNUM; t1 += 2 ) { CopyObjFuncs [ t1 ] = CopyPlist; diff --git a/src/precord.c b/src/precord.c index 8bd3968276..b45fb6b04c 100644 --- a/src/precord.c +++ b/src/precord.c @@ -42,6 +42,7 @@ #ifdef HPCGAP #include +#include #endif /**************************************************************************** @@ -131,7 +132,22 @@ Int GrowPRec ( } -#if !defined(USE_THREADSAFE_COPYING) +#ifdef USE_THREADSAFE_COPYING +void TraversePRecord(Obj obj) +{ + UInt i, len = LEN_PREC(obj); + for (i = 1; i <= len; i++) + QueueForTraversal((Obj)GET_ELM_PREC(obj, i)); +} + +void CopyPRecord(Obj copy, Obj original) +{ + UInt i, len = LEN_PREC(original); + for (i = 1; i <= len; i++) + SET_ELM_PREC(copy, i, ReplaceByCopy(GET_ELM_PREC(original, i))); +} + +#else /**************************************************************************** ** @@ -904,7 +920,10 @@ static Int InitKernel ( IsCopyableObjFuncs[ T_PREC ] = AlwaysYes; IsCopyableObjFuncs[ T_PREC +IMMUTABLE ] = AlwaysYes; -#if !defined(USE_THREADSAFE_COPYING) +#ifdef USE_THREADSAFE_COPYING + SetTraversalMethod(T_PREC, TRAVERSE_BY_FUNCTION, TraversePRecord, CopyPRecord); + SetTraversalMethod(T_PREC +IMMUTABLE, TRAVERSE_BY_FUNCTION, TraversePRecord, CopyPRecord); +#else /* install into copy function tables */ CopyObjFuncs [ T_PREC ] = CopyPRec; CopyObjFuncs [ T_PREC +IMMUTABLE ] = CopyPRec; @@ -914,7 +933,7 @@ static Int InitKernel ( CleanObjFuncs[ T_PREC +IMMUTABLE ] = CleanPRec; CleanObjFuncs[ T_PREC +COPYING ] = CleanPRecCopy; CleanObjFuncs[ T_PREC +IMMUTABLE +COPYING ] = CleanPRecCopy; -#endif // !defined(USE_THREADSAFE_COPYING) +#endif /* install printer */ PrintObjFuncs[ T_PREC ] = PrintPRec; diff --git a/src/precord.h b/src/precord.h index cc1c0632ce..a8c3ddf9b7 100644 --- a/src/precord.h +++ b/src/precord.h @@ -253,6 +253,12 @@ extern void SortPRecRNam ( int inplace ); +#ifdef USE_THREADSAFE_COPYING +extern void TraversePRecord(Obj obj); +extern void CopyPRecord(Obj copy, Obj original); +#endif + + /**************************************************************************** ** *F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * * diff --git a/src/weakptr.c b/src/weakptr.c index 8edee112df..ba8afbddaa 100644 --- a/src/weakptr.c +++ b/src/weakptr.c @@ -26,6 +26,7 @@ #ifdef HPCGAP #include +#include #endif #ifdef BOEHM_GC @@ -557,7 +558,40 @@ static void SweepWeakPointerObj( Bag *src, Bag *dst, UInt len) #endif -#if !defined(USE_THREADSAFE_COPYING) +#ifdef USE_THREADSAFE_COPYING +void TraverseWPObj(Obj obj) +{ + UInt len = STORED_LEN_WPOBJ(obj); + const Obj * ptr = CONST_ADDR_OBJ(obj) + 1; + while (len) { + volatile Obj tmp = *ptr; + MEMBAR_READ(); + if (IS_BAG_REF(tmp) && IS_BAG_REF(*ptr)) + QueueForTraversal(*ptr); + ptr++; + len--; + } +} + +void CopyWPObj(Obj copy, Obj original) +{ + UInt len = STORED_LEN_WPOBJ(original); + const Obj * ptr = CONST_ADDR_OBJ(original) + 1; + Obj * copyptr = ADDR_OBJ(copy) + 1; + while (len--) { + volatile Obj tmp = *ptr; + MEMBAR_READ(); + if (IS_BAG_REF(tmp) && IS_BAG_REF(*ptr)) { + *copyptr = ReplaceByCopy(tmp); + REGISTER_WP(copyptr, tmp); + } + ptr++; + copyptr++; + } +} + + +#else /**************************************************************************** ** @@ -859,7 +893,9 @@ static Int InitKernel ( // List functions ElmDefListFuncs[T_WPOBJ] = ElmDefWPList; -#if !defined(USE_THREADSAFE_COPYING) +#ifdef USE_THREADSAFE_COPYING + SetTraversalMethod(T_WPOBJ, TRAVERSE_BY_FUNCTION, TraverseWPObj, CopyWPObj); +#else /* copying functions */ CopyObjFuncs[ T_WPOBJ ] = CopyObjWPObj; CopyObjFuncs[ T_WPOBJ + COPYING ] = CopyObjWPObjCopy; diff --git a/tst/teststandard/weakptr.tst b/tst/testinstall/weakptr.tst similarity index 97% rename from tst/teststandard/weakptr.tst rename to tst/testinstall/weakptr.tst index dcbded60ca..e277d49f58 100644 --- a/tst/teststandard/weakptr.tst +++ b/tst/testinstall/weakptr.tst @@ -5,7 +5,6 @@ ## #Y Copyright (C) 1997, ## -## Exclude from testinstall.g: too sensitive to compiler idiosyncracies SL ## gap> START_TEST("weakptr.tst");