From 0913c7cb95c46386b1259375747aaaa2a9f8edb1 Mon Sep 17 00:00:00 2001 From: rfm Date: Tue, 13 Jan 2009 15:57:38 +0000 Subject: [PATCH] More garbage collection updates/fixes. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27590 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 9 ++ Headers/Additions/GNUstepBase/config.h.in | 162 +--------------------- Source/GSArray.m | 48 ++++++- Source/GSPrivate.h | 5 - Source/NSArray.m | 2 - Source/NSGarbageCollector.m | 2 + Source/NSNotificationCenter.m | 77 +++++++--- Source/NSThread.m | 10 ++ configure | 119 ++++++++++++++-- configure.ac | 16 ++- 10 files changed, 249 insertions(+), 201 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e6713ce2..175c5fbd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-01-13 Richard Frith-Macdonald + + * Source/NSGarbageCollector.m: Mark the two unimplemented methods. + * Source/NSNotificationCenter.m: Automatically remove observers if + they are collected by the GC system. + * Source/NSThread.m: Make the GC system aware of each thread if poss. + * Source/GSArray.m: Don't use inline array class with GC. + * configure.ac: Add check for GC_register_my_thread + 2009-01-12 Richard Frith-Macdonald * Source/GNUmakefile: diff --git a/Headers/Additions/GNUstepBase/config.h.in b/Headers/Additions/GNUstepBase/config.h.in index 4926e627e..b27c4a744 100644 --- a/Headers/Additions/GNUstepBase/config.h.in +++ b/Headers/Additions/GNUstepBase/config.h.in @@ -12,159 +12,6 @@ /* Define if constructors are automatically loaded */ #undef CON_AUTOLOAD -/* Built in default value for GNUstep config file */ -#undef GNUSTEP_TARGET_CONFIG_FILE - -/* Built in default value for GNUstep local apps */ -#undef GNUSTEP_TARGET_LOCAL_ADMIN_APPS - -/* Built in default value for GNUstep local tools */ -#undef GNUSTEP_TARGET_LOCAL_ADMIN_TOOLS - -/* Built in default value for GNUstep local apps */ -#undef GNUSTEP_TARGET_LOCAL_APPS - -/* Built in default value for GNUstep local documentation */ -#undef GNUSTEP_TARGET_LOCAL_DOC - -/* Built in default value for GNUstep local info documentation */ -#undef GNUSTEP_TARGET_LOCAL_DOC_INFO - -/* Built in default value for GNUstep local manpages documentation */ -#undef GNUSTEP_TARGET_LOCAL_DOC_MAN - -/* Built in default value for GNUstep local headers */ -#undef GNUSTEP_TARGET_LOCAL_HEADERS - -/* Built in default value for GNUstep local libraries */ -#undef GNUSTEP_TARGET_LOCAL_LIBRARIES - -/* Built in default value for GNUstep local library */ -#undef GNUSTEP_TARGET_LOCAL_LIBRARY - -/* Built in default value for GNUstep local tools */ -#undef GNUSTEP_TARGET_LOCAL_TOOLS - -/* Built in default value for GNUstep Local Users directory */ -#undef GNUSTEP_TARGET_LOCAL_USERS_DIR - -/* Built in default value for GNUstep local web apps */ -#undef GNUSTEP_TARGET_LOCAL_WEB_APPS - -/* Built in default value for GNUstep Makefiles */ -#undef GNUSTEP_TARGET_MAKEFILES - -/* Built in default value for GNUstep network apps */ -#undef GNUSTEP_TARGET_NETWORK_ADMIN_APPS - -/* Built in default value for GNUstep system tools */ -#undef GNUSTEP_TARGET_NETWORK_ADMIN_TOOLS - -/* Built in default value for GNUstep network apps */ -#undef GNUSTEP_TARGET_NETWORK_APPS - -/* Built in default value for GNUstep network documentation */ -#undef GNUSTEP_TARGET_NETWORK_DOC - -/* Built in default value for GNUstep network info documentation */ -#undef GNUSTEP_TARGET_NETWORK_DOC_INFO - -/* Built in default value for GNUstep network manpages documentation */ -#undef GNUSTEP_TARGET_NETWORK_DOC_MAN - -/* Built in default value for GNUstep network headers */ -#undef GNUSTEP_TARGET_NETWORK_HEADERS - -/* Built in default value for GNUstep network libraries */ -#undef GNUSTEP_TARGET_NETWORK_LIBRARIES - -/* Built in default value for GNUstep network library */ -#undef GNUSTEP_TARGET_NETWORK_LIBRARY - -/* Built in default value for GNUstep network tools */ -#undef GNUSTEP_TARGET_NETWORK_TOOLS - -/* Built in default value for GNUstep Network Users directory */ -#undef GNUSTEP_TARGET_NETWORK_USERS_DIR - -/* Built in default value for GNUstep network web apps */ -#undef GNUSTEP_TARGET_NETWORK_WEB_APPS - -/* Built in default value for GNUstep system apps */ -#undef GNUSTEP_TARGET_SYSTEM_ADMIN_APPS - -/* Built in default value for GNUstep system tools */ -#undef GNUSTEP_TARGET_SYSTEM_ADMIN_TOOLS - -/* Built in default value for GNUstep system apps */ -#undef GNUSTEP_TARGET_SYSTEM_APPS - -/* Built in default value for GNUstep system documentation */ -#undef GNUSTEP_TARGET_SYSTEM_DOC - -/* Built in default value for GNUstep system info documentation */ -#undef GNUSTEP_TARGET_SYSTEM_DOC_INFO - -/* Built in default value for GNUstep system manpages documentation */ -#undef GNUSTEP_TARGET_SYSTEM_DOC_MAN - -/* Built in default value for GNUstep system headers */ -#undef GNUSTEP_TARGET_SYSTEM_HEADERS - -/* Built in default value for GNUstep system libraries */ -#undef GNUSTEP_TARGET_SYSTEM_LIBRARIES - -/* Built in default value for GNUstep system library */ -#undef GNUSTEP_TARGET_SYSTEM_LIBRARY - -/* Built in default value for GNUstep system tools */ -#undef GNUSTEP_TARGET_SYSTEM_TOOLS - -/* Built in default value for GNUstep System Users directory */ -#undef GNUSTEP_TARGET_SYSTEM_USERS_DIR - -/* Built in default value for GNUstep web apps */ -#undef GNUSTEP_TARGET_SYSTEM_WEB_APPS - -/* Built in default value for GNUstep user config file */ -#undef GNUSTEP_TARGET_USER_CONFIG_FILE - -/* Built in default value for GNUstep user defaults directory */ -#undef GNUSTEP_TARGET_USER_DEFAULTS_DIR - -/* Built in default value for GNUstep user_dir admin apps */ -#undef GNUSTEP_TARGET_USER_DIR_ADMIN_APPS - -/* Built in default value for GNUstep user_dir tools */ -#undef GNUSTEP_TARGET_USER_DIR_ADMIN_TOOLS - -/* Built in default value for GNUstep user_dir apps */ -#undef GNUSTEP_TARGET_USER_DIR_APPS - -/* Built in default value for GNUstep user_dir documentation */ -#undef GNUSTEP_TARGET_USER_DIR_DOC - -/* Built in default value for GNUstep user_dir info documentation */ -#undef GNUSTEP_TARGET_USER_DIR_DOC_INFO - -/* Built in default value for GNUstep user_dir manpages documentation */ -#undef GNUSTEP_TARGET_USER_DIR_DOC_MAN - -/* Built in default value for GNUstep user_dir headers */ -#undef GNUSTEP_TARGET_USER_DIR_HEADERS - -/* Built in default value for GNUstep user_dir libraries */ -#undef GNUSTEP_TARGET_USER_DIR_LIBRARIES - -/* Built in default value for GNUstep user_dir library */ -#undef GNUSTEP_TARGET_USER_DIR_LIBRARY - -/* Built in default value for GNUstep user_dir tools */ -#undef GNUSTEP_TARGET_USER_DIR_TOOLS - -/* Built in default value for GNUstep user_dir web apps */ -#undef GNUSTEP_TARGET_USER_DIR_WEB_APPS - /* Define if this constant is defined */ #undef HANDLE_LLONG_MAX @@ -199,6 +46,12 @@ /* Define if libobjc has the __objc_msg_forward2 function */ #undef HAVE_FORWARD2 +/* Define to 1 if you have the header file. */ +#undef HAVE_GC_H + +/* Define if GC_register_my_thread function is available */ +#undef HAVE_GC_REGISTER_MY_THREAD + /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD @@ -600,9 +453,6 @@ /* Define if your system needs to have short/int word aligned */ #undef NEED_WORD_ALIGNMENT -/* Disable GNUSTEP_CONFIG_FILE environment variable */ -#undef OPTION_NO_ENVIRONMENT - /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT diff --git a/Source/GSArray.m b/Source/GSArray.m index f78070dc9..7bc6c965d 100644 --- a/Source/GSArray.m +++ b/Source/GSArray.m @@ -43,7 +43,11 @@ static SEL eqSel; static SEL oaiSel; +#if GS_WITH_GC +static Class GSArrayClass; +#else static Class GSInlineArrayClass; +#endif @class GSArray; @@ -75,7 +79,8 @@ static Class GSInlineArrayClass; [NSNumber numberWithUnsignedInt: _count], @"Count", self, @"Array", nil, nil]; - reason = [NSString stringWithFormat: @"Index %d is out of range %d (in '%@')", + reason = [NSString stringWithFormat: + @"Index %d is out of range %d (in '%@')", index, _count, NSStringFromSelector(sel)]; exception = [NSException exceptionWithName: NSRangeException @@ -91,7 +96,11 @@ static Class GSInlineArrayClass; [self setVersion: 1]; eqSel = @selector(isEqual:); oaiSel = @selector(objectAtIndex:); +#if GS_WITH_GC + GSArrayClass = [GSArray class]; +#else GSInlineArrayClass = [GSInlineArray class]; +#endif } } @@ -349,19 +358,29 @@ static Class GSInlineArrayClass; } @end +#if !GS_WITH_GC +/* This class stores objects inline in data beyond the end of the instance. + * However, when GC is enabled the object data is typed, and all data after + * the end of the class is ignored by the garbage collector (which would + * mean that objects in the array could be collected). + * We therefore do not provide the class ewhan GC is being used. + */ +@interface GSInlineArray : GSArray +{ +} +@end + @implementation GSInlineArray - (void) dealloc { if (_contents_array) { -#if !GS_WITH_GC unsigned i; for (i = 0; i < _count; i++) { [_contents_array[i] release]; } -#endif } NSDeallocateObject(self); GSNOSUPERDEALLOC; @@ -392,6 +411,7 @@ static Class GSInlineArrayClass; return self; } @end +#endif @implementation GSMutableArray @@ -437,7 +457,11 @@ static Class GSInlineArrayClass; { NSArray *copy; +#if GS_WITH_GC + copy = (id)NSAllocateObject(GSArrayClass, 0, zone); +#else copy = (id)NSAllocateObject(GSInlineArrayClass, sizeof(id)*_count, zone); +#endif return [copy initWithObjects: _contents_array count: _count]; } @@ -1002,7 +1026,11 @@ static Class GSInlineArrayClass; + (void) initialize { +#if GS_WITH_GC + GSArrayClass = [GSArray class]; +#else GSInlineArrayClass = [GSInlineArray class]; +#endif } - (id) autorelease @@ -1039,13 +1067,21 @@ static Class GSInlineArrayClass; } else { - GSInlineArray *a; unsigned c; +#if GS_WITH_GC + GSArray *a; + + [aCoder decodeValueOfObjCType: @encode(unsigned) at: &c]; + a = (id)NSAllocateObject(GSArrayClass, 0, GSObjCZone(self)); + a->_contents_array = NSZoneMalloc(GSObjCZone(self), sizeof(id)*c); +#else + GSInlineArray *a; [aCoder decodeValueOfObjCType: @encode(unsigned) at: &c]; a = (id)NSAllocateObject(GSInlineArrayClass, sizeof(id)*c, GSObjCZone(self)); a->_contents_array = (id*)&a[1]; +#endif if (c > 0) { [aCoder decodeArrayOfObjCType: @encode(id) @@ -1059,8 +1095,12 @@ static Class GSInlineArrayClass; - (id) initWithObjects: (id*)objects count: (unsigned)count { +#if GS_WITH_GC + self = (id)NSAllocateObject(GSArrayClass, 0, GSObjCZone(self)); +#else self = (id)NSAllocateObject(GSInlineArrayClass, sizeof(id)*count, GSObjCZone(self)); +#endif return [self initWithObjects: objects count: count]; } diff --git a/Source/GSPrivate.h b/Source/GSPrivate.h index 1ab2ead63..a492d82e2 100644 --- a/Source/GSPrivate.h +++ b/Source/GSPrivate.h @@ -73,11 +73,6 @@ } @end -@interface GSInlineArray : GSArray -{ -} -@end - @interface GSPlaceholderArray : NSArray { } diff --git a/Source/NSArray.m b/Source/NSArray.m index 502d52648..b3390123e 100644 --- a/Source/NSArray.m +++ b/Source/NSArray.m @@ -84,7 +84,6 @@ extern void GSPropertyListMake(id,NSDictionary*,BOOL,BOOL,unsigned,id*); static Class NSArrayClass; static Class GSArrayClass; -static Class GSInlineArrayClass; static Class NSMutableArrayClass; static Class GSMutableArrayClass; static Class GSPlaceholderArrayClass; @@ -125,7 +124,6 @@ static SEL rlSel; NSArrayClass = [NSArray class]; NSMutableArrayClass = [NSMutableArray class]; GSArrayClass = [GSArray class]; - GSInlineArrayClass = [GSInlineArray class]; GSMutableArrayClass = [GSMutableArray class]; GSPlaceholderArrayClass = [GSPlaceholderArray class]; diff --git a/Source/NSGarbageCollector.m b/Source/NSGarbageCollector.m index db3573aac..bffc15438 100644 --- a/Source/NSGarbageCollector.m +++ b/Source/NSGarbageCollector.m @@ -82,6 +82,7 @@ static unsigned disabled = 0; - (void) disableCollectorForPointer: (void *)ptr { // FIXME + [self notImplemented: _cmd]; return; } @@ -102,6 +103,7 @@ static unsigned disabled = 0; - (void) enableCollectorForPointer: (void *)ptr { // FIXME + [self notImplemented: _cmd]; return; } diff --git a/Source/NSNotificationCenter.m b/Source/NSNotificationCenter.m index 098816310..6ae28e02d 100644 --- a/Source/NSNotificationCenter.m +++ b/Source/NSNotificationCenter.m @@ -30,13 +30,22 @@ */ #include "config.h" -#include "Foundation/NSNotification.h" -#include "Foundation/NSException.h" -#include "Foundation/NSLock.h" -#include "Foundation/NSThread.h" -#include "Foundation/NSDebug.h" -#include "GNUstepBase/GSLock.h" +#import "Foundation/NSNotification.h" +#import "Foundation/NSException.h" +#import "Foundation/NSLock.h" +#import "Foundation/NSThread.h" +#import "Foundation/NSDebug.h" +#import "GNUstepBase/GSLock.h" +/* purgeCollected() returns a list of observations with any observations for + * a collected observer removed. + */ +#if GS_WITH_GC +#include +#define purgeCollected(X) (X = listPurge(X, nil)) +#else +#define purgeCollected(X) (X) +#endif /** * Concrete class implementing NSNotification. @@ -425,6 +434,9 @@ static void obsFree(Observation *o) { NCTable *t = o->link; +#if GS_WITH_GC + GC_unregister_disappearing_link((GC_PTR*)&o->observer); +#endif o->link = (NCTable*)t->freeList; t->freeList = o; } @@ -533,7 +545,7 @@ purgeMapNode(GSIMapTable map, GSIMapNode node, id observer) * I know of. * * We also use this trick to differentiate between map table keys that - * should be treated as objects (notification names) and thise that + * should be treated as objects (notification names) and those that * should be treated as pointers (notification objects) */ #define CHEATGC(X) (id)(((uintptr_t)X) | 1) @@ -641,7 +653,10 @@ static NSNotificationCenter *default_center = nil; * *

The notification center does not retain observer or object. Therefore, * you should always send removeObserver: or removeObserver:name:object: to - * the notification center before releasing these objects.

+ * the notification center before releasing these objects.
+ * As a convenience, when built with garbage collection, you do not need to + * remove any garbage collected observer as the system will do it implicitly. + *

* *

NB. For MacOS-X compatibility, adding an observer multiple times will * register it to receive multiple copies of any matching notification, however @@ -687,8 +702,23 @@ static NSNotificationCenter *default_center = nil; o->retained = 0; o->next = 0; +#if GS_WITH_GC + /* Ensure that if the observer is garbage collected, we clear the + * oservation so that we don't end up sending notifications to the + * deallocated object. + * The observer must be a real GC-allocated object or this mechanism + * can't be used. + */ + if (GC_base(observer) != 0) + { + GC_general_register_disappearing_link((GC_PTR*)&o->observer, observer); + } +#endif + if (object != nil) - object = CHEATGC(object); + { + object = CHEATGC(object); + } /* * Record the Observation in one of the linked lists. @@ -943,6 +973,7 @@ static NSNotificationCenter *default_center = nil; */ - (void) _postAndRelease: (NSNotification*)notification { + IF_NO_GC(GSGarbageCollector *collector = [NSGarbageCollector defaultCollector]) Observation *o; unsigned count; NSString *name = [notification name]; @@ -952,6 +983,9 @@ static NSNotificationCenter *default_center = nil; GSIArrayItem i[64]; GSIArray_t b; GSIArray a = &b; +#if GS_WITH_GG + GSGarbageCollector *collector = [NSGarbageCollector defaultCollector]; +#endif if (name == nil) { @@ -971,14 +1005,21 @@ static NSNotificationCenter *default_center = nil; GSIArrayInitWithZoneAndStaticCapacity(a, NSDefaultMallocZone(), 64, i); /* - * Lock the table of observers while we traverse it. + * Lock the table of observations while we traverse it. + * + * The table of observations contains weak pointers which are zeroed when + * the observers get garbage collected. So to avoid consistency problems + * we disable gc while we copy all the observations we are interested in. */ lockNCTable(TABLE); +#if GS_WITH_GG + [collector disable]; +#endif /* * Find all the observers that specified neither NAME nor OBJECT. */ - for (o = WILDCARD; o != ENDOBS; o = o->next) + for (o = purgeCollected(WILDCARD); o != ENDOBS; o = o->next) { GSIArrayAddItem(a, (GSIArrayItem)o); } @@ -991,7 +1032,7 @@ static NSNotificationCenter *default_center = nil; n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)object); if (n != 0) { - o = n->value.ext; + o = purgeCollected(n->value.ext); while (o != ENDOBS) { GSIArrayAddItem(a, (GSIArrayItem)o); @@ -1023,7 +1064,7 @@ static NSNotificationCenter *default_center = nil; n = GSIMapNodeForSimpleKey(m, (GSIMapKey)object); if (n != 0) { - o = n->value.ext; + o = purgeCollected(n->value.ext); while (o != ENDOBS) { GSIArrayAddItem(a, (GSIArrayItem)o); @@ -1039,7 +1080,7 @@ static NSNotificationCenter *default_center = nil; n = GSIMapNodeForSimpleKey(m, (GSIMapKey)nil); if (n != 0) { - o = n->value.ext; + o = purgeCollected(n->value.ext); while (o != ENDOBS) { GSIArrayAddItem(a, (GSIArrayItem)o); @@ -1047,13 +1088,17 @@ static NSNotificationCenter *default_center = nil; } } } - } } /* - * Finished with the table ... we can unlock it. + * Finished with the table ... we can unlock it and re-enable garbage + * collection, safe in the knowledge that the observers we will be + * notifying won't get collected prematurely. */ +#if GS_WITH_GG + [collector enable]; +#endif unlockNCTable(TABLE); /* diff --git a/Source/NSThread.m b/Source/NSThread.m index 9131a91aa..7f7269dda 100644 --- a/Source/NSThread.m +++ b/Source/NSThread.m @@ -80,6 +80,10 @@ #include "GSPrivate.h" #include "GSRunLoopCtxt.h" +#if GS_WITH_GC +#include +#endif + @interface NSAutoreleasePool (NSThread) + (void) _endThread: (NSThread*)thread; @end @@ -506,6 +510,9 @@ gnustep_base_thread_callback(void) objc_thread_set_data (NULL); +#if GS_WITH_GC && defined(HAVE_GC_REGISTER_MY_THREAD) + GC_unregister_my_thread(); +#endif /* * Tell the runtime to exit the thread */ @@ -734,6 +741,9 @@ gnustep_base_thread_callback(void) NSStringFromSelector(_cmd)]; } +#if GS_WITH_GC && defined(HAVE_GC_REGISTER_MY_THREAD) + GC_register_my_thread(); +#endif #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK) if (_stackSize > 0) { diff --git a/configure b/configure index 08ea94acc..fbdf055b7 100755 --- a/configure +++ b/configure @@ -3468,11 +3468,9 @@ fi done if test "$gc_ok" = no; then - { { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc.h header" >&5 -echo "$as_me: error: Garbage collection was required, but the gc.h header" >&2;} + { { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc.h header couldn't be found." >&5 +echo "$as_me: error: Garbage collection was required, but the gc.h header couldn't be found." >&2;} { (exit 1); exit 1; }; } - { echo "$as_me:$LINENO: couldn't be found." >&5 -echo "$as_me: couldn't be found." >&6;} fi saved_LIBS="$LIBS" LIBS+=" -lgc" @@ -3573,11 +3571,110 @@ else fi if test "$gc_ok" = no; then - { { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc library" >&5 -echo "$as_me: error: Garbage collection was required, but the gc library" >&2;} + { { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc library couldn't be found." >&5 +echo "$as_me: error: Garbage collection was required, but the gc library couldn't be found." >&2;} { (exit 1); exit 1; }; } - { echo "$as_me:$LINENO: couldn't be found." >&5 -echo "$as_me: couldn't be found." >&6;} + fi + echo "$as_me:$LINENO: checking for GC_register_my_thread" >&5 +echo $ECHO_N "checking for GC_register_my_thread... $ECHO_C" >&6 +if test "${ac_cv_func_GC_register_my_thread+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define GC_register_my_thread to an innocuous variant, in case declares GC_register_my_thread. + For example, HP-UX 11i declares gettimeofday. */ +#define GC_register_my_thread innocuous_GC_register_my_thread + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char GC_register_my_thread (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef GC_register_my_thread + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char GC_register_my_thread (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_GC_register_my_thread) || defined (__stub___GC_register_my_thread) +choke me +#else +char (*f) () = GC_register_my_thread; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != GC_register_my_thread; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_GC_register_my_thread=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_GC_register_my_thread=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_GC_register_my_thread" >&5 +echo "${ECHO_T}$ac_cv_func_GC_register_my_thread" >&6 + + if test "$ac_cv_func_GC_register_my_thread" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GC_REGISTER_MY_THREAD 1 +_ACEOF + + else + { echo "$as_me:$LINENO: It looks like your libgc is quite old ... please use a newer one to support making the garbage collector aware of new threads." >&5 +echo "$as_me: It looks like your libgc is quite old ... please use a newer one to support making the garbage collector aware of new threads." >&6;} fi LIBS="-lobjc_gc -ldl" echo "$as_me:$LINENO: checking for class_ivar_set_gcinvisible" >&5 @@ -3677,11 +3774,9 @@ else fi if test "$gc_ok" = no; then - { { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc runtime" >&5 -echo "$as_me: error: Garbage collection was required, but the gc runtime" >&2;} + { { echo "$as_me:$LINENO: error: Garbage collection was required, but the gc runtime couldn't be found." >&5 +echo "$as_me: error: Garbage collection was required, but the gc runtime couldn't be found." >&2;} { (exit 1); exit 1; }; } - { echo "$as_me:$LINENO: couldn't be found." >&5 -echo "$as_me: couldn't be found." >&6;} fi LIBS="$saved_LIBS" diff --git a/configure.ac b/configure.ac index 5d3f7135d..f499a55fb 100644 --- a/configure.ac +++ b/configure.ac @@ -264,21 +264,25 @@ fi if test $OBJC_WITH_GC = yes; then AC_CHECK_HEADERS(gc.h, gc_ok=yes, gc_ok=no) if test "$gc_ok" = no; then - AC_MSG_ERROR([Garbage collection was required, but the gc.h header]) - AC_MSG_NOTICE([couldn't be found.]) + AC_MSG_ERROR([Garbage collection was required, but the gc.h header couldn't be found.]) fi saved_LIBS="$LIBS" LIBS+=" -lgc" AC_CHECK_FUNC(GC_malloc, gc_ok=yes, gc_ok=no) if test "$gc_ok" = no; then - AC_MSG_ERROR([Garbage collection was required, but the gc library]) - AC_MSG_NOTICE([couldn't be found.]) + AC_MSG_ERROR([Garbage collection was required, but the gc library couldn't be found.]) + fi + AC_CHECK_FUNC(GC_register_my_thread) + if test "$ac_cv_func_GC_register_my_thread" = yes; then + AC_DEFINE(HAVE_GC_REGISTER_MY_THREAD,1, + [Define if GC_register_my_thread function is available]) + else + AC_MSG_NOTICE([It looks like your libgc is quite old ... please use a newer one to support making the garbage collector aware of new threads.]) fi LIBS="-lobjc_gc -ldl" AC_CHECK_FUNC(class_ivar_set_gcinvisible, gc_ok=yes, gc_ok=no) if test "$gc_ok" = no; then - AC_MSG_ERROR([Garbage collection was required, but the gc runtime]) - AC_MSG_NOTICE([couldn't be found.]) + AC_MSG_ERROR([Garbage collection was required, but the gc runtime couldn't be found.]) fi LIBS="$saved_LIBS" AC_SUBST(OBJC_WITH_GC)