Index: src/atomic.h ================================================================== --- src/atomic.h +++ src/atomic.h @@ -7,19 +7,29 @@ * 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 "objfw-defs.h" +#import "OFMacros.h" #if !defined(OF_THREADS) # define of_atomic_add32(p, i) (*p += i) # define of_atomic_sub32(p, i) (*p -= i) # define of_atomic_or32(p, i) (*p |= i) # define of_atomic_and32(p, i) (*p &= i) # define of_atomic_xor32(p, i) (*p ^= i) -# define of_atomic_cmpswap32(p, o, n) (*p == o ? ((*p = n) ? 1 : 1) : 0) + +static OF_INLINE BOOL +of_atomic_cmpswap32(int32_t *p, int32_t o, int32_t n) +{ + if (*p == o) { + *p = n; + return YES; + } + + return NO; +} #elif defined(OF_HAVE_GCC_ATOMIC_OPS) # define of_atomic_add32(p, i) __sync_add_and_fetch(p, i) # define of_atomic_sub32(p, i) __sync_sub_and_fetch(p, i) # define of_atomic_or32(p, i) __sync_or_and_fetch(p, i) # define of_atomic_and32(p, i) __sync_and_and_fetch(p, i) Index: src/threading.h ================================================================== --- src/threading.h +++ src/threading.h @@ -24,10 +24,19 @@ #include typedef HANDLE of_thread_t; typedef CRITICAL_SECTION of_mutex_t; typedef DWORD of_tlskey_t; #endif + +#if defined(OF_ATOMIC_OPS) +#import "atomic.h" +typedef int32_t of_spinlock_t; +#elif defined(OF_HAVE_PTHREAD_SPINLOCKS) +typedef pthread_spinlock_t of_spinlock_t; +#else +typedef pthread_mutex_t of_spinlock_t; +#endif #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) @@ -184,34 +193,72 @@ #elif defined(_WIN32) return (TlsFree(key) ? YES : NO); #endif } +static OF_INLINE BOOL +of_spinlock_new(of_spinlock_t *s) +{ +#if defined(OF_ATOMIC_OPS) + *s = 0; + return YES; +#elif defined(OF_HAVE_PTHREAD_SPINLOCKS) + return (pthread_spin_init(s, 0) ? NO : YES); +#else + return of_mutex_new(s); +#endif +} + +static OF_INLINE BOOL +of_spinlock_trylock(of_spinlock_t *s) +{ +#if defined(OF_ATOMIC_OPS) + return (of_atomic_cmpswap32(s, 0, 1) ? YES : NO); +#elif defined(OF_HAVE_PTHREAD_SPINLOCKS) + return (pthread_spin_trylock(s) ? NO : YES); +#else + return of_mutex_trylock(s); +#endif +} + +static OF_INLINE BOOL +of_spinlock_lock(of_spinlock_t *s) +{ #if defined(OF_ATOMIC_OPS) -# import "atomic.h" -typedef int32_t of_spinlock_t; -# define of_spinlock_new(s) ((*(s) = 0) + YES) -# define of_spinlock_trylock(s) (of_atomic_cmpswap32(s, 0, 1) ? YES : NO) + while (!of_spinlock_trylock(s)) { # ifdef OF_HAVE_SCHED_YIELD -# define of_spinlock_lock(s) \ - while (!of_spinlock_trylock(s)) \ - sched_yield() -# else -# define of_spinlock_lock(s) while (!of_spinlock_trylock(s)); + sched_yield(); # endif -# define of_spinlock_unlock(s) *(s) = 0 -# define of_spinlock_free(s) YES + } + + return YES; +#elif defined(OF_HAVE_PTHREAD_SPINLOCKS) + return (pthread_spin_lock(s) ? NO : YES); +#else + return of_mutex_lock(s); +#endif +} + +static OF_INLINE BOOL +of_spinlock_unlock(of_spinlock_t *s) +{ +#if defined(OF_ATOMIC_OPS) + *s = 0; + return YES; +#elif defined(OF_HAVE_PTHREAD_SPINLOCKS) + return (pthread_spin_unlock(s) ? NO : YES); +#else + return of_mutex_unlock(s); +#endif +} + +static OF_INLINE BOOL +of_spinlock_free(of_spinlock_t *s) +{ +#if defined(OF_ATOMIC_OPS) + return YES; #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) -typedef pthread_spinlock_t of_spinlock_t; -# define of_spinlock_new(s) (pthread_spin_init(s, 0) ? NO : YES) -# define of_spinlock_trylock(s) (pthread_spin_trylock(s) ? NO : YES) -# define of_spinlock_lock(s) pthread_spin_lock(s) -# define of_spinlock_unlock(s) pthread_spin_unlock(s) -# define of_spinlock_free(s) (pthread_spin_destroy(s) ? NO : YES) + return (pthread_spin_destroy(s) ? NO : YES); #else -typedef of_mutex_t of_spinlock_t; -# define of_spinlock_new(s) of_mutex_new(s) -# define of_spinlock_trylock(s) of_mutex_trylock(s) -# define of_spinlock_lock(s) of_mutex_lock(s) -# define of_spinlock_unlock(s) of_mutex_unlock(s) -# define of_spinlock_free(s) of_mutex_free(s) + return of_mutex_free(s); #endif +}