Index: src/runtime/runtime-private.h ================================================================== --- src/runtime/runtime-private.h +++ src/runtime/runtime-private.h @@ -141,32 +141,25 @@ extern struct objc_hashtable* objc_hashtable_new(uint32_t); extern void objc_hashtable_set(struct objc_hashtable*, const char*, const void*); extern void* objc_hashtable_get(struct objc_hashtable*, const char*); extern void objc_hashtable_free(struct objc_hashtable *h); -extern BOOL objc_hashtable_warn_on_collision; extern void objc_register_selector(struct objc_abi_selector*); extern void objc_register_all_selectors(struct objc_abi_symtab*); extern void objc_free_all_selectors(void); extern struct objc_sparsearray* objc_sparsearray_new(void); extern void objc_sparsearray_copy(struct objc_sparsearray*, struct objc_sparsearray*); extern void objc_sparsearray_set(struct objc_sparsearray*, uint32_t, const void*); extern void objc_sparsearray_free(struct objc_sparsearray*); -extern void objc_sparsearray_free_when_singlethreaded(struct objc_sparsearray*); extern void objc_sparsearray_cleanup(void); extern void objc_init_static_instances(struct objc_abi_symtab*); extern void __objc_exec_class(struct objc_abi_module*); -extern BOOL objc_mutex_new(objc_mutex_t*); -extern BOOL objc_mutex_lock(objc_mutex_t*); -extern BOOL objc_mutex_unlock(objc_mutex_t*); -extern BOOL objc_mutex_free(objc_mutex_t*); extern void objc_global_mutex_lock(void); extern void objc_global_mutex_unlock(void); extern void objc_global_mutex_free(void); -extern void objc_free_when_singlethreaded(void*); static inline void* objc_sparsearray_get(const struct objc_sparsearray *s, uint32_t idx) { #ifndef OF_SELUID16 Index: src/runtime/threading.m ================================================================== --- src/runtime/threading.m +++ src/runtime/threading.m @@ -19,61 +19,19 @@ #include #include #import "runtime.h" #import "runtime-private.h" - -static objc_mutex_t global_mutex; -static BOOL global_mutex_init = NO; - -BOOL -objc_mutex_new(objc_mutex_t *mutex) -{ - if (!of_mutex_new(&mutex->mutex )) - return NO; - - mutex->count = 0; - - return YES; -} - -BOOL -objc_mutex_lock(objc_mutex_t *mutex) -{ - if (mutex->count > 0 && of_thread_is_current(mutex->owner)) { - mutex->count++; - return YES; - } - - if (!of_mutex_lock(&mutex->mutex)) - return NO; - - mutex->owner = of_thread_current(); - mutex->count++; - - return YES; -} - -BOOL -objc_mutex_unlock(objc_mutex_t *mutex) -{ - if (--mutex->count == 0) - return of_mutex_unlock(&mutex->mutex); - - return YES; -} - -BOOL -objc_mutex_free(objc_mutex_t *mutex) -{ - return of_mutex_free(&mutex->mutex); -} +#import "threading.h" + +static of_rmutex_t global_mutex; +static BOOL global_mutex_init = NO; static void objc_global_mutex_new(void) { - if (!objc_mutex_new(&global_mutex)) + if (!of_rmutex_new(&global_mutex)) OBJC_ERROR("Failed to create global mutex!"); global_mutex_init = YES; } @@ -81,22 +39,22 @@ objc_global_mutex_lock(void) { if (!global_mutex_init) objc_global_mutex_new(); - if (!objc_mutex_lock(&global_mutex)) + if (!of_rmutex_lock(&global_mutex)) OBJC_ERROR("Failed to lock global mutex!"); } void objc_global_mutex_unlock(void) { - if (!objc_mutex_unlock(&global_mutex)) + if (!of_rmutex_unlock(&global_mutex)) OBJC_ERROR("Failed to unlock global mutex!"); } void objc_global_mutex_free(void) { - if (!objc_mutex_free(&global_mutex)) + if (!of_rmutex_free(&global_mutex)) OBJC_ERROR("Failed to free global mutex!"); } Index: src/threading.h ================================================================== --- src/threading.h +++ src/threading.h @@ -46,10 +46,15 @@ #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) typedef pthread_spinlock_t of_spinlock_t; #else typedef of_mutex_t of_spinlock_t; #endif + +typedef struct { + of_mutex_t mutex; + of_tlskey_t count; +} of_rmutex_t; #if defined(OF_HAVE_PTHREADS) # define of_thread_is_current(t) pthread_equal(t, pthread_self()) # define of_thread_current pthread_self #elif defined(_WIN32) @@ -361,5 +366,71 @@ return !pthread_spin_destroy(spinlock); #else return of_mutex_free(spinlock); #endif } + +static OF_INLINE BOOL +of_rmutex_new(of_rmutex_t *rmutex) +{ + if (!of_mutex_new(&rmutex->mutex)) + return NO; + + if (!of_tlskey_new(&rmutex->count)) + return NO; + + return YES; +} + +static OF_INLINE BOOL +of_rmutex_lock(of_rmutex_t *rmutex) +{ + uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count); + + if (count > 0) { + if (!of_tlskey_set(rmutex->count, (void*)(count + 1))) + return NO; + return YES; + } + + if (!of_mutex_lock(&rmutex->mutex)) + return NO; + + if (!of_tlskey_set(rmutex->count, (void*)1)) { + of_mutex_unlock(&rmutex->mutex); + return NO; + } + + return YES; +} + +static OF_INLINE BOOL +of_rmutex_unlock(of_rmutex_t *rmutex) +{ + uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count); + + if (count > 1) { + if (!of_tlskey_set(rmutex->count, (void*)(count - 1))) + return NO; + return YES; + } + + if (!of_tlskey_set(rmutex->count, (void*)0)) + return NO; + + if (!of_mutex_unlock(&rmutex->mutex)) + return NO; + + return YES; +} + +static OF_INLINE BOOL +of_rmutex_free(of_rmutex_t *rmutex) +{ + if (!of_mutex_free(&rmutex->mutex)) + return NO; + + if (!of_tlskey_free(rmutex->count)) + return NO; + + return YES; +}