cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=f449f0ddb6c030e1763cc549caac5e162efbca74
commit f449f0ddb6c030e1763cc549caac5e162efbca74 Author: Jean Guyomarc'h <[email protected]> Date: Thu Aug 21 11:23:24 2014 +0200 eina: port Eina_Spinlock for OSX Summary: Support of Spinlocks in Eina (Eina_Spinlock) for OSX, which does not implement them in pthread. @feature Reviewers: raster, raoulh, naguirre, cedric, stefan_schmidt Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D1151 Signed-off-by: Cedric BAIL <[email protected]> --- configure.ac | 8 ++++- m4/efl_threads.m4 | 29 ++++++++++++++++++ src/lib/eina/eina_config.h.in | 5 +++ src/lib/eina/eina_inline_lock_posix.x | 57 +++++++++++++++++++++++++++++++---- 4 files changed, 92 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index dbd24cc..c39c550 100644 --- a/configure.ac +++ b/configure.ac @@ -936,6 +936,7 @@ EINA_CONFIG([HAVE_PTHREAD_BARRIER], [test "x${efl_have_pthread_barrier}" = "xyes EINA_CONFIG([HAVE_PTHREAD_AFFINITY], [test "x${efl_have_setaffinity}" = "xyes"]) EINA_CONFIG([HAVE_DEBUG_THREADS], [test "x${want_debug_threads}" = "xyes"]) EINA_CONFIG([HAVE_POSIX_SPINLOCK], [test "x${efl_have_posix_threads_spinlock}" = "xyes"]) +EINA_CONFIG([HAVE_OSX_SPINLOCK], [test "x${efl_have_osx_spinlock}" = "xyes"]) ### Modules @@ -4498,7 +4499,12 @@ elif test "${have_windows}" = "yes"; then fi EFL_ADD_FEATURE([system], [ipv6]) -EFL_ADD_FEATURE([thread], [spinlocks], [${efl_have_posix_threads_spinlock}]) +if test "x${efl_have_posix_threads_spinlock}" = "xyes" || test "x${efl_have_osx_spinlock}" = "xyes"; then + efl_have_spinlock="yes" +else + efl_have_spinlock="no" +fi +EFL_ADD_FEATURE([thread], [spinlocks], [${efl_have_spinlock}]) EFL_ADD_FEATURE([thread], [barrier], [${efl_have_pthread_barrier}]) EFL_ADD_FEATURE([thread], [affinity], [${efl_have_setaffinity}]) diff --git a/m4/efl_threads.m4 b/m4/efl_threads.m4 index 04b3e64..9596908 100644 --- a/m4/efl_threads.m4 +++ b/m4/efl_threads.m4 @@ -125,8 +125,37 @@ if test "x${efl_have_posix_threads_spinlock}" = "xyes" ; then AC_DEFINE([EFL_HAVE_POSIX_THREADS_SPINLOCK], [1], [Define to mention that POSIX threads spinlocks are supported]) fi + +dnl checks if the compiler supports OSX spinlock + +efl_have_osx_spinlock="no" + +if test "x${_efl_have_posix_threads}" = "xyes" ; then + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#include <libkern/OSAtomic.h> + ]], + [[ +OSSpinLock spin_lock = 0; +OSSpinLockTry(&spin_lock); + ]])], + [efl_have_osx_spinlock="yes"], + [efl_have_osx_spinlock="no"]) +fi + +AC_MSG_CHECKING([whether to build OSX spinlock code]) +AC_MSG_RESULT([${efl_have_osx_spinlock}]) + +if test "x${efl_have_osx_spinlock}" = "xyes" ; then + AC_DEFINE([EFL_HAVE_OSX_SPINLOCK], [1], [Define to mention that OSX spinlocks are supported]) +fi + + + AS_IF([test "x$_efl_have_posix_threads" = "xyes" || test "x$_efl_have_win32_threads" = "xyes"], [$1], [m4_if([$2], [$2], [AC_MSG_ERROR([Threads are required.])])]) + ]) + diff --git a/src/lib/eina/eina_config.h.in b/src/lib/eina/eina_config.h.in index 1f6fe67..cdaf867 100644 --- a/src/lib/eina/eina_config.h.in +++ b/src/lib/eina/eina_config.h.in @@ -97,6 +97,11 @@ #endif @EINA_CONFIGURE_HAVE_POSIX_SPINLOCK@ +#ifndef EINA_HAVE_OSX_SPINLOCK +# undef EINA_HAVE_OSX_SPINLOCK +#endif +@EINA_CONFIGURE_HAVE_OSX_SPINLOCK@ + /* Do not turn the following #define as meaning EFL64. We are only interested to know if sizeof (void*) == 64bits or not. Those means something else. diff --git a/src/lib/eina/eina_inline_lock_posix.x b/src/lib/eina/eina_inline_lock_posix.x index 0de48e5..172e571 100644 --- a/src/lib/eina/eina_inline_lock_posix.x +++ b/src/lib/eina/eina_inline_lock_posix.x @@ -38,6 +38,10 @@ # include <pthread.h> #endif +#ifdef EINA_HAVE_OSX_SPINLOCK +# include <libkern/OSAtomic.h> +#endif + #include <semaphore.h> #include <sys/time.h> @@ -59,8 +63,10 @@ typedef struct _Eina_RWLock Eina_RWLock; typedef struct _Eina_Condition Eina_Condition; typedef pthread_key_t Eina_TLS; typedef sem_t Eina_Semaphore; -#ifdef EINA_HAVE_POSIX_SPINLOCK +#if defined(EINA_HAVE_POSIX_SPINLOCK) typedef pthread_spinlock_t Eina_Spinlock; +#elif defined(EINA_HAVE_OSX_SPINLOCK) +typedef OSSpinLock Eina_Spinlock; #else typedef Eina_Lock Eina_Spinlock; #endif @@ -603,8 +609,13 @@ eina_barrier_wait(Eina_Barrier *barrier) static inline Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock) { -#ifdef EINA_HAVE_POSIX_SPINLOCK +#if defined(EINA_HAVE_POSIX_SPINLOCK) return pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE) == 0 ? EINA_TRUE : 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_LOCK_SUCCEED; #else return eina_lock_new(spinlock); #endif @@ -613,7 +624,7 @@ eina_spinlock_new(Eina_Spinlock *spinlock) static inline Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock) { -#ifdef EINA_HAVE_POSIX_SPINLOCK +#if defined(EINA_HAVE_POSIX_SPINLOCK) int t; do { @@ -626,6 +637,12 @@ eina_spinlock_take(Eina_Spinlock *spinlock) } while (t != 0); 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; #else return eina_lock_take(spinlock); #endif @@ -634,11 +651,16 @@ eina_spinlock_take(Eina_Spinlock *spinlock) static inline Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock) { -#ifdef EINA_HAVE_POSIX_SPINLOCK +#if defined(EINA_HAVE_POSIX_SPINLOCK) int t; t = pthread_spin_trylock(spinlock); return t ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED; +#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; #else return eina_lock_take_try(spinlock); #endif @@ -647,8 +669,13 @@ eina_spinlock_take_try(Eina_Spinlock *spinlock) static inline Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock) { -#ifdef EINA_HAVE_POSIX_SPINLOCK +#if defined(EINA_HAVE_POSIX_SPINLOCK) return pthread_spin_unlock(spinlock) ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED; +#elif defined(EINA_HAVE_OSX_SPINLOCK) + /* void OSSpinLockUnlock(OSSpinLock *lock); + * Unconditionally unlocks the lock by zeroing it. */ + OSSpinLockUnlock(spinlock); + return EINA_LOCK_SUCCEED; #else return eina_lock_release(spinlock); #endif @@ -657,8 +684,11 @@ eina_spinlock_release(Eina_Spinlock *spinlock) static inline void eina_spinlock_free(Eina_Spinlock *spinlock) { -#ifdef EINA_HAVE_POSIX_SPINLOCK +#if defined(EINA_HAVE_POSIX_SPINLOCK) pthread_spin_destroy(spinlock); +#elif defined(EINA_HAVE_OSX_SPINLOCK) + /* Not applicable */ + (void) spinlock; #else eina_lock_free(spinlock); #endif @@ -670,4 +700,19 @@ eina_spinlock_free(Eina_Spinlock *spinlock) # 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 --
