Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -595,15 +595,22 @@ - (void)run { _running = true; - while (_running) { - void *pool = objc_autoreleasePoolPush(); - OFDate *now = [OFDate date]; + for (;;) { + void *pool; + OFDate *now; OFTimer *timer; OFDate *nextTimer; + + of_memory_read_barrier(); + if (!_running) + break; + + pool = objc_autoreleasePoolPush(); + now = [OFDate date]; #ifdef OF_HAVE_THREADS [_timersQueueLock lock]; @try { #endif @@ -661,8 +668,9 @@ } - (void)stop { _running = false; + of_memory_write_barrier(); [_streamObserver cancel]; } @end Index: src/OFThreadPool.m ================================================================== --- src/OFThreadPool.m +++ src/OFThreadPool.m @@ -172,10 +172,11 @@ - (id)main { void *pool; + of_memory_read_barrier(); if (_terminate) return nil; pool = objc_autoreleasePoolPush(); @@ -184,10 +185,11 @@ [_queueCondition lock]; @try { of_list_object_t *listObject; + of_memory_read_barrier(); if (_terminate) { objc_autoreleasePoolPop(pool); return nil; } @@ -194,10 +196,11 @@ listObject = [_queue firstListObject]; while (listObject == NULL) { [_queueCondition wait]; + of_memory_read_barrier(); if (_terminate) { objc_autoreleasePoolPop(pool); return nil; } @@ -208,17 +211,19 @@ [_queue removeListObject: listObject]; } @finally { [_queueCondition unlock]; } + of_memory_read_barrier(); if (_terminate) { objc_autoreleasePoolPop(pool); return nil; } [job perform]; + of_memory_read_barrier(); if (_terminate) { objc_autoreleasePoolPop(pool); return nil; } @@ -225,10 +230,11 @@ objc_autoreleasePoolPop(pool); pool = objc_autoreleasePoolPush(); [_countCondition lock]; @try { + of_memory_read_barrier(); if (_terminate) { objc_autoreleasePoolPop(pool); return nil; } @@ -306,10 +312,12 @@ OFEnumerator *enumerator = [_threads objectEnumerator]; OFThreadPoolThread *thread; while ((thread = [enumerator nextObject]) != nil) thread->_terminate = true; + + of_memory_write_barrier(); } @finally { [_countCondition unlock]; } [_queueCondition broadcast]; Index: src/atomic.h ================================================================== --- src/atomic.h +++ src/atomic.h @@ -755,5 +755,48 @@ return OSAtomicCompareAndSwapPtrBarrier(o, n, p); #else # error No atomic operations available! #endif } + +static OF_INLINE void +of_memory_barrier(void) +{ +#if !defined(OF_HAVE_THREADS) +#elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) + __asm__ __volatile__ ( + "mfence" + ); +#elif defined(OF_HAVE_GCC_ATOMIC_OPS) + __sync_synchronize(); +#elif defined(OF_HAVE_OSATOMIC) + OSMemoryBarrier(); +#else +# error No atomic operations available! +#endif +} + +static OF_INLINE void +of_memory_read_barrier(void) +{ +#if !defined(OF_HAVE_THREADS) +#elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) + __asm__ __volatile__ ( + "lfence" + ); +#else + of_memory_barrier(); +#endif +} + +static OF_INLINE void +of_memory_write_barrier(void) +{ +#if !defined(OF_HAVE_THREADS) +#elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) + __asm__ __volatile__ ( + "sfence" + ); +#else + of_memory_barrier(); +#endif +} Index: src/threading.h ================================================================== --- src/threading.h +++ src/threading.h @@ -351,12 +351,11 @@ static OF_INLINE bool of_spinlock_unlock(of_spinlock_t *spinlock) { #if defined(OF_HAVE_ATOMIC_OPS) - *spinlock = 0; - return true; + return of_atomic_cmpswap_int(spinlock, 1, 0); #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) return !pthread_spin_unlock(spinlock); #else return of_mutex_unlock(spinlock); #endif