Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -157,11 +157,14 @@ AC_SUBST(NO_CONST_CFSTRINGS) AC_CHECK_HEADER(objc/runtime.h, [AC_DEFINE(HAVE_OBJC_RUNTIME_H, 1, [Whether we have objc/runtime.h])]) -AC_CHECK_FUNC(objc_sync_enter,, AC_SUBST(OBJC_SYNC_M, "objc_sync.m")) +AC_CHECK_FUNC(objc_sync_enter,, [ + AC_SUBST(OBJC_SYNC_M, "objc_sync.m") + AC_DEFINE(NEED_OBJC_SYNC_INIT, 1, + [Whether objc_sync_init needs to be called])]) test x"$GCC" = x"yes" && CFLAGS="$CFLAGS -Werror" if test x"$GOBJC" = x"yes"; then old_OBJCFLAGS="$OBJCFLAGS" OBJCFLAGS="$OBJCFLAGS -Werror" Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -9,10 +9,11 @@ * the packaging of this file. */ #include "config.h" +#include #include #include #include #include @@ -37,14 +38,24 @@ #define PRE_IVAR ((struct pre_ivar*)((char*)self - PRE_IVAR_ALIGN)) static struct { Class isa; } alloc_failed_exception; + +#ifdef NEED_OBJC_SYNC_INIT +extern BOOL objc_sync_init(); +#endif @implementation OFObject + (void)initialize { +#ifdef NEED_OBJC_SYNC_INIT + if (!objc_sync_init()) { + fputs("Runtime error: objc_sync_init() failed!\n", stderr); + abort(); + } +#endif } + alloc { OFObject *instance; Index: src/objc_sync.m ================================================================== --- src/objc_sync.m +++ src/objc_sync.m @@ -14,13 +14,19 @@ #include #include #ifndef _WIN32 #include -#else +#endif + +#import + +#ifdef _WIN32 #include #endif + +#import "OFMacros.h" struct locks_s { id obj; size_t count; size_t recursion; @@ -31,139 +37,163 @@ HANDLE thread; HANDLE mutex; #endif }; -static int initialized = 0; #ifndef _WIN32 static pthread_mutex_t mutex; #else static HANDLE mutex; #endif static struct locks_s *locks = NULL; static size_t num_locks = 0; + +#ifndef _WIN32 +static OF_INLINE BOOL +mutex_new(pthread_mutex_t *m) +{ + return (pthread_mutex_init(m, NULL) ? NO : YES); +} + +static OF_INLINE BOOL +mutex_free(pthread_mutex_t *m) +{ + return (pthread_mutex_destroy(m) ? NO : YES); +} + +static OF_INLINE BOOL +mutex_lock(pthread_mutex_t *m) +{ + return (pthread_mutex_lock(m) ? NO : YES); +} + +static OF_INLINE BOOL +mutex_unlock(pthread_mutex_t *m) +{ + return (pthread_mutex_unlock(m) ? NO : YES); +} + +static OF_INLINE BOOL +thread_is_current(pthread_t t) +{ + return (pthread_equal(t, pthread_self()) ? YES : NO); +} + +static OF_INLINE pthread_t +thread_current() +{ + return pthread_self(); +} +#else +static OF_INLINE BOOL +mutex_new(HANDLE *m) +{ + return (((*m = CreateMutex(NULL, FALSE, NULL)) != NULL) ? YES : NO); +} + +static OF_INLINE BOOL +mutex_free(HANDLE *m) +{ + return (CloseHandle(*m) ? YES : NO); +} + +static OF_INLINE BOOL +mutex_lock(HANDLE *m) +{ + return (WaitForSingleObject(*m, INFINITE) == WAIT_OBJECT_0 ? YES : NO); +} + +static OF_INLINE BOOL +mutex_unlock(HANDLE *m) +{ + return (ReleaseMutex(*m) ? YES : NO); +} + +static OF_INLINE BOOL +thread_is_current(HANDLE t) +{ + return (t == GetCurrentThread() ? YES : NO); +} + +static OF_INLINE HANDLE +thread_current() +{ + return GetCurrentThread(); +} +#endif + +BOOL +objc_sync_init() +{ + return (mutex_new(&mutex) ? YES : NO); +} int objc_sync_enter(id obj) { size_t i; - /* - * FIXME: - * Theoretically, it's possible to encounter a race condition during - * initialization. - */ - if (!initialized) { -#ifndef _WIN32 - if (pthread_mutex_init(&mutex, NULL)) -#else - if ((mutex = CreateMutex(NULL, FALSE, NULL)) == NULL) -#endif - return 1; - - initialized = 1; - } - -#ifndef _WIN32 - if (pthread_mutex_lock(&mutex)) -#else - if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) - return 1; -#endif + if (obj == nil) + return 0; + + if (!mutex_lock(&mutex)) + return 1; for (i = 0; i < num_locks; i++) { if (locks[i].obj == obj) { -#ifndef _WIN32 - if (pthread_equal(pthread_self(), locks[i].thread)) -#else - if (locks[i].thread == GetCurrentThread()) -#endif + if (thread_is_current(locks[i].thread)) locks[i].recursion++; else -#ifndef _WIN32 - if (pthread_mutex_lock(&locks[i].mutex)) { - pthread_mutex_unlock(&mutex); + if (!mutex_lock(&locks[i].mutex)) { + mutex_unlock(&mutex); return 1; } -#else - if (WaitForSingleObject(locks[i].mutex, - INFINITE) != WAIT_OBJECT_0) { - ReleaseMutex(mutex); - return 1; - } -#endif locks[i].count++; -#ifndef _WIN32 - if (pthread_mutex_unlock(&locks[i].mutex)) -#else - if (!ReleaseMutex(mutex)) -#endif + if (!mutex_unlock(&mutex)) return 1; return 0; } } if (locks == NULL) { if ((locks = malloc(sizeof(struct locks_s))) == NULL) { -#ifndef _WIN32 - pthread_mutex_unlock(&mutex); -#else - ReleaseMutex(mutex); -#endif + mutex_unlock(&mutex); return 1; } } else { struct locks_s *new_locks; if ((new_locks = realloc(locks, (num_locks + 1) * sizeof(struct locks_s))) == NULL) { -#ifndef _WIN32 - pthread_mutex_unlock(&mutex); -#else - ReleaseMutex(mutex); -#endif + mutex_unlock(&mutex); return 1; } locks = new_locks; } locks[num_locks].obj = obj; locks[num_locks].count = 1; locks[num_locks].recursion = 0; - -#ifndef _WIN32 - locks[num_locks].thread = pthread_self(); - - if (pthread_mutex_init(&locks[num_locks].mutex, NULL)) { - pthread_mutex_unlock(&mutex); - return 1; - } - - if (pthread_mutex_lock(&locks[num_locks].mutex)) { - pthread_mutex_unlock(&mutex); - return 1; - } -#else - locks[num_locks].thread = GetCurrentThread(); - - if ((locks[num_locks].mutex = CreateMutex(NULL, TRUE, NULL)) == NULL) { - ReleaseMutex(mutex); - return 1; - } -#endif - - num_locks++; - -#ifndef _WIN32 - if (pthread_mutex_unlock(&mutex)) -#else - if (!ReleaseMutex(mutex)) -#endif + locks[num_locks].thread = thread_current(); + + if (!mutex_new(&locks[num_locks].mutex)) { + mutex_unlock(&mutex); + return 1; + } + + if (!mutex_lock(&locks[num_locks].mutex)) { + mutex_unlock(&mutex); + return 1; + } + + num_locks++; + + if (!mutex_unlock(&mutex)) return 1; return 0; } @@ -170,100 +200,60 @@ int objc_sync_exit(id obj) { size_t i; -#ifndef _WIN32 - if (pthread_mutex_lock(&mutex)) -#else - if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) - return 1; -#endif - - for (i = 0; i < num_locks; i++) { - if (locks[i].obj == obj) { -#ifndef _WIN32 - if (pthread_equal(pthread_self(), locks[i].thread) && - locks[i].recursion) { - locks[i].recursion--; - - if (pthread_mutex_unlock(&mutex)) - return 1; - - return 0; - } -#else - if (locks[i].thread == GetCurrentThread() && - locks[i].recursion) { - locks[i].recursion--; - - if (!ReleaseMutex(mutex)) - return 1; - - return 0; - } -#endif - -#ifndef _WIN32 - if (pthread_mutex_unlock(&locks[i].mutex)) { - pthread_mutex_unlock(&mutex); - return 1; - } -#else - if (!ReleaseMutex(locks[i].mutex)) { - ReleaseMutex(mutex); - return 1; - } -#endif + if (obj == nil) + return 0; + + if (!mutex_lock(&mutex)) + return 1; + + for (i = 0; i < num_locks; i++) { + if (locks[i].obj == obj) { + if (locks[i].recursion > 0 && + thread_is_current(locks[i].thread)) { + locks[i].recursion--; + + if (!mutex_unlock(&mutex)) + return 1; + + return 0; + } + + if (!mutex_unlock(&locks[i].mutex)) { + mutex_unlock(&mutex); + return 1; + } locks[i].count--; if (locks[i].count == 0) { struct locks_s *new_locks; -#ifndef _WIN32 - if (pthread_mutex_destroy(&locks[i].mutex)) { - pthread_mutex_unlock(&mutex); + if (!mutex_free(&locks[i].mutex)) { + mutex_unlock(&mutex); return 1; } -#else - if (!CloseHandle(locks[i].mutex)) { - ReleaseMutex(mutex); - return 1; - } -#endif num_locks--; locks[i] = locks[num_locks]; if ((new_locks = realloc(locks, (num_locks) * sizeof(struct locks_s))) == NULL) { -#ifndef _WIN32 - pthread_mutex_unlock(&mutex); -#else - ReleaseMutex(mutex); -#endif + mutex_unlock(&mutex); return 1; } locks = new_locks; } -#ifndef _WIN32 - if (pthread_mutex_unlock(&mutex)) -#else - if (!ReleaseMutex(mutex)) -#endif + if (!mutex_unlock(&mutex)) return 1; return 0; } } -#ifndef _WIN32 - pthread_mutex_unlock(&mutex); -#else - ReleaseMutex(mutex); -#endif - + mutex_unlock(&mutex); return 1; }