eina: add Eina_Spinlock API.

This commit is contained in:
Cedric Bail 2013-10-10 17:22:28 +09:00
parent a230728162
commit 1b07350a46
9 changed files with 170 additions and 1 deletions

View File

@ -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

1
NEWS
View File

@ -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()

View 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

View 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"])

View 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_ */

View File

@ -19,6 +19,10 @@
#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

View 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

View 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

View 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) \