From 30b5b5728001224f458853a8b30dfca0a424b306 Mon Sep 17 00:00:00 2001 From: ayers Date: Thu, 6 May 2004 15:25:01 +0000 Subject: [PATCH] * Headers/Additions/GNUstepBase/GSObjCRuntime.h/m (GSAllocateMutexAt): New function. (_GSObjCRuntimeInitializer): Define local support class. * Headers/Additions/GNUstepBase/objc-gnu2next.h: Fixed minor whitespace issues. (objc_mutex_t, objc_mutex_allocate, objc_mutex_deallocate) (objc_mutex_lock, objc_mutex_unlock, objc_mutex_trylock): Declare for the NeXT runtime. * Source/Additions/GSNextRuntime.m (objc_mutex_allocate, objc_mutex_deallocate) (objc_mutex_lock, objc_mutex_unlock, objc_mutex_trylock): Implement for NeXT runtime. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@19249 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 16 ++++++ Headers/Additions/GNUstepBase/GSObjCRuntime.h | 25 +++++++++ Headers/Additions/GNUstepBase/objc-gnu2next.h | 14 ++++- Source/Additions/GSNextRuntime.m | 56 +++++++++++++++++++ Source/Additions/GSObjCRuntime.m | 53 ++++++++++++++++++ 5 files changed, 162 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8a49917f1..e8620bc9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2004-05-06 David Ayers + + * Headers/Additions/GNUstepBase/GSObjCRuntime.h/m + (GSAllocateMutexAt): New function. + (_GSObjCRuntimeInitializer): Define local support class. + + * Headers/Additions/GNUstepBase/objc-gnu2next.h: Fixed minor + whitespace issues. + (objc_mutex_t, objc_mutex_allocate, objc_mutex_deallocate) + (objc_mutex_lock, objc_mutex_unlock, objc_mutex_trylock): Declare + for the NeXT runtime. + * Source/Additions/GSNextRuntime.m + (objc_mutex_allocate, objc_mutex_deallocate) + (objc_mutex_lock, objc_mutex_unlock, objc_mutex_trylock): + Implement for NeXT runtime. + 2004-05-06 Mateu Batle * Tools/gdomap.c: mingw fixes. diff --git a/Headers/Additions/GNUstepBase/GSObjCRuntime.h b/Headers/Additions/GNUstepBase/GSObjCRuntime.h index 24736e024..a5092e551 100644 --- a/Headers/Additions/GNUstepBase/GSObjCRuntime.h +++ b/Headers/Additions/GNUstepBase/GSObjCRuntime.h @@ -468,6 +468,31 @@ GSObjCZone(NSObject *obj); GS_EXPORT void * GSAutoreleasedBuffer(unsigned size); +/** + * Allocate a new objc_mutex_t and store it in the location + * pointed to by request. A mutex is only created if the value + * pointed to by request is NULL. This function is thread safe + * in the sense that multiple threads my call this function with the same + * value of request and only one will actually set the mutex. + * It is the users responsibility that no one else attempts to set + * the mutex pointed to. This function should be + * used with objc_mutex_t variables which were statically initialized + * to NULL like: + * + * void function (void) + * { + * static objc_mutex_t my_lock = NULL; + * if (my_lock == NULL) + * GSAllocateMutexAt(&my_lock); + * objc_mutex_lock(my_lock); + * do_work (); + * objc_mutex_unlock(my_lock); + * } + * + */ +GS_EXPORT void +GSAllocateMutexAt(objc_mutex_t *request); + /** Returns a system error message on a variety of systems */ GS_EXPORT const char * diff --git a/Headers/Additions/GNUstepBase/objc-gnu2next.h b/Headers/Additions/GNUstepBase/objc-gnu2next.h index 83bff8b53..41310daa4 100644 --- a/Headers/Additions/GNUstepBase/objc-gnu2next.h +++ b/Headers/Additions/GNUstepBase/objc-gnu2next.h @@ -36,8 +36,8 @@ #include #include -/* Disable builtin functions for gcc < 3.x since it triggers a bad bug (even some 3.x versions may have this - bug) */ +/* Disable builtin functions for gcc < 3.x since it triggers a bad bug + (even some 3.x versions may have this bug). */ #if __GNUC__ < 3 #define __builtin_apply(a,b,c) 0 #define __builtin_apply_args() 0 @@ -192,6 +192,16 @@ extern void *(*_objc_realloc)(void *, size_t); extern void *(*_objc_calloc)(size_t, size_t); extern void (*_objc_free)(void *); + +/* threading functions */ +typedef void *objc_mutex_t; + +objc_mutex_t objc_mutex_allocate (void); +int objc_mutex_deallocate (objc_mutex_t mutex); +int objc_mutex_lock (objc_mutex_t mutex); +int objc_mutex_unlock (objc_mutex_t mutex); +int objc_mutex_trylock (objc_mutex_t mutex); + /* encoding functions */ extern int objc_sizeof_type(const char* type); extern int objc_alignof_type(const char* type); diff --git a/Source/Additions/GSNextRuntime.m b/Source/Additions/GSNextRuntime.m index e3a2278ab..00a34a802 100644 --- a/Source/Additions/GSNextRuntime.m +++ b/Source/Additions/GSNextRuntime.m @@ -593,3 +593,59 @@ objc_set_error_handler(objc_error_handler func) return temp; } +/* + * Functions for threading support. + */ + +/* This currently assumes that the NeXT Runtime is using pthreads + as the underlying thread support. This is true for 'modern' NeXT + Runtime implementations but it may not be for older versions. */ + +#include + +objc_mutex_t +objc_mutex_allocate(void) +{ + pthread_mutex_t *p; + p = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t)); + if (pthread_mutex_init(p, NULL) != 0) + { + abort(); + } + return (objc_mutex_t)p; +} + +int +objc_mutex_deallocate(objc_mutex_t mutex) +{ + int ret; + pthread_mutex_t *p = (pthread_mutex_t *)mutex; + ret = pthread_mutex_destroy(p); + if (ret == 0) + { + free(p); + } + return ret; +} + +int +objc_mutex_lock(objc_mutex_t mutex) +{ + pthread_mutex_t *p = (pthread_mutex_t *)mutex; + return pthread_mutex_lock(p); +} + +int +objc_mutex_unlock (objc_mutex_t mutex) +{ + pthread_mutex_t *p = (pthread_mutex_t *)mutex; + return pthread_mutex_unlock(p); +} + +int +objc_mutex_trylock (objc_mutex_t mutex) +{ + pthread_mutex_t *p = (pthread_mutex_t *)mutex; + return pthread_mutex_trylock(p); +} + diff --git a/Source/Additions/GSObjCRuntime.m b/Source/Additions/GSObjCRuntime.m index f30331509..6cc233ebb 100644 --- a/Source/Additions/GSObjCRuntime.m +++ b/Source/Additions/GSObjCRuntime.m @@ -59,6 +59,59 @@ @end #endif +static objc_mutex_t local_lock = NULL; + +/* This class it intended soley for thread safe / +load safe + initialization of the local lock. + It's a root class so it won't trigger the initialization + of any other class. */ +@interface _GSObjCRuntimeInitializer /* Root Class */ +{ + Class isa; +} ++ (Class)class; +@end +@implementation _GSObjCRuntimeInitializer ++ (void)initialize +{ + if (local_lock == NULL) + { + local_lock = objc_mutex_allocate(); + } +} ++ (Class)class +{ + return self; +} +@end + +void +GSAllocateMutexAt(objc_mutex_t *request) +{ + if (request == NULL) + { + /* This could be called very early in process + initialization so many things may not have + been setup correctly yet. */ + fprintf(stderr, + "Error: GSAllocateMutexAt() called with NULL pointer.\n"); + abort(); + } + + if (local_lock == NULL) + { + /* Initialize in a thread safe way. */ + [_GSObjCRuntimeInitializer class]; + } + + objc_mutex_lock(local_lock); + if (*request == NULL) + { + *request = objc_mutex_allocate(); + } + objc_mutex_unlock(local_lock); +} + /** Deprecated ... use GSObjCFindVariable() */ BOOL GSFindInstanceVariable(id obj, const char *name,