Index: src/OFAutoreleasePool.m ================================================================== --- src/OFAutoreleasePool.m +++ src/OFAutoreleasePool.m @@ -17,17 +17,16 @@ #import "OFArray.h" #import "OFExceptions.h" #ifdef OF_THREADS # import "threading.h" - -#define GROW_SIZE 16 - static of_tlskey_t first_key, last_key; #else static OFAutoreleasePool *first = nil, *last = nil; #endif + +#define GROW_SIZE 16 @implementation OFAutoreleasePool #ifdef OF_THREADS + (void)initialize { Index: src/OFBlock.m ================================================================== --- src/OFBlock.m +++ src/OFBlock.m @@ -12,18 +12,25 @@ #include "config.h" #include #include #include + +#include #if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__) # import #endif #import "OFBlock.h" #import "OFExceptions.h" -#import "atomic.h" +#ifdef OF_ATOMIC_OPS +# import "atomic.h" +#endif +#ifdef OF_THREADS +# import "threading.h" +#endif @protocol RetainRelease - retain; - (void)release; @end @@ -133,10 +140,16 @@ static struct { Class isa; } alloc_failed_exception; +#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) +# define NUM_SPINLOCKS 8 /* needs to be a power of 2 */ +# define SPINLOCK_HASH(p) ((uintptr_t)p >> 4) & (NUM_SPINLOCKS - 1) +static of_spinlock_t spinlocks[NUM_SPINLOCKS]; +#endif + void* _Block_copy(const void *block_) { of_block_literal_t *block = (of_block_literal_t*)block_; @@ -157,12 +170,27 @@ block->descriptor->copy_helper(copy, block); return copy; } - if (block->isa == (Class)&_NSConcreteMallocBlock) + if (block->isa == (Class)&_NSConcreteMallocBlock) { +#if defined(OF_ATOMIC_OPS) of_atomic_inc_int(&block->flags); +#else +# ifdef OF_THREADS + unsigned hash = SPINLOCK_HASH(block); + + assert(of_spinlock_lock(&spinlocks[hash])); +# endif + + block->flags++; + +# ifdef OF_THREADS + assert(of_spinlock_unlock(&spinlocks[hash])); +# endif +#endif + } return block; } void @@ -171,16 +199,39 @@ of_block_literal_t *block = (of_block_literal_t*)block_; if (block->isa != (Class)&_NSConcreteMallocBlock) return; +#ifdef OF_ATOMIC_OPS if ((of_atomic_dec_int(&block->flags) & OF_BLOCK_REFCOUNT_MASK) == 0) { if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE) block->descriptor->dispose_helper(block); free(block); } +#else +# ifdef OF_THREADS + unsigned hash = SPINLOCK_HASH(block); + + assert(of_spinlock_lock(&spinlocks[hash])); +# endif + + if ((--block->flags & OF_BLOCK_REFCOUNT_MASK) == 0) { +# ifdef OF_THREADS + assert(of_spinlock_unlock(&spinlocks[hash])); +# endif + + if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE) + block->descriptor->dispose_helper(block); + + free(block); + } + +# ifdef OF_THREADS + assert(of_spinlock_unlock(&spinlocks[hash])); +# endif +#endif } void _Block_object_assign(void *dst_, const void *src_, const int flags_) { @@ -276,10 +327,22 @@ memcpy(&_NSConcreteMallocBlock, tmp, sizeof(_NSConcreteMallocBlock)); free(tmp); objc_registerClassPair((Class)&_NSConcreteMallocBlock); } #endif + +#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) ++ (void)initialize +{ + size_t i; + + for (i = 0; i < NUM_SPINLOCKS; i++) + if (!of_spinlock_new(&spinlocks[i])) + @throw [OFInitializationFailedException + newWithClass: self]; +} +#endif + alloc { @throw [OFNotImplementedException newWithClass: self selector: _cmd]; Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -26,11 +26,13 @@ #endif #import "OFFile.h" #import "OFString.h" #import "OFArray.h" -#import "OFThread.h" +#ifdef OF_THREADS +# import "OFThread.h" +#endif #import "OFDate.h" #import "OFAutoreleasePool.h" #import "OFExceptions.h" #import "macros.h" @@ -60,11 +62,11 @@ OFFile *of_stdin = nil; OFFile *of_stdout = nil; OFFile *of_stderr = nil; -#ifndef _WIN32 +#if defined(OF_THREADS) && !defined(_WIN32) static OFMutex *mutex; #endif static int parse_mode(const char *mode) { @@ -108,11 +110,11 @@ of_stdin = [[OFFileSingleton alloc] initWithFileDescriptor: 0]; of_stdout = [[OFFileSingleton alloc] initWithFileDescriptor: 1]; of_stderr = [[OFFileSingleton alloc] initWithFileDescriptor: 2]; } -#ifndef _WIN32 +#if defined(OF_THREADS) && !defined(_WIN32) + (void)initialize { if (self == [OFFile class]) mutex = [[OFMutex alloc] init]; } @@ -418,13 +420,15 @@ if (owner == nil && group == nil) @throw [OFInvalidArgumentException newWithClass: self selector: _cmd]; +# ifdef OF_THREADS [mutex lock]; @try { +# endif if (owner != nil) { struct passwd *pw; if ((pw = getpwnam([owner cString])) == NULL) @throw [OFChangeFileOwnerFailedException @@ -446,13 +450,15 @@ owner: owner group: group]; gid = gr->gr_gid; } +# ifdef OF_THREADS } @finally { [mutex unlock]; } +# endif if (chown([path cString], uid, gid)) @throw [OFChangeFileOwnerFailedException newWithClass: self path: path owner: owner Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -36,13 +36,13 @@ # include #endif #import "OFString.h" -#ifdef OF_ATOMIC_OPS +#if defined(OF_ATOMIC_OPS) # import "atomic.h" -#else +#elif defined(OF_THREADS) # import "threading.h" #endif /* A few macros to reduce #ifdefs */ #ifdef OF_OLD_GNU_RUNTIME @@ -53,11 +53,11 @@ struct pre_ivar { void **memchunks; size_t memchunks_size; int32_t retain_count; -#ifndef OF_ATOMIC_OPS +#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) of_spinlock_t retain_spinlock; #endif }; /* Hopefully no arch needs more than 16 bytes padding */ @@ -141,11 +141,11 @@ ((struct pre_ivar*)instance)->memchunks = NULL; ((struct pre_ivar*)instance)->memchunks_size = 0; ((struct pre_ivar*)instance)->retain_count = 1; -#ifndef OF_ATOMIC_OPS +#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) if (!of_spinlock_new(&((struct pre_ivar*)instance)->retain_spinlock)) { free(instance); @throw [OFInitializationFailedException newWithClass: self]; } #endif @@ -656,16 +656,18 @@ pointer: ptr]; } - retain { -#ifdef OF_ATOMIC_OPS +#if defined(OF_ATOMIC_OPS) of_atomic_inc_32(&PRE_IVAR->retain_count); -#else +#elif defined(OF_THREADS) assert(of_spinlock_lock(&PRE_IVAR->retain_spinlock)); PRE_IVAR->retain_count++; assert(of_spinlock_unlock(&PRE_IVAR->retain_spinlock)); +#else + PRE_IVAR->retain_count++; #endif return self; } @@ -675,22 +677,25 @@ return (size_t)PRE_IVAR->retain_count; } - (void)release { -#ifdef OF_ATOMIC_OPS +#if defined(OF_ATOMIC_OPS) if (of_atomic_dec_32(&PRE_IVAR->retain_count) <= 0) [self dealloc]; -#else +#elif defined(OF_THREADS) size_t c; assert(of_spinlock_lock(&PRE_IVAR->retain_spinlock)); c = --PRE_IVAR->retain_count; assert(of_spinlock_unlock(&PRE_IVAR->retain_spinlock)); if (!c) [self dealloc]; +#else + if (--PRE_IVAR->retain_count <= 0) + [self dealloc]; #endif } - autorelease { Index: src/threading.h ================================================================== --- src/threading.h +++ src/threading.h @@ -7,15 +7,17 @@ * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE included in * the packaging of this file. */ -#import "atomic.h" +#import "objfw-defs.h" #if !defined(OF_THREADS) || (!defined(OF_HAVE_PTHREADS) && !defined(_WIN32)) # error No threads available! #endif + +#import "macros.h" #if defined(OF_HAVE_PTHREADS) # include typedef pthread_t of_thread_t; typedef pthread_mutex_t of_mutex_t;