From 519207c7eb228b6fd3dc4e5626b1c4cd374991d4 Mon Sep 17 00:00:00 2001 From: Jean Guyomarc'h Date: Sat, 1 Oct 2016 15:09:37 +0200 Subject: [PATCH] eina: fix macos spinlocks and upgrade API to sierra --- src/lib/eina/eina_inline_lock_posix.x | 42 +++++++------------------------ src/lib/eina/eina_lock.c | 47 +++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/lib/eina/eina_inline_lock_posix.x b/src/lib/eina/eina_inline_lock_posix.x index 51760ca..6f15631 100644 --- a/src/lib/eina/eina_inline_lock_posix.x +++ b/src/lib/eina/eina_inline_lock_posix.x @@ -38,10 +38,6 @@ # include #endif -#ifdef EINA_HAVE_OSX_SPINLOCK -# include -#endif - #ifdef EINA_HAVE_OSX_SEMAPHORE # include #endif @@ -87,7 +83,7 @@ typedef pthread_key_t Eina_TLS; #if defined(EINA_HAVE_POSIX_SPINLOCK) typedef pthread_spinlock_t Eina_Spinlock; #elif defined(EINA_HAVE_OSX_SPINLOCK) -typedef OSSpinLock Eina_Spinlock; +typedef uintptr_t Eina_Spinlock; #else typedef Eina_Lock Eina_Spinlock; #endif @@ -153,6 +149,11 @@ EAPI Eina_Bool _eina_spinlock_new(Eina_Spinlock *spinlock); EAPI void _eina_spinlock_free(Eina_Spinlock *spinlock); EAPI Eina_Bool _eina_semaphore_new(Eina_Semaphore *sem, int count_init); EAPI Eina_Bool _eina_semaphore_free(Eina_Semaphore *sem); +#ifdef EINA_HAVE_OSX_SPINLOCK +EAPI Eina_Lock_Result _eina_spinlock_macos_take(Eina_Spinlock *spinlock); +EAPI Eina_Lock_Result _eina_spinlock_macos_take_try(Eina_Spinlock *spinlock); +EAPI Eina_Lock_Result _eina_spinlock_macos_release(Eina_Spinlock *spinlock); +#endif static inline Eina_Bool eina_lock_new(Eina_Lock *mutex) @@ -637,11 +638,7 @@ eina_spinlock_take(Eina_Spinlock *spinlock) return EINA_LOCK_SUCCEED; #elif defined(EINA_HAVE_OSX_SPINLOCK) - /* void OSSpinLockLock(OSSpinLock *lock); - * Will spin if the lock is already held, but employs various strategies to - * back off, making it immune to most priority-inversion livelocks. */ - OSSpinLockLock(spinlock); - return EINA_LOCK_SUCCEED; + return _eina_spinlock_macos_take(spinlock); #else return eina_lock_take(spinlock); #endif @@ -657,10 +654,7 @@ eina_spinlock_take_try(Eina_Spinlock *spinlock) else EINA_LOCK_ABORT_DEBUG(t, spin_trylock, spinlock); return EINA_LOCK_FAIL; #elif defined(EINA_HAVE_OSX_SPINLOCK) - /* bool OSSpinLockTry(OSSpinLock *lock); - * Immediately returns false if the lock was held, true if it took the - * lock. It does not spin. */ - return (OSSpinLockTry(spinlock)) ? EINA_LOCK_SUCCEED : EINA_LOCK_FAIL; + return _eina_spinlock_macos_take_try(spinlock); #else return eina_lock_take_try(spinlock); #endif @@ -676,10 +670,7 @@ eina_spinlock_release(Eina_Spinlock *spinlock) else EINA_LOCK_ABORT_DEBUG(ok, spin_unlock, spinlock); return EINA_LOCK_FAIL; #elif defined(EINA_HAVE_OSX_SPINLOCK) - /* void OSSpinLockUnlock(OSSpinLock *lock); - * Unconditionally unlocks the lock by zeroing it. */ - OSSpinLockUnlock(spinlock); - return EINA_LOCK_SUCCEED; + return _eina_spinlock_macos_release(spinlock); #else return eina_lock_release(spinlock); #endif @@ -739,19 +730,4 @@ eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED) # define _XOPEN_SOURCE EINA_XOPEN_SOURCE #endif -#ifdef EINA_HAVE_OSX_SPINLOCK -/* The inclusion of libkern/OSAtomic.h is a mess because it includes stdbool - * which #defines bool. #undef bool is not sufficient because then other - * headers (dlfcn.h) require it and #include stdbool.h to get it. It is - * therefore important to "undo" the whole stdbool.h inclusion. */ -# undef true -# undef false -# undef bool -# undef __bool_true_false_are_defined -# undef _STDBOOL_H_ // OSX SDK -# undef __STDBOOL_H // Clang 5.1 -# undef _STDBOOL_H // GCC -#endif - - #endif diff --git a/src/lib/eina/eina_lock.c b/src/lib/eina/eina_lock.c index a01571c..5cb834e 100644 --- a/src/lib/eina/eina_lock.c +++ b/src/lib/eina/eina_lock.c @@ -7,6 +7,51 @@ #include "eina_config.h" #include "Eina.h" +#ifdef EINA_HAVE_OSX_SPINLOCK + +/* + * macOS 10.12 introduced the os_unfair_lock API which + * deprecates OSSpinLock, while keeping compatible. + * + * The Spinlock API is not inlined because it would imply including + * stdbool.h, which is not wanted: it would introduce new macros, + * and break compilation of existing programs. + */ +# ifdef __MAC_10_12 +# include +# define SPINLOCK_GET(LCK) ((os_unfair_lock_t)(LCK)) +# else +# include +# define SPINLOCK_GET(LCK) ((OSSpinLock *)(LCK)) +# define os_unfair_lock_lock(LCK) OSSpinLockLock(LCK) +# define os_unfair_lock_unlock(LCK) OSSpinLockUnlock(LCK) +# define os_unfair_lock_trylock(LCK) OSSpinLockTry(LCK) +# endif + +EAPI Eina_Lock_Result +_eina_spinlock_macos_take(Eina_Spinlock *spinlock) +{ + os_unfair_lock_lock(SPINLOCK_GET(spinlock)); + return EINA_LOCK_SUCCEED; +} + +EAPI Eina_Lock_Result +_eina_spinlock_macos_take_try(Eina_Spinlock *spinlock) +{ + return (os_unfair_lock_trylock(SPINLOCK_GET(spinlock)) == true) + ? EINA_LOCK_SUCCEED + : EINA_LOCK_FAIL; +} + +EAPI Eina_Lock_Result +_eina_spinlock_macos_release(Eina_Spinlock *spinlock) +{ + os_unfair_lock_unlock(SPINLOCK_GET(spinlock)); + return EINA_LOCK_SUCCEED; +} +#endif /* EINA_HAVE_OSX_SPINLOCK */ + + EAPI void _eina_lock_debug_abort(int err, const char *fn, const volatile void *ptr) { @@ -216,8 +261,6 @@ _eina_spinlock_new(Eina_Spinlock *spinlock) else EINA_LOCK_ABORT_DEBUG(ok, spin_init, spinlock); return EINA_FALSE; #elif defined(EINA_HAVE_OSX_SPINLOCK) - /* OSSpinLock is an integer type. The convention is that unlocked is - * * zero, and locked is nonzero. */ *spinlock = 0; return EINA_TRUE; #else -- 2.7.4