summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Guyomarc'h <jean.guyomarch@gmail.com>2014-08-21 11:23:24 +0200
committerCedric BAIL <cedric@osg.samsung.com>2014-08-21 12:04:53 +0200
commitf449f0ddb6c030e1763cc549caac5e162efbca74 (patch)
treeb108946ace8d71909c36ab0facbb2bcbbc6438be
parentf5b81093978fbbe411f9fb509617b6f4081f8da8 (diff)
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 <cedric@osg.samsung.com>
-rw-r--r--configure.ac8
-rw-r--r--m4/efl_threads.m429
-rw-r--r--src/lib/eina/eina_config.h.in5
-rw-r--r--src/lib/eina/eina_inline_lock_posix.x57
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
936EINA_CONFIG([HAVE_PTHREAD_AFFINITY], [test "x${efl_have_setaffinity}" = "xyes"]) 936EINA_CONFIG([HAVE_PTHREAD_AFFINITY], [test "x${efl_have_setaffinity}" = "xyes"])
937EINA_CONFIG([HAVE_DEBUG_THREADS], [test "x${want_debug_threads}" = "xyes"]) 937EINA_CONFIG([HAVE_DEBUG_THREADS], [test "x${want_debug_threads}" = "xyes"])
938EINA_CONFIG([HAVE_POSIX_SPINLOCK], [test "x${efl_have_posix_threads_spinlock}" = "xyes"]) 938EINA_CONFIG([HAVE_POSIX_SPINLOCK], [test "x${efl_have_posix_threads_spinlock}" = "xyes"])
939EINA_CONFIG([HAVE_OSX_SPINLOCK], [test "x${efl_have_osx_spinlock}" = "xyes"])
939 940
940### Modules 941### Modules
941 942
@@ -4498,7 +4499,12 @@ elif test "${have_windows}" = "yes"; then
4498fi 4499fi
4499EFL_ADD_FEATURE([system], [ipv6]) 4500EFL_ADD_FEATURE([system], [ipv6])
4500 4501
4501EFL_ADD_FEATURE([thread], [spinlocks], [${efl_have_posix_threads_spinlock}]) 4502if test "x${efl_have_posix_threads_spinlock}" = "xyes" || test "x${efl_have_osx_spinlock}" = "xyes"; then
4503 efl_have_spinlock="yes"
4504else
4505 efl_have_spinlock="no"
4506fi
4507EFL_ADD_FEATURE([thread], [spinlocks], [${efl_have_spinlock}])
4502EFL_ADD_FEATURE([thread], [barrier], [${efl_have_pthread_barrier}]) 4508EFL_ADD_FEATURE([thread], [barrier], [${efl_have_pthread_barrier}])
4503EFL_ADD_FEATURE([thread], [affinity], [${efl_have_setaffinity}]) 4509EFL_ADD_FEATURE([thread], [affinity], [${efl_have_setaffinity}])
4504 4510
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
125 AC_DEFINE([EFL_HAVE_POSIX_THREADS_SPINLOCK], [1], [Define to mention that POSIX threads spinlocks are supported]) 125 AC_DEFINE([EFL_HAVE_POSIX_THREADS_SPINLOCK], [1], [Define to mention that POSIX threads spinlocks are supported])
126fi 126fi
127 127
128
129dnl checks if the compiler supports OSX spinlock
130
131efl_have_osx_spinlock="no"
132
133if test "x${_efl_have_posix_threads}" = "xyes" ; then
134 AC_LINK_IFELSE(
135 [AC_LANG_PROGRAM([[
136#include <libkern/OSAtomic.h>
137 ]],
138 [[
139OSSpinLock spin_lock = 0;
140OSSpinLockTry(&spin_lock);
141 ]])],
142 [efl_have_osx_spinlock="yes"],
143 [efl_have_osx_spinlock="no"])
144fi
145
146AC_MSG_CHECKING([whether to build OSX spinlock code])
147AC_MSG_RESULT([${efl_have_osx_spinlock}])
148
149if test "x${efl_have_osx_spinlock}" = "xyes" ; then
150 AC_DEFINE([EFL_HAVE_OSX_SPINLOCK], [1], [Define to mention that OSX spinlocks are supported])
151fi
152
153
154
128AS_IF([test "x$_efl_have_posix_threads" = "xyes" || test "x$_efl_have_win32_threads" = "xyes"], 155AS_IF([test "x$_efl_have_posix_threads" = "xyes" || test "x$_efl_have_win32_threads" = "xyes"],
129 [$1], 156 [$1],
130 [m4_if([$2], [$2], [AC_MSG_ERROR([Threads are required.])])]) 157 [m4_if([$2], [$2], [AC_MSG_ERROR([Threads are required.])])])
131 158
159
132]) 160])
161
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 @@
97#endif 97#endif
98@EINA_CONFIGURE_HAVE_POSIX_SPINLOCK@ 98@EINA_CONFIGURE_HAVE_POSIX_SPINLOCK@
99 99
100#ifndef EINA_HAVE_OSX_SPINLOCK
101# undef EINA_HAVE_OSX_SPINLOCK
102#endif
103@EINA_CONFIGURE_HAVE_OSX_SPINLOCK@
104
100/* Do not turn the following #define as meaning EFL64. We are only 105/* Do not turn the following #define as meaning EFL64. We are only
101 interested to know if sizeof (void*) == 64bits or not. Those means 106 interested to know if sizeof (void*) == 64bits or not. Those means
102 something else. 107 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 @@
38# include <pthread.h> 38# include <pthread.h>
39#endif 39#endif
40 40
41#ifdef EINA_HAVE_OSX_SPINLOCK
42# include <libkern/OSAtomic.h>
43#endif
44
41#include <semaphore.h> 45#include <semaphore.h>
42 46
43#include <sys/time.h> 47#include <sys/time.h>
@@ -59,8 +63,10 @@ typedef struct _Eina_RWLock Eina_RWLock;
59typedef struct _Eina_Condition Eina_Condition; 63typedef struct _Eina_Condition Eina_Condition;
60typedef pthread_key_t Eina_TLS; 64typedef pthread_key_t Eina_TLS;
61typedef sem_t Eina_Semaphore; 65typedef sem_t Eina_Semaphore;
62#ifdef EINA_HAVE_POSIX_SPINLOCK 66#if defined(EINA_HAVE_POSIX_SPINLOCK)
63typedef pthread_spinlock_t Eina_Spinlock; 67typedef pthread_spinlock_t Eina_Spinlock;
68#elif defined(EINA_HAVE_OSX_SPINLOCK)
69typedef OSSpinLock Eina_Spinlock;
64#else 70#else
65typedef Eina_Lock Eina_Spinlock; 71typedef Eina_Lock Eina_Spinlock;
66#endif 72#endif
@@ -603,8 +609,13 @@ eina_barrier_wait(Eina_Barrier *barrier)
603static inline Eina_Bool 609static inline Eina_Bool
604eina_spinlock_new(Eina_Spinlock *spinlock) 610eina_spinlock_new(Eina_Spinlock *spinlock)
605{ 611{
606#ifdef EINA_HAVE_POSIX_SPINLOCK 612#if defined(EINA_HAVE_POSIX_SPINLOCK)
607 return pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE) == 0 ? EINA_TRUE : EINA_FALSE; 613 return pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE) == 0 ? EINA_TRUE : EINA_FALSE;
614#elif defined(EINA_HAVE_OSX_SPINLOCK)
615 /* OSSpinLock is an integer type. The convention is that unlocked is
616 * zero, and locked is nonzero. */
617 *spinlock = 0;
618 return EINA_LOCK_SUCCEED;
608#else 619#else
609 return eina_lock_new(spinlock); 620 return eina_lock_new(spinlock);
610#endif 621#endif
@@ -613,7 +624,7 @@ eina_spinlock_new(Eina_Spinlock *spinlock)
613static inline Eina_Lock_Result 624static inline Eina_Lock_Result
614eina_spinlock_take(Eina_Spinlock *spinlock) 625eina_spinlock_take(Eina_Spinlock *spinlock)
615{ 626{
616#ifdef EINA_HAVE_POSIX_SPINLOCK 627#if defined(EINA_HAVE_POSIX_SPINLOCK)
617 int t; 628 int t;
618 629
619 do { 630 do {
@@ -626,6 +637,12 @@ eina_spinlock_take(Eina_Spinlock *spinlock)
626 } while (t != 0); 637 } while (t != 0);
627 638
628 return EINA_LOCK_SUCCEED; 639 return EINA_LOCK_SUCCEED;
640#elif defined(EINA_HAVE_OSX_SPINLOCK)
641 /* void OSSpinLockLock(OSSpinLock *lock);
642 * Will spin if the lock is already held, but employs various strategies to
643 * back off, making it immune to most priority-inversion livelocks. */
644 OSSpinLockLock(spinlock);
645 return EINA_LOCK_SUCCEED;
629#else 646#else
630 return eina_lock_take(spinlock); 647 return eina_lock_take(spinlock);
631#endif 648#endif
@@ -634,11 +651,16 @@ eina_spinlock_take(Eina_Spinlock *spinlock)
634static inline Eina_Lock_Result 651static inline Eina_Lock_Result
635eina_spinlock_take_try(Eina_Spinlock *spinlock) 652eina_spinlock_take_try(Eina_Spinlock *spinlock)
636{ 653{
637#ifdef EINA_HAVE_POSIX_SPINLOCK 654#if defined(EINA_HAVE_POSIX_SPINLOCK)
638 int t; 655 int t;
639 656
640 t = pthread_spin_trylock(spinlock); 657 t = pthread_spin_trylock(spinlock);
641 return t ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED; 658 return t ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
659#elif defined(EINA_HAVE_OSX_SPINLOCK)
660 /* bool OSSpinLockTry(OSSpinLock *lock);
661 * Immediately returns false if the lock was held, true if it took the
662 * lock. It does not spin. */
663 return (OSSpinLockTry(spinlock)) ? EINA_LOCK_SUCCEED : EINA_LOCK_FAIL;
642#else 664#else
643 return eina_lock_take_try(spinlock); 665 return eina_lock_take_try(spinlock);
644#endif 666#endif
@@ -647,8 +669,13 @@ eina_spinlock_take_try(Eina_Spinlock *spinlock)
647static inline Eina_Lock_Result 669static inline Eina_Lock_Result
648eina_spinlock_release(Eina_Spinlock *spinlock) 670eina_spinlock_release(Eina_Spinlock *spinlock)
649{ 671{
650#ifdef EINA_HAVE_POSIX_SPINLOCK 672#if defined(EINA_HAVE_POSIX_SPINLOCK)
651 return pthread_spin_unlock(spinlock) ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED; 673 return pthread_spin_unlock(spinlock) ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
674#elif defined(EINA_HAVE_OSX_SPINLOCK)
675 /* void OSSpinLockUnlock(OSSpinLock *lock);
676 * Unconditionally unlocks the lock by zeroing it. */
677 OSSpinLockUnlock(spinlock);
678 return EINA_LOCK_SUCCEED;
652#else 679#else
653 return eina_lock_release(spinlock); 680 return eina_lock_release(spinlock);
654#endif 681#endif
@@ -657,8 +684,11 @@ eina_spinlock_release(Eina_Spinlock *spinlock)
657static inline void 684static inline void
658eina_spinlock_free(Eina_Spinlock *spinlock) 685eina_spinlock_free(Eina_Spinlock *spinlock)
659{ 686{
660#ifdef EINA_HAVE_POSIX_SPINLOCK 687#if defined(EINA_HAVE_POSIX_SPINLOCK)
661 pthread_spin_destroy(spinlock); 688 pthread_spin_destroy(spinlock);
689#elif defined(EINA_HAVE_OSX_SPINLOCK)
690 /* Not applicable */
691 (void) spinlock;
662#else 692#else
663 eina_lock_free(spinlock); 693 eina_lock_free(spinlock);
664#endif 694#endif
@@ -670,4 +700,19 @@ eina_spinlock_free(Eina_Spinlock *spinlock)
670# define _XOPEN_SOURCE EINA_XOPEN_SOURCE 700# define _XOPEN_SOURCE EINA_XOPEN_SOURCE
671#endif 701#endif
672 702
703#ifdef EINA_HAVE_OSX_SPINLOCK
704/* The inclusion of libkern/OSAtomic.h is a mess because it includes stdbool
705 * which #defines bool. #undef bool is not sufficient because then other
706 * headers (dlfcn.h) require it and #include stdbool.h to get it. It is
707 * therefore important to "undo" the whole stdbool.h inclusion. */
708# undef true
709# undef false
710# undef bool
711# undef __bool_true_false_are_defined
712# undef _STDBOOL_H_ // OSX SDK
713# undef __STDBOOL_H // Clang 5.1
714# undef _STDBOOL_H // GCC
715#endif
716
717
673#endif 718#endif