summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric Bail <cedric.bail@samsung.com>2013-10-10 17:22:28 +0900
committerCedric Bail <cedric.bail@samsung.com>2013-10-11 11:08:17 +0900
commit1b07350a460fd7177d894116f422577325842225 (patch)
tree68a29da1e957c547e1687221c053d8dcf256e4e2
parenta230728162efd743cec18f8e2a000aac8dab0580 (diff)
eina: add Eina_Spinlock API.
-rw-r--r--ChangeLog4
-rw-r--r--NEWS1
-rw-r--r--configure.ac3
-rw-r--r--m4/efl_threads.m42
-rw-r--r--src/lib/eina/eina_config.h.in5
-rw-r--r--src/lib/eina/eina_inline_lock_posix.x83
-rw-r--r--src/lib/eina/eina_inline_lock_win32.x32
-rw-r--r--src/lib/eina/eina_inline_lock_wince.x31
-rw-r--r--src/lib/eina/eina_lock.h10
9 files changed, 170 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index f81b1399f1..808f62d291 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
12013-10-11 Cedric Bail
2
3 * Eina: add Eina_Spinlock API.
4
12013-10-10 Carsten Haitzler (The Rasterman) 52013-10-10 Carsten Haitzler (The Rasterman)
2 6
3 * Ecore-con: use dlopen/dlsym (eina_module) to load libcurl to 7 * Ecore-con: use dlopen/dlsym (eina_module) to load libcurl to
diff --git a/NEWS b/NEWS
index fa991926b5..91d5bd126a 100644
--- a/NEWS
+++ b/NEWS
@@ -41,6 +41,7 @@ Additions:
41 EINA_RECTANGLE_INIT, EINA_RECTANGLE_FORMAT, EINA_RECTANGLE_ARGS. 41 EINA_RECTANGLE_INIT, EINA_RECTANGLE_FORMAT, EINA_RECTANGLE_ARGS.
42 - Add eina_f16p16_double_from(), eina_f16p16_double_to(). 42 - Add eina_f16p16_double_from(), eina_f16p16_double_to().
43 - Add eina_swap16(), eina_swap32(), eina_swap64(). 43 - Add eina_swap16(), eina_swap32(), eina_swap64().
44 - Add Eina_Spinlock API.
44 * Eet: 45 * Eet:
45 - Add eet_mmap() 46 - Add eet_mmap()
46 - Add eet_data_descriptor_name_get() 47 - Add eet_data_descriptor_name_get()
diff --git a/configure.ac b/configure.ac
index f9e61b38be..8938381bcc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -825,7 +825,8 @@ EFL_ADD_CFLAGS([EINA], [${EFL_PTHREAD_CFLAGS}])
825 825
826EINA_CONFIG([HAVE_PTHREAD_BARRIER], [test "x${efl_have_pthread_barrier}" = "xyes"]) 826EINA_CONFIG([HAVE_PTHREAD_BARRIER], [test "x${efl_have_pthread_barrier}" = "xyes"])
827EINA_CONFIG([HAVE_PTHREAD_AFFINITY], [test "x${efl_have_setaffinity}" = "xyes"]) 827EINA_CONFIG([HAVE_PTHREAD_AFFINITY], [test "x${efl_have_setaffinity}" = "xyes"])
828EINA_CONFIG([HAVE_DEBUG_THREADS], [test "$want_debug_threads" = "yes"]) 828EINA_CONFIG([HAVE_DEBUG_THREADS], [test "x${want_debug_threads}" = "xyes"])
829EINA_CONFIG([HAVE_POSIX_SPINLOCK], [test "x${efl_have_posix_threads_spinlock}" = "xyes"])
829 830
830### Modules 831### Modules
831 832
diff --git a/m4/efl_threads.m4 b/m4/efl_threads.m4
index a657500434..e7a84b36c0 100644
--- a/m4/efl_threads.m4
+++ b/m4/efl_threads.m4
@@ -116,11 +116,13 @@ if test "x${_efl_have_posix_threads}" = "xyes" ; then
116 AC_LINK_IFELSE( 116 AC_LINK_IFELSE(
117 [AC_LANG_PROGRAM([[ 117 [AC_LANG_PROGRAM([[
118#include <pthread.h> 118#include <pthread.h>
119#include <sched.h>
119 ]], 120 ]],
120 [[ 121 [[
121pthread_spinlock_t lock; 122pthread_spinlock_t lock;
122int res; 123int res;
123res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE); 124res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
125sched_yield();
124 ]])], 126 ]])],
125 [efl_have_posix_threads_spinlock="yes"], 127 [efl_have_posix_threads_spinlock="yes"],
126 [efl_have_posix_threads_spinlock="no"]) 128 [efl_have_posix_threads_spinlock="no"])
diff --git a/src/lib/eina/eina_config.h.in b/src/lib/eina/eina_config.h.in
index 27acdf72b6..72e3ed3eeb 100644
--- a/src/lib/eina/eina_config.h.in
+++ b/src/lib/eina/eina_config.h.in
@@ -92,4 +92,9 @@
92#endif 92#endif
93@EINA_CONFIGURE_HAVE_BYTESWAP_H@ 93@EINA_CONFIGURE_HAVE_BYTESWAP_H@
94 94
95#ifdef EINA_HAVE_POSIX_SPINLOCK
96# undef EINA_HAVE_POSIX_SPINLOCK
97#endif
98@EINA_CONFIGURE_HAVE_POSIX_SPINLOCK@
99
95#endif /* EINA_CONFIG_H_ */ 100#endif /* EINA_CONFIG_H_ */
diff --git a/src/lib/eina/eina_inline_lock_posix.x b/src/lib/eina/eina_inline_lock_posix.x
index 88c4b61c11..472717774f 100644
--- a/src/lib/eina/eina_inline_lock_posix.x
+++ b/src/lib/eina/eina_inline_lock_posix.x
@@ -19,6 +19,10 @@
19#ifndef EINA_INLINE_LOCK_POSIX_X_ 19#ifndef EINA_INLINE_LOCK_POSIX_X_
20#define EINA_INLINE_LOCK_POSIX_X_ 20#define EINA_INLINE_LOCK_POSIX_X_
21 21
22#ifdef EINA_HAVE_POSIX_SPINLOCK
23# include <sched.h>
24#endif
25
22#include <errno.h> 26#include <errno.h>
23#ifndef __USE_UNIX98 27#ifndef __USE_UNIX98
24# define __USE_UNIX98 28# define __USE_UNIX98
@@ -49,6 +53,11 @@ typedef struct _Eina_RWLock Eina_RWLock;
49typedef struct _Eina_Condition Eina_Condition; 53typedef struct _Eina_Condition Eina_Condition;
50typedef pthread_key_t Eina_TLS; 54typedef pthread_key_t Eina_TLS;
51typedef sem_t Eina_Semaphore; 55typedef sem_t Eina_Semaphore;
56#ifdef EINA_HAVE_POSIX_SPINLOCK
57typedef pthread_spinlock_t Eina_Spinlock;
58#else
59typedef Eina_Lock Eina_Spinlock;
60#endif
52 61
53struct _Eina_Lock 62struct _Eina_Lock
54{ 63{
@@ -577,5 +586,79 @@ eina_barrier_wait(Eina_Barrier *barrier)
577#include "eina_inline_lock_barrier.x" 586#include "eina_inline_lock_barrier.x"
578#endif 587#endif
579 588
589static inline Eina_Bool
590eina_spinlock_new(Eina_Spinlock *spinlock)
591{
592#ifdef EINA_HAVE_POSIX_SPINLOCK
593 return pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE) == 0 ? EINA_TRUE : EINA_FALSE;
594#else
595 return eina_lock_new(spinlock);
596#endif
597}
598
599static inline Eina_Lock_Result
600eina_spinlock_take(Eina_Spinlock *spinlock)
601{
602#ifdef EINA_HAVE_POSIX_SPINLOCK
603 Eina_Bool yield;
604 int t;
605
606 do {
607 yield = EINA_FALSE;
608
609 t = pthread_spin_trylock(spinlock);
610 if (t != 0)
611 {
612 if (errno == EBUSY)
613 {
614 sched_yield();
615 yield = EINA_TRUE;
616 }
617 else if (errno == EDEADLK)
618 {
619 return EINA_LOCK_DEADLOCK;
620 }
621 }
622
623 } while (t != 0 && yield);
624
625 return t ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
626#else
627 return eina_lock_take(spinlock);
628#endif
629}
630
631static inline Eina_Lock_Result
632eina_spinlock_take_try(Eina_Spinlock *spinlock)
633{
634#ifdef EINA_HAVE_POSIX_SPINLOCK
635 int t;
636
637 t = pthread_spin_trylock(spinlock);
638 return t ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
639#else
640 return eina_lock_take_try(spinlock);
641#endif
642}
643
644static inline Eina_Lock_Result
645eina_spinlock_release(Eina_Spinlock *spinlock)
646{
647#ifdef EINA_HAVE_POSIX_SPINLOCK
648 return pthread_spin_unlock(spinlock) ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
649#else
650 return eina_lock_release(spinlock);
651#endif
652}
653
654static inline void
655eina_spinlock_free(Eina_Spinlock *spinlock)
656{
657#ifdef EINA_HAVE_POSIX_SPINLOCK
658 pthread_spin_destroy(spinlock);
659#else
660 eina_lock_free(spinlock);
661#endif
662}
580 663
581#endif 664#endif
diff --git a/src/lib/eina/eina_inline_lock_win32.x b/src/lib/eina/eina_inline_lock_win32.x
index 383a543f98..3c637affb1 100644
--- a/src/lib/eina/eina_inline_lock_win32.x
+++ b/src/lib/eina/eina_inline_lock_win32.x
@@ -30,6 +30,7 @@ typedef struct _Eina_Condition Eina_Condition;
30typedef struct _Eina_RWLock Eina_RWLock; 30typedef struct _Eina_RWLock Eina_RWLock;
31typedef DWORD Eina_TLS; 31typedef DWORD Eina_TLS;
32typedef HANDLE Eina_Semaphore; 32typedef HANDLE Eina_Semaphore;
33typedef Eina_Lock Eina_Spinlock;
33 34
34#if _WIN32_WINNT >= 0x0600 35#if _WIN32_WINNT >= 0x0600
35struct _Eina_Condition 36struct _Eina_Condition
@@ -551,6 +552,37 @@ eina_semaphore_release(Eina_Semaphore *sem, int count_release)
551 return ReleaseSemaphore(*sem, count_release, NULL) ? EINA_TRUE : EINA_FALSE; 552 return ReleaseSemaphore(*sem, count_release, NULL) ? EINA_TRUE : EINA_FALSE;
552} 553}
553 554
555// FIXME: Implement proper spinlock = http://www.codeproject.com/Articles/184046/Spin-Lock-in-C
556static inline Eina_Bool
557eina_spinlock_new(Eina_Spinlock *spinlock)
558{
559 return eina_lock_new(spinlock);
560}
561
562static inline Eina_Lock_Result
563eina_spinlock_take(Eina_Spinlock *spinlock)
564{
565 return eina_lock_take(spinlock);
566}
567
568static inline Eina_Lock_Result
569eina_spinlock_take_try(Eina_Spinlock *spinlock)
570{
571 return eina_lock_take_try(spinlock);
572}
573
574static inline Eina_Lock_Result
575eina_spinlock_release(Eina_Spinlock *spinlock)
576{
577 return eina_lock_release(spinlock);
578}
579
580static inline void
581eina_spinlock_free(Eina_Spinlock *spinlock)
582{
583 eina_lock_free(spinlock);
584}
585
554#include "eina_inline_lock_barrier.x" 586#include "eina_inline_lock_barrier.x"
555 587
556#endif 588#endif
diff --git a/src/lib/eina/eina_inline_lock_wince.x b/src/lib/eina/eina_inline_lock_wince.x
index 787795977f..3b732568da 100644
--- a/src/lib/eina/eina_inline_lock_wince.x
+++ b/src/lib/eina/eina_inline_lock_wince.x
@@ -28,6 +28,7 @@
28EAPI extern Eina_Bool _threads_activated; 28EAPI extern Eina_Bool _threads_activated;
29 29
30typedef HANDLE Eina_Lock; 30typedef HANDLE Eina_Lock;
31typedef Eina_Lock Eina_Spinlock;
31typedef Eina_Lock Eina_RWLock; 32typedef Eina_Lock Eina_RWLock;
32typedef DWORD Eina_TLS; 33typedef DWORD Eina_TLS;
33typedef void * Eina_Semaphore; 34typedef void * Eina_Semaphore;
@@ -204,6 +205,36 @@ eina_semaphore_release(Eina_Semaphore *sem EINA_UNUSED,
204 return EINA_FALSE; 205 return EINA_FALSE;
205} 206}
206 207
208static inline Eina_Bool
209eina_spinlock_new(Eina_Spinlock *spinlock)
210{
211 return eina_lock_new(spinlock);
212}
213
214static inline void
215eina_spinlock_free(Eina_Spinlock *spinlock)
216{
217 eina_lock_free(spinlock);
218}
219
220static inline Eina_Lock_Result
221eina_spinlock_take(Eina_Spinlock *spinlock)
222{
223 return eina_lock_take(spinlock);
224}
225
226static inline Eina_Lock_Result
227eina_spinlock_take_try(Eina_Spinlock *spinlock)
228{
229 return eina_lock_take_try(spinlock);
230}
231
232static inline Eina_Lock_Result
233eina_spinlock_release(Eina_Spinlock *spinlock)
234{
235 return eina_lock_release(spinlock);
236}
237
207#include "eina_inline_lock_barrier.x" 238#include "eina_inline_lock_barrier.x"
208 239
209#endif 240#endif
diff --git a/src/lib/eina/eina_lock.h b/src/lib/eina/eina_lock.h
index ceb19d7b71..3e4a510252 100644
--- a/src/lib/eina/eina_lock.h
+++ b/src/lib/eina/eina_lock.h
@@ -113,6 +113,16 @@ static inline void eina_barrier_free(Eina_Barrier *barrier);
113/** @relates static Eina_Bool eina_barrier_wait(Eina_Barrier *barrier); @since 1.8 */ 113/** @relates static Eina_Bool eina_barrier_wait(Eina_Barrier *barrier); @since 1.8 */
114static inline Eina_Bool eina_barrier_wait(Eina_Barrier *barrier); 114static inline Eina_Bool eina_barrier_wait(Eina_Barrier *barrier);
115 115
116/** @relates static Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock); @since 1.8 */
117static inline Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock);
118/** @relates static Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock); @since 1.8 */
119static inline Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock);
120/** @relates static Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock); @since 1.8 */
121static inline Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock);
122/** @relates static Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock); @since 1.8 */
123static inline Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock);
124/** @relates static void eina_spinlock_free(Eina_Spinlock *spinlock); @since 1.8 */
125static inline void eina_spinlock_free(Eina_Spinlock *spinlock);
116 126
117#ifdef EINA_HAVE_DEBUG_THREADS 127#ifdef EINA_HAVE_DEBUG_THREADS
118# define EINA_MAIN_LOOP_CHECK_RETURN_VAL(val) \ 128# define EINA_MAIN_LOOP_CHECK_RETURN_VAL(val) \