eina: add Eina_Spinlock API.
authorCedric Bail <cedric.bail@samsung.com>
Thu, 10 Oct 2013 08:22:28 +0000 (17:22 +0900)
committerCedric Bail <cedric.bail@samsung.com>
Fri, 11 Oct 2013 02:08:17 +0000 (11:08 +0900)
ChangeLog
NEWS
configure.ac
m4/efl_threads.m4
src/lib/eina/eina_config.h.in
src/lib/eina/eina_inline_lock_posix.x
src/lib/eina/eina_inline_lock_win32.x
src/lib/eina/eina_inline_lock_wince.x
src/lib/eina/eina_lock.h

index f81b139..808f62d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-10-11  Cedric Bail
+
+       * Eina: add Eina_Spinlock API.
+
 2013-10-10  Carsten Haitzler (The Rasterman)
 
         * Ecore-con: use dlopen/dlsym (eina_module) to load libcurl to
diff --git a/NEWS b/NEWS
index fa99192..91d5bd1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -41,6 +41,7 @@ Additions:
      EINA_RECTANGLE_INIT, EINA_RECTANGLE_FORMAT, EINA_RECTANGLE_ARGS.
      - Add eina_f16p16_double_from(), eina_f16p16_double_to().
      - Add eina_swap16(), eina_swap32(), eina_swap64().
+     - Add Eina_Spinlock API.
     * Eet:
      - Add eet_mmap()
      - Add eet_data_descriptor_name_get()
index f9e61b3..8938381 100644 (file)
@@ -825,7 +825,8 @@ EFL_ADD_CFLAGS([EINA], [${EFL_PTHREAD_CFLAGS}])
 
 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 "$want_debug_threads" = "yes"])
+EINA_CONFIG([HAVE_DEBUG_THREADS], [test "x${want_debug_threads}" = "xyes"])
+EINA_CONFIG([HAVE_POSIX_SPINLOCK], [test "x${efl_have_posix_threads_spinlock}" = "xyes"])
 
 ### Modules
 
index a657500..e7a84b3 100644 (file)
@@ -116,11 +116,13 @@ if test "x${_efl_have_posix_threads}" = "xyes" ; then
    AC_LINK_IFELSE(
       [AC_LANG_PROGRAM([[
 #include <pthread.h>
+#include <sched.h>
                        ]],
                        [[
 pthread_spinlock_t lock;
 int res;
 res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
+sched_yield();
                        ]])],
       [efl_have_posix_threads_spinlock="yes"],
       [efl_have_posix_threads_spinlock="no"])
index 27acdf7..72e3ed3 100644 (file)
@@ -92,4 +92,9 @@
 #endif
 @EINA_CONFIGURE_HAVE_BYTESWAP_H@
 
+#ifdef EINA_HAVE_POSIX_SPINLOCK
+# undef EINA_HAVE_POSIX_SPINLOCK
+#endif
+@EINA_CONFIGURE_HAVE_POSIX_SPINLOCK@
+
 #endif /* EINA_CONFIG_H_ */
index 88c4b61..4727177 100644 (file)
 #ifndef EINA_INLINE_LOCK_POSIX_X_
 #define EINA_INLINE_LOCK_POSIX_X_
 
+#ifdef EINA_HAVE_POSIX_SPINLOCK
+# include <sched.h>
+#endif
+
 #include <errno.h>
 #ifndef __USE_UNIX98
 # define __USE_UNIX98
@@ -49,6 +53,11 @@ 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
+typedef pthread_spinlock_t Eina_Spinlock;
+#else
+typedef Eina_Lock Eina_Spinlock;
+#endif
 
 struct _Eina_Lock
 {
@@ -577,5 +586,79 @@ eina_barrier_wait(Eina_Barrier *barrier)
 #include "eina_inline_lock_barrier.x"
 #endif
 
+static inline Eina_Bool
+eina_spinlock_new(Eina_Spinlock *spinlock)
+{
+#ifdef EINA_HAVE_POSIX_SPINLOCK
+   return pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE) == 0 ? EINA_TRUE : EINA_FALSE;
+#else
+   return eina_lock_new(spinlock);
+#endif
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_take(Eina_Spinlock *spinlock)
+{
+#ifdef EINA_HAVE_POSIX_SPINLOCK
+   Eina_Bool yield;
+   int t;
+
+   do {
+      yield = EINA_FALSE;
+
+      t = pthread_spin_trylock(spinlock);
+      if (t != 0)
+        {
+           if (errno == EBUSY)
+             {
+                sched_yield();
+                yield = EINA_TRUE;
+             }
+           else if (errno == EDEADLK)
+             {
+                return EINA_LOCK_DEADLOCK;
+             }
+        }
+
+   } while (t != 0 && yield);
+
+   return t ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
+#else
+   return eina_lock_take(spinlock);
+#endif
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_take_try(Eina_Spinlock *spinlock)
+{
+#ifdef EINA_HAVE_POSIX_SPINLOCK
+   int t;
+
+   t = pthread_spin_trylock(spinlock);
+   return t ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
+#else
+   return eina_lock_take_try(spinlock);
+#endif
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_release(Eina_Spinlock *spinlock)
+{
+#ifdef EINA_HAVE_POSIX_SPINLOCK
+   return pthread_spin_unlock(spinlock) ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
+#else
+   return eina_lock_release(spinlock);
+#endif
+}
+
+static inline void
+eina_spinlock_free(Eina_Spinlock *spinlock)
+{
+#ifdef EINA_HAVE_POSIX_SPINLOCK
+   pthread_spin_destroy(spinlock);
+#else
+   eina_lock_free(spinlock);
+#endif
+}
 
 #endif
index 383a543..3c637af 100644 (file)
@@ -30,6 +30,7 @@ typedef struct _Eina_Condition Eina_Condition;
 typedef struct _Eina_RWLock    Eina_RWLock;
 typedef DWORD                  Eina_TLS;
 typedef HANDLE                 Eina_Semaphore;
+typedef Eina_Lock              Eina_Spinlock;
 
 #if _WIN32_WINNT >= 0x0600
 struct _Eina_Condition
@@ -551,6 +552,37 @@ eina_semaphore_release(Eina_Semaphore *sem, int count_release)
    return ReleaseSemaphore(*sem, count_release, NULL) ? EINA_TRUE : EINA_FALSE;
 }
 
+// FIXME: Implement proper spinlock = http://www.codeproject.com/Articles/184046/Spin-Lock-in-C
+static inline Eina_Bool
+eina_spinlock_new(Eina_Spinlock *spinlock)
+{
+   return eina_lock_new(spinlock);
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_take(Eina_Spinlock *spinlock)
+{
+   return eina_lock_take(spinlock);
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_take_try(Eina_Spinlock *spinlock)
+{
+   return eina_lock_take_try(spinlock);
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_release(Eina_Spinlock *spinlock)
+{
+   return eina_lock_release(spinlock);
+}
+
+static inline void
+eina_spinlock_free(Eina_Spinlock *spinlock)
+{
+   eina_lock_free(spinlock);
+}
+
 #include "eina_inline_lock_barrier.x"
 
 #endif
index 7877959..3b73256 100644 (file)
@@ -28,6 +28,7 @@
 EAPI extern Eina_Bool _threads_activated;
 
 typedef HANDLE    Eina_Lock;
+typedef Eina_Lock Eina_Spinlock;
 typedef Eina_Lock Eina_RWLock;
 typedef DWORD     Eina_TLS;
 typedef void *    Eina_Semaphore;
@@ -204,6 +205,36 @@ eina_semaphore_release(Eina_Semaphore *sem EINA_UNUSED,
    return EINA_FALSE;
 }
 
+static inline Eina_Bool
+eina_spinlock_new(Eina_Spinlock *spinlock)
+{
+   return eina_lock_new(spinlock);
+}
+
+static inline void
+eina_spinlock_free(Eina_Spinlock *spinlock)
+{
+   eina_lock_free(spinlock);
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_take(Eina_Spinlock *spinlock)
+{
+   return eina_lock_take(spinlock);
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_take_try(Eina_Spinlock *spinlock)
+{
+   return eina_lock_take_try(spinlock);
+}
+
+static inline Eina_Lock_Result
+eina_spinlock_release(Eina_Spinlock *spinlock)
+{
+   return eina_lock_release(spinlock);
+}
+
 #include "eina_inline_lock_barrier.x"
 
 #endif
index ceb19d7..3e4a510 100644 (file)
@@ -113,6 +113,16 @@ static inline void eina_barrier_free(Eina_Barrier *barrier);
 /** @relates static Eina_Bool eina_barrier_wait(Eina_Barrier *barrier); @since 1.8 */
 static inline Eina_Bool eina_barrier_wait(Eina_Barrier *barrier);
 
+/** @relates static Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock); @since 1.8 */
+static inline Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock);
+/** @relates static Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock); @since 1.8 */
+static inline Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock);
+/** @relates static Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock); @since 1.8 */
+static inline Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock);
+/** @relates static Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock); @since 1.8 */
+static inline Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock);
+/** @relates static void eina_spinlock_free(Eina_Spinlock *spinlock); @since 1.8 */
+static inline void eina_spinlock_free(Eina_Spinlock *spinlock);
 
 #ifdef EINA_HAVE_DEBUG_THREADS
 # define EINA_MAIN_LOOP_CHECK_RETURN_VAL(val)                          \