forked from enlightenment/efl
Windows:eina: Add Thread synchronization (#34)
This should add all needed functions/structures for thread synchronization besides: - eina_condition initialization; - cond_timedwait.
This commit is contained in:
parent
728e1afde9
commit
ea6d1c40ee
|
@ -49,7 +49,7 @@
|
|||
// broken on OSX in that a HUP signal will maybe cause a crash... but compiling
|
||||
// with -pg would have guaranteed always caused a crash before anyway.
|
||||
// given OSX only supports "old-style" signals like:
|
||||
//
|
||||
//
|
||||
// #define SIGHUP 1 /* hangup */
|
||||
// #define SIGINT 2 /* interrupt */
|
||||
// #define SIGQUIT 3 /* quit */
|
||||
|
@ -90,7 +90,7 @@
|
|||
// #endif
|
||||
// #define SIGUSR1 30 /* user defined signal 1 */
|
||||
// #define SIGUSR2 31 /* user defined signal 2 */
|
||||
//
|
||||
//
|
||||
// (excerpt from OSX's signal.h - found at:
|
||||
// http://github.com/st3fan/osx-10.9/blob/master/xnu-2422.1.72/bsd/sys/signal.h
|
||||
// pasting here due to how difficult it was to find a signal list for OSX)
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
typedef struct _Eina_Barrier Eina_Barrier;
|
||||
|
||||
/** @private */
|
||||
struct _Eina_Barrier
|
||||
{
|
||||
int needed; /**< The number of waiting threads that will cause the barrier to signal and reset. */
|
||||
int called; /**< The number of threads that are waiting on this barrier. */
|
||||
Eina_Lock cond_lock; /**< The lock for the barrier */
|
||||
Eina_Condition cond; /**< The condition variable for the barrier */
|
||||
};
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_barrier_wait(Eina_Barrier *barrier)
|
||||
{
|
||||
eina_lock_take(&(barrier->cond_lock));
|
||||
barrier->called++;
|
||||
if (barrier->called == barrier->needed)
|
||||
{
|
||||
barrier->called = 0;
|
||||
eina_condition_broadcast(&(barrier->cond));
|
||||
}
|
||||
else
|
||||
eina_condition_wait(&(barrier->cond));
|
||||
eina_lock_release(&(barrier->cond_lock));
|
||||
return EINA_TRUE;
|
||||
}
|
|
@ -25,7 +25,26 @@
|
|||
#endif
|
||||
#define _XOPEN_SOURCE 600
|
||||
|
||||
#ifdef EINA_HAVE_POSIX_SPINLOCK
|
||||
#ifdef EINA_HAVE_OSX_SPINLOCK
|
||||
/*
|
||||
* macOS 10.12 introduced the os_unfair_lock API which
|
||||
* deprecates OSSpinLock, while keeping compatible.
|
||||
*
|
||||
* The Spinlock API is not inlined because it would imply including
|
||||
* stdbool.h, which is not wanted: it would introduce new macros,
|
||||
* and break compilation of existing programs.
|
||||
*/
|
||||
# if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
||||
# include <os/lock.h>
|
||||
# define SPINLOCK_GET(LCK) ((os_unfair_lock_t)(LCK))
|
||||
# else
|
||||
# include <libkern/OSAtomic.h>
|
||||
# define SPINLOCK_GET(LCK) ((OSSpinLock *)(LCK))
|
||||
# define os_unfair_lock_lock(LCK) OSSpinLockLock(LCK)
|
||||
# define os_unfair_lock_unlock(LCK) OSSpinLockUnlock(LCK)
|
||||
# define os_unfair_lock_trylock(LCK) OSSpinLockTry(LCK)
|
||||
# endif
|
||||
#elif defined(EINA_HAVE_PTHREAD_SPINLOCK)
|
||||
# include <sched.h>
|
||||
#endif
|
||||
|
||||
|
@ -80,7 +99,7 @@ typedef struct _Eina_RWLock Eina_RWLock;
|
|||
typedef struct _Eina_Condition Eina_Condition;
|
||||
typedef pthread_key_t Eina_TLS;
|
||||
|
||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||
#ifdef EINA_HAVE_PTHREAD_SPINLOCK
|
||||
typedef pthread_spinlock_t Eina_Spinlock;
|
||||
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
||||
typedef uintptr_t Eina_Spinlock;
|
||||
|
@ -99,17 +118,15 @@ EAPI void eina_lock_debug(const Eina_Lock *mutex);
|
|||
/** @privatesection @{ */
|
||||
struct _Eina_Lock
|
||||
{
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
EINA_INLIST; /**< Keeps track of the threads waiting for the lock */
|
||||
#endif
|
||||
pthread_mutex_t mutex; /**< The mutex that handles the locking */
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
EINA_INLIST; /**< Keeps track of the threads waiting for the lock */
|
||||
pthread_t lock_thread_id; /**< The ID of the thread that currently has the lock */
|
||||
Eina_Lock_Bt_Func lock_bt[EINA_LOCK_DEBUG_BT_NUM]; /**< The function that will produce a backtrace on the thread that has the lock */
|
||||
int lock_bt_num; /**< Number of addresses in the backtrace */
|
||||
Eina_Bool locked : 1; /**< Indicates locked or not locked */
|
||||
Eina_Bool recursive : 1; /**< Indicates recursive lock */
|
||||
#endif
|
||||
#endif /* EINA_HAVE_DEBUG_THREADS */
|
||||
};
|
||||
|
||||
struct _Eina_Condition
|
||||
|
@ -139,51 +156,29 @@ EAPI extern pthread_mutex_t _eina_tracking_lock;
|
|||
EAPI extern Eina_Inlist *_eina_tracking;
|
||||
#endif
|
||||
|
||||
|
||||
EAPI Eina_Bool _eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive);
|
||||
EAPI void _eina_lock_free(Eina_Lock *mutex);
|
||||
EAPI Eina_Bool _eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
|
||||
EAPI void _eina_condition_free(Eina_Condition *cond);
|
||||
EAPI Eina_Bool _eina_rwlock_new(Eina_RWLock *mutex);
|
||||
EAPI void _eina_rwlock_free(Eina_RWLock *mutex);
|
||||
EAPI Eina_Bool _eina_spinlock_new(Eina_Spinlock *spinlock);
|
||||
EAPI void _eina_spinlock_free(Eina_Spinlock *spinlock);
|
||||
EAPI Eina_Bool _eina_semaphore_new(Eina_Semaphore *sem, int count_init);
|
||||
EAPI Eina_Bool _eina_semaphore_free(Eina_Semaphore *sem);
|
||||
#ifdef EINA_HAVE_OSX_SPINLOCK
|
||||
EAPI Eina_Lock_Result _eina_spinlock_macos_take(Eina_Spinlock *spinlock);
|
||||
EAPI Eina_Lock_Result _eina_spinlock_macos_take_try(Eina_Spinlock *spinlock);
|
||||
EAPI Eina_Lock_Result _eina_spinlock_macos_release(Eina_Spinlock *spinlock);
|
||||
#endif
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_lock_new(Eina_Lock *mutex)
|
||||
_eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive)
|
||||
{
|
||||
Eina_Bool ret = _eina_lock_new(mutex, EINA_FALSE);
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
mutex->recursive = EINA_FALSE;
|
||||
mutex->lock_thread_id = 0;
|
||||
mutex->lock_bt_num = 0;
|
||||
mutex->locked = 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
pthread_mutexattr_t attr;
|
||||
Eina_Bool ok = EINA_FALSE;
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_lock_recursive_new(Eina_Lock *mutex)
|
||||
{
|
||||
Eina_Bool ret = _eina_lock_new(mutex, EINA_TRUE);
|
||||
if (pthread_mutexattr_init(&attr) != 0) return EINA_FALSE;
|
||||
if (recursive)
|
||||
{
|
||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) goto fail_release;
|
||||
}
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
mutex->recursive = EINA_TRUE;
|
||||
mutex->lock_thread_id = 0;
|
||||
mutex->lock_bt_num = 0;
|
||||
mutex->locked = 0;
|
||||
else if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) goto fail_release;
|
||||
#endif
|
||||
return ret;
|
||||
if (pthread_mutex_init(&(mutex->mutex), &attr) != 0) goto fail_release;
|
||||
ok = EINA_TRUE;
|
||||
fail_release:
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_lock_free(Eina_Lock *mutex)
|
||||
_eina_lock_free(Eina_Lock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (mutex->locked)
|
||||
|
@ -194,11 +189,15 @@ eina_lock_free(Eina_Lock *mutex)
|
|||
pthread_mutex_unlock(&_eina_tracking_lock);
|
||||
}
|
||||
#endif
|
||||
_eina_lock_free(mutex);
|
||||
|
||||
int ok;
|
||||
ok = pthread_mutex_destroy(&(mutex->mutex));
|
||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, mutex_destroy, mutex);
|
||||
}
|
||||
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_lock_take_try(Eina_Lock *mutex)
|
||||
_eina_lock_take_try(Eina_Lock *mutex)
|
||||
{
|
||||
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
||||
int ok;
|
||||
|
@ -240,7 +239,7 @@ eina_lock_take_try(Eina_Lock *mutex)
|
|||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_lock_take(Eina_Lock *mutex)
|
||||
_eina_lock_take(Eina_Lock *mutex)
|
||||
{
|
||||
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
||||
int ok;
|
||||
|
@ -313,7 +312,7 @@ eina_lock_take(Eina_Lock *mutex)
|
|||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_lock_release(Eina_Lock *mutex)
|
||||
_eina_lock_release(Eina_Lock *mutex)
|
||||
{
|
||||
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
||||
int ok;
|
||||
|
@ -347,19 +346,59 @@ eina_lock_release(Eina_Lock *mutex)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||
_eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||
{
|
||||
return _eina_condition_new(cond, mutex);
|
||||
pthread_condattr_t attr;
|
||||
int ok;
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
assert(mutex != NULL);
|
||||
#endif
|
||||
|
||||
cond->lock = mutex;
|
||||
pthread_condattr_init(&attr);
|
||||
|
||||
/* OSX doesn't provide clockid_t or clock_gettime. */
|
||||
#if defined(__clockid_t_defined)
|
||||
cond->clkid = (clockid_t) 0;
|
||||
/* We try here to chose the best clock for cond_timedwait */
|
||||
# if defined(CLOCK_MONOTONIC_RAW)
|
||||
if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC_RAW))
|
||||
cond->clkid = CLOCK_MONOTONIC_RAW;
|
||||
# endif
|
||||
# if defined(CLOCK_MONOTONIC)
|
||||
if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
|
||||
cond->clkid = CLOCK_MONOTONIC;
|
||||
# endif
|
||||
# if defined(CLOCK_REALTIME)
|
||||
if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_REALTIME))
|
||||
cond->clkid = CLOCK_REALTIME;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
ok = pthread_cond_init(&cond->condition, &attr);
|
||||
if (ok != 0)
|
||||
{
|
||||
pthread_condattr_destroy(&attr);
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (ok == EBUSY)
|
||||
fprintf(stderr, "EINA ERROR: eina_condition_new on already initialized Eina_Condition\n");
|
||||
#endif
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
pthread_condattr_destroy(&attr);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_condition_free(Eina_Condition *cond)
|
||||
_eina_condition_free(Eina_Condition *cond)
|
||||
{
|
||||
_eina_condition_free(cond);
|
||||
pthread_cond_destroy(&(cond->condition));
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_wait(Eina_Condition *cond)
|
||||
_eina_condition_wait(Eina_Condition *cond)
|
||||
{
|
||||
Eina_Bool r = EINA_FALSE;
|
||||
int ok;
|
||||
|
@ -390,7 +429,7 @@ eina_condition_wait(Eina_Condition *cond)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_timedwait(Eina_Condition *cond, double t)
|
||||
_eina_condition_timedwait(Eina_Condition *cond, double t)
|
||||
{
|
||||
struct timespec ts;
|
||||
time_t sec;
|
||||
|
@ -456,7 +495,7 @@ eina_condition_timedwait(Eina_Condition *cond, double t)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_broadcast(Eina_Condition *cond)
|
||||
_eina_condition_broadcast(Eina_Condition *cond)
|
||||
{
|
||||
int ok;
|
||||
|
||||
|
@ -472,7 +511,7 @@ eina_condition_broadcast(Eina_Condition *cond)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_signal(Eina_Condition *cond)
|
||||
_eina_condition_signal(Eina_Condition *cond)
|
||||
{
|
||||
int ok;
|
||||
|
||||
|
@ -488,19 +527,25 @@ eina_condition_signal(Eina_Condition *cond)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_rwlock_new(Eina_RWLock *mutex)
|
||||
_eina_rwlock_new(Eina_RWLock *mutex)
|
||||
{
|
||||
return _eina_rwlock_new(mutex);
|
||||
int ok;
|
||||
|
||||
ok = pthread_rwlock_init(&(mutex->mutex), NULL);
|
||||
if (ok == 0) return EINA_TRUE;
|
||||
else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, rwlock_init, mutex);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_rwlock_free(Eina_RWLock *mutex)
|
||||
_eina_rwlock_free(Eina_RWLock *mutex)
|
||||
{
|
||||
_eina_rwlock_free(mutex);
|
||||
pthread_rwlock_destroy(&(mutex->mutex));
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_rwlock_take_read(Eina_RWLock *mutex)
|
||||
_eina_rwlock_take_read(Eina_RWLock *mutex)
|
||||
{
|
||||
int ok;
|
||||
|
||||
|
@ -520,7 +565,7 @@ eina_rwlock_take_read(Eina_RWLock *mutex)
|
|||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_rwlock_take_write(Eina_RWLock *mutex)
|
||||
_eina_rwlock_take_write(Eina_RWLock *mutex)
|
||||
{
|
||||
int ok;
|
||||
|
||||
|
@ -540,7 +585,7 @@ eina_rwlock_take_write(Eina_RWLock *mutex)
|
|||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_rwlock_release(Eina_RWLock *mutex)
|
||||
_eina_rwlock_release(Eina_RWLock *mutex)
|
||||
{
|
||||
int ok;
|
||||
|
||||
|
@ -559,92 +604,167 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
_eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
{
|
||||
if (pthread_key_create(key, delete_cb) == 0) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
{
|
||||
return eina_tls_cb_new(key, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_tls_free(Eina_TLS key)
|
||||
_eina_tls_free(Eina_TLS key)
|
||||
{
|
||||
pthread_key_delete(key);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
eina_tls_get(Eina_TLS key)
|
||||
_eina_tls_get(Eina_TLS key)
|
||||
{
|
||||
return pthread_getspecific(key);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_set(Eina_TLS key, const void *data)
|
||||
_eina_tls_set(Eina_TLS key, const void *data)
|
||||
{
|
||||
if (pthread_setspecific(key, data) == 0) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
||||
typedef struct _Eina_Barrier Eina_Barrier;
|
||||
|
||||
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
||||
struct _Eina_Barrier
|
||||
{
|
||||
pthread_barrier_t barrier;
|
||||
};
|
||||
#else
|
||||
struct _Eina_Barrier
|
||||
{
|
||||
int needed; /**< The number of waiting threads that will cause the barrier to signal and reset. */
|
||||
int called; /**< The number of threads that are waiting on this barrier. */
|
||||
Eina_Lock cond_lock; /**< The lock for the barrier */
|
||||
Eina_Condition cond; /**< The condition variable for the barrier */
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_barrier_wait(Eina_Barrier *barrier)
|
||||
_eina_barrier_new(Eina_Barrier *barrier, int needed)
|
||||
{
|
||||
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
||||
int ok = pthread_barrier_init(&(barrier->barrier), NULL, needed);
|
||||
if (ok == 0) return EINA_TRUE;
|
||||
else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, barrier_init, barrier);
|
||||
return EINA_FALSE;
|
||||
#else
|
||||
barrier->needed = needed;
|
||||
barrier->called = 0;
|
||||
if (eina_lock_new(&(barrier->cond_lock)))
|
||||
{
|
||||
if (eina_condition_new(&(barrier->cond), &(barrier->cond_lock)))
|
||||
return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_barrier_free(Eina_Barrier *barrier)
|
||||
{
|
||||
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
||||
int ok = pthread_barrier_destroy(&(barrier->barrier));
|
||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, barrier_destroy, barrier);
|
||||
#else
|
||||
eina_condition_free(&(barrier->cond));
|
||||
eina_lock_free(&(barrier->cond_lock));
|
||||
barrier->needed = 0;
|
||||
barrier->called = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_barrier_wait(Eina_Barrier *barrier)
|
||||
{
|
||||
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
||||
int ok = pthread_barrier_wait(&(barrier->barrier));
|
||||
if (ok == 0) return EINA_TRUE;
|
||||
else if (ok == PTHREAD_BARRIER_SERIAL_THREAD) return EINA_TRUE;
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, barrier_wait, barrier);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
#else
|
||||
#include "eina_inline_lock_barrier.x"
|
||||
eina_lock_take(&(barrier->cond_lock));
|
||||
barrier->called++;
|
||||
if (barrier->called == barrier->needed)
|
||||
{
|
||||
barrier->called = 0;
|
||||
eina_condition_broadcast(&(barrier->cond));
|
||||
}
|
||||
else
|
||||
eina_condition_wait(&(barrier->cond));
|
||||
eina_lock_release(&(barrier->cond_lock));
|
||||
return EINA_TRUE;
|
||||
|
||||
#endif
|
||||
|
||||
EAPI Eina_Bool _eina_barrier_new(Eina_Barrier *barrier, int needed);
|
||||
EAPI void _eina_barrier_free(Eina_Barrier *barrier);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_barrier_new(Eina_Barrier *barrier, int needed)
|
||||
_eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return _eina_barrier_new(barrier, needed);
|
||||
#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
|
||||
int ok = pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE);
|
||||
if (ok == 0) return EINA_TRUE;
|
||||
else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, spin_init, spinlock);
|
||||
return EINA_FALSE;
|
||||
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
||||
*spinlock = 0;
|
||||
return EINA_TRUE;
|
||||
#else
|
||||
return eina_lock_new(spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_barrier_free(Eina_Barrier *barrier)
|
||||
_eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||
{
|
||||
_eina_barrier_free(barrier);
|
||||
#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
|
||||
int ok = pthread_spin_destroy(spinlock);
|
||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, spin_destroy, spinlock);
|
||||
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
||||
/* Not applicable */
|
||||
(void) spinlock;
|
||||
#else
|
||||
eina_lock_free(spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||
#ifdef EINA_HAVE_OSX_SPINLOCK
|
||||
static inline Eina_Lock_Result
|
||||
_eina_spinlock_macos_take(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return _eina_spinlock_new(spinlock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||
{
|
||||
_eina_spinlock_free(spinlock);
|
||||
os_unfair_lock_lock(SPINLOCK_GET(spinlock));
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
||||
_eina_spinlock_macos_take_try(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||
return (os_unfair_lock_trylock(SPINLOCK_GET(spinlock)) == true)
|
||||
? EINA_LOCK_SUCCEED
|
||||
: EINA_LOCK_FAIL;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_spinlock_macos_release(Eina_Spinlock *spinlock)
|
||||
{
|
||||
os_unfair_lock_unlock(SPINLOCK_GET(spinlock));
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
#endif /* EINA_HAVE_OSX_SPINLOCK */
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
|
||||
int t = pthread_spin_trylock(spinlock);
|
||||
if (t == 0) return EINA_LOCK_SUCCEED;
|
||||
else if (t == EBUSY) return EINA_LOCK_FAIL;
|
||||
|
@ -658,9 +778,9 @@ eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
|||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_spinlock_take(Eina_Spinlock *spinlock)
|
||||
_eina_spinlock_take(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||
#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
|
||||
int t;
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
|
@ -683,9 +803,9 @@ eina_spinlock_take(Eina_Spinlock *spinlock)
|
|||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_spinlock_release(Eina_Spinlock *spinlock)
|
||||
_eina_spinlock_release(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||
#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
|
||||
int ok = pthread_spin_unlock(spinlock);
|
||||
if (ok == 0) return EINA_LOCK_SUCCEED;
|
||||
else if (ok == EPERM) return EINA_LOCK_FAIL;
|
||||
|
@ -699,19 +819,37 @@ eina_spinlock_release(Eina_Spinlock *spinlock)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
||||
_eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
||||
{
|
||||
return _eina_semaphore_new(sem, count_init);
|
||||
if (sem && (count_init >= 0))
|
||||
{
|
||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||
kern_return_t kr = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, count_init);
|
||||
return (kr == KERN_SUCCESS) ? EINA_TRUE : EINA_FALSE;
|
||||
#else
|
||||
return (sem_init(sem, 0, count_init) == 0) ? EINA_TRUE : EINA_FALSE;
|
||||
#endif
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_free(Eina_Semaphore *sem)
|
||||
_eina_semaphore_free(Eina_Semaphore *sem)
|
||||
{
|
||||
return _eina_semaphore_free(sem);
|
||||
if (sem)
|
||||
{
|
||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||
return (semaphore_destroy(mach_task_self(), *sem) == KERN_SUCCESS)
|
||||
? EINA_TRUE : EINA_FALSE;
|
||||
#else
|
||||
return (sem_destroy(sem) == 0) ? EINA_TRUE : EINA_FALSE;
|
||||
#endif
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_lock(Eina_Semaphore *sem)
|
||||
_eina_semaphore_lock(Eina_Semaphore *sem)
|
||||
{
|
||||
if (sem)
|
||||
{
|
||||
|
@ -735,7 +873,7 @@ err:
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
|
||||
_eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
|
||||
{
|
||||
if (sem)
|
||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||
|
|
|
@ -0,0 +1,747 @@
|
|||
/* EINA - EFL data type library
|
||||
* Copyright (C) 2020 Lucas Cavalcante de Sousa
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library;
|
||||
* if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EINA_INLINE_LOCK_WIN32_X_
|
||||
#define EINA_INLINE_LOCK_WIN32_X_
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <Windows.h>
|
||||
#include <synchapi.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include "unimplemented.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
#include <assert.h>
|
||||
#include <execinfo.h>
|
||||
#define EINA_LOCK_DEBUG_BT_NUM 64
|
||||
typedef void (*Eina_Lock_Bt_Func) ();
|
||||
|
||||
#include "eina_inlist.h"
|
||||
#endif
|
||||
|
||||
EAPI void _eina_lock_debug_abort(int err, const char *fn, const volatile void *ptr);
|
||||
EAPI void _eina_lock_debug_deadlock(const char *fn, const volatile void *ptr);
|
||||
|
||||
#define EINA_LOCK_ABORT_DEBUG(err, fn, ptr) \
|
||||
_eina_lock_debug_abort(err, #fn, ptr)
|
||||
#define EINA_LOCK_DEADLOCK_DEBUG(fn, ptr) \
|
||||
_eina_lock_debug_deadlock(#fn, ptr)
|
||||
|
||||
/* For cond_timedwait */
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <eina_error.h>
|
||||
|
||||
typedef struct _Eina_Lock Eina_Lock;
|
||||
typedef struct _Eina_RWLock Eina_RWLock;
|
||||
typedef struct _Eina_Condition Eina_Condition;
|
||||
typedef struct _Eina_Barrier Eina_Barrier;
|
||||
typedef LPDWORD Eina_TLS;
|
||||
typedef HANDLE Eina_Semaphore;
|
||||
|
||||
#ifdef EINA_HAVE_WIN32_SPINLOCK
|
||||
typedef PCRITICAL_SECTION Eina_Spinlock;
|
||||
#else
|
||||
typedef Eina_Lock Eina_Spinlock;
|
||||
#endif
|
||||
|
||||
EAPI void eina_lock_debug(const Eina_Lock *mutex);
|
||||
|
||||
/** @privatesection @{ */
|
||||
typedef HANDLE _Eina_Thread;
|
||||
typedef PCRITICAL_SECTION _Eina_Mutex_t;
|
||||
typedef CONDITION_VARIABLE _Eina_Condition_t;
|
||||
typedef PSRWLOCK _Eina_RWLock_t;
|
||||
|
||||
struct _Eina_Lock
|
||||
{
|
||||
_Eina_Mutex_t mutex; /**< The mutex that handles the locking */
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
EINA_INLIST; /**< Keeps track of the threads waiting for the lock */
|
||||
_Eina_Thread lock_thread_id; /**< The ID of the thread that currently has the lock */
|
||||
Eina_Lock_Bt_Func lock_bt[EINA_LOCK_DEBUG_BT_NUM]; /**< The function that will produce a backtrace on the thread that has the lock */
|
||||
int lock_bt_num; /**< Number of addresses in the backtrace */
|
||||
Eina_Bool locked : 1; /**< Indicates locked or not locked */
|
||||
Eina_Bool recursive : 1; /**< Indicates recursive lock */
|
||||
#endif /* EINA_HAVE_DEBUG_THREADS */
|
||||
};
|
||||
|
||||
struct _Eina_Condition
|
||||
{
|
||||
Eina_Lock *lock; /**< The lock for this condition */
|
||||
_Eina_Condition_t condition; /**< The condition variable */
|
||||
#if defined(__clockid_t_defined)
|
||||
clockid_t clkid; /**< The attached clock for timedwait */
|
||||
#endif
|
||||
};
|
||||
|
||||
enum _Eina_RWLock_Mode {
|
||||
_Eina_RWLock_Mode_Shared,
|
||||
_Eina_RWLock_Mode_Exclusive,
|
||||
_Eina_RWLock_Mode_None
|
||||
};
|
||||
|
||||
struct _Eina_RWLock
|
||||
{
|
||||
_Eina_RWLock_t mutex; /**< The mutex that handles the locking */
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
_Eina_Thread lock_thread_wid; /**< The ID of the thread that currently has the lock */
|
||||
#endif
|
||||
enum _Eina_RWLock_Mode mode; /**< The mode the SRWLock is (Shared, Exclusive or None)*/
|
||||
};
|
||||
/** @} privatesection */
|
||||
|
||||
EAPI extern Eina_Bool _eina_threads_activated;
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
EAPI extern int _eina_threads_debug;
|
||||
EAPI extern _Eina_Thread _eina_main_loop;
|
||||
EAPI extern Eina_Lock _eina_tracking_lock;
|
||||
EAPI extern Eina_Inlist *_eina_tracking;
|
||||
#endif
|
||||
|
||||
EAPI Eina_Bool eina_lock_new(Eina_Lock *mutex);
|
||||
EAPI void eina_lock_free(Eina_Lock *mutex);
|
||||
EAPI Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
|
||||
EAPI Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
|
||||
EAPI Eina_Lock_Result eina_lock_release(Eina_Lock *mutex);
|
||||
EAPI Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
|
||||
EAPI void eina_condition_free(Eina_Condition *cond);
|
||||
EAPI Eina_Bool eina_condition_wait(Eina_Condition *cond);
|
||||
EAPI Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive)
|
||||
{
|
||||
InitializeCriticalSection((mutex->mutex));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_lock_free(Eina_Lock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (mutex->locked)
|
||||
{
|
||||
EnterCriticalSection(_eina_tracking_lock);
|
||||
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
||||
EINA_INLIST_GET(mutex));
|
||||
LeaveCriticalSection(_eina_tracking_lock);
|
||||
}
|
||||
#endif
|
||||
DWORD ok;
|
||||
|
||||
DeleteCriticalSection((mutex->mutex));
|
||||
ok = GetLastError();
|
||||
if (ok != ERROR_SUCCESS) EINA_LOCK_ABORT_DEBUG((int)ok, mutex_destroy
|
||||
, mutex);
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_lock_take_try(Eina_Lock *mutex)
|
||||
{
|
||||
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
||||
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
int ok = TryEnterCriticalSection((mutex->mutex));
|
||||
DWORD err = GetLastError();
|
||||
if (ok != 0) ret = EINA_LOCK_SUCCEED;
|
||||
else if (err == ERROR_POSSIBLE_DEADLOCK)
|
||||
{
|
||||
eina_lock_debug(mutex);
|
||||
ret = EINA_LOCK_DEADLOCK;
|
||||
}
|
||||
else if (err != ERROR_TIMEOUT) EINA_LOCK_ABORT_DEBUG((int)err, trylock, mutex);
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (ret == EINA_LOCK_SUCCEED)
|
||||
{
|
||||
/* recursive locks can't make use of any of this */
|
||||
if (mutex->recursive) return ret;
|
||||
mutex->locked = 1;
|
||||
mutex->lock_thread_id = GetCurrentThreadId();
|
||||
/* backtrace() can somehow generate EINVAL even though this is not documented anywhere? */
|
||||
int err = errno;
|
||||
mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
|
||||
errno = err;
|
||||
|
||||
EnterCriticalSection(_eina_tracking_lock);
|
||||
_eina_tracking = eina_inlist_append(_eina_tracking,
|
||||
EINA_INLIST_GET(mutex));
|
||||
LeaveCriticalSection(_eina_tracking_lock);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_lock_take(Eina_Lock *mutex)
|
||||
{
|
||||
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
||||
DWORD ok;
|
||||
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (eina_lock_take_try(mutex) == EINA_LOCK_SUCCEED) return EINA_LOCK_SUCCEED;
|
||||
|
||||
if (_eina_threads_debug >= 100)
|
||||
{
|
||||
struct timeval t0, t1;
|
||||
int dt;
|
||||
|
||||
gettimeofday(&t0, NULL);
|
||||
ok = EnterCriticalSection((mutex->mutex));
|
||||
gettimeofday(&t1, NULL);
|
||||
|
||||
dt = (t1.tv_sec - t0.tv_sec) * 1000000;
|
||||
if (t1.tv_usec > t0.tv_usec) dt += (t1.tv_usec - t0.tv_usec);
|
||||
else dt -= t0.tv_usec - t1.tv_usec;
|
||||
if (dt > _eina_threads_debug) abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
EnterCriticalSection((mutex->mutex));
|
||||
ok = GetLastError();
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ok == ERROR_SUCCESS) ret = EINA_LOCK_SUCCEED;
|
||||
else if (ok == ERROR_POSSIBLE_DEADLOCK)
|
||||
{
|
||||
eina_lock_debug(mutex);
|
||||
ret = EINA_LOCK_DEADLOCK;
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (_eina_threads_debug) abort();
|
||||
#endif
|
||||
}
|
||||
else if (ok != ERROR_TIMEOUT) EINA_LOCK_ABORT_DEBUG((int)ok, lock, mutex);
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
/* recursive locks can't make use of any of this */
|
||||
if (mutex->recursive) return ret;
|
||||
mutex->locked = 1;
|
||||
mutex->lock_thread_id = GetCurrentThreadId();
|
||||
/* backtrace() can somehow generate EINVAL even though this is not documented anywhere? */
|
||||
int err = errno;
|
||||
mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
|
||||
errno = err;
|
||||
|
||||
EnterCriticalSection(_eina_tracking_lock);
|
||||
_eina_tracking = eina_inlist_append(_eina_tracking,
|
||||
EINA_INLIST_GET(mutex));
|
||||
LeaveCriticalSection(_eina_tracking_lock);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_lock_release(Eina_Lock *mutex)
|
||||
{
|
||||
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
||||
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
/* recursive locks can't make use of any of this */
|
||||
if (!mutex->recursive)
|
||||
{
|
||||
mutex->locked = 0;
|
||||
mutex->lock_thread_id = 0;
|
||||
memset(mutex->lock_bt, 0, EINA_LOCK_DEBUG_BT_NUM * sizeof(Eina_Lock_Bt_Func));
|
||||
mutex->lock_bt_num = 0;
|
||||
EnterCriticalSection(_eina_tracking_lock);
|
||||
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
||||
EINA_INLIST_GET(mutex));
|
||||
LeaveCriticalSection(_eina_tracking_lock);
|
||||
}
|
||||
#endif
|
||||
LeaveCriticalSection((mutex->mutex));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) ret = EINA_LOCK_SUCCEED;
|
||||
else if (ok != ERROR_ACCESS_DENIED) ret = EINA_LOCK_FAIL;
|
||||
else EINA_LOCK_ABORT_DEBUG((int)ok, unlock, mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED static inline Eina_Bool
|
||||
_eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||
{
|
||||
// TODO
|
||||
#warning eina_condition_new is not implemented
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_condition_free(Eina_Condition *cond)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_condition_wait(Eina_Condition *cond)
|
||||
{
|
||||
Eina_Bool r = EINA_FALSE;
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
assert(_eina_threads_activated);
|
||||
assert(cond->lock != NULL);
|
||||
|
||||
EnterCriticalSection(_eina_tracking_lock);
|
||||
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
||||
EINA_INLIST_GET(cond->lock));
|
||||
LeaveCriticalSection(_eina_tracking_lock);
|
||||
#endif
|
||||
|
||||
int ok = SleepConditionVariableCS(&(cond->condition)
|
||||
, (cond->lock->mutex), INFINITE);
|
||||
DWORD err = GetLastError();
|
||||
if (ok != 0) r = EINA_TRUE;
|
||||
else if (err != ERROR_ACCESS_DENIED) r = EINA_FALSE;
|
||||
else EINA_LOCK_ABORT_DEBUG((int)ok, cond_wait, cond);
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
EnterCriticalSection(_eina_tracking_lock);
|
||||
_eina_tracking = eina_inlist_append(_eina_tracking
|
||||
, EINA_INLIST_GET(cond->lock));
|
||||
LeaveCriticalSection(_eina_tracking_lock);
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED static inline Eina_Bool
|
||||
_eina_condition_timedwait(Eina_Condition *cond, double t)
|
||||
{
|
||||
//** TODO **//
|
||||
#warning eina_condition_timedwait is not implemented
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_condition_broadcast(Eina_Condition *cond)
|
||||
{
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
assert(cond->lock != NULL);
|
||||
#endif
|
||||
|
||||
WakeAllConditionVariable(&(cond->condition));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
|
||||
EINA_LOCK_ABORT_DEBUG((int)ok, cond_broadcast, cond);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_condition_signal(Eina_Condition *cond)
|
||||
{
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
assert(cond->lock != NULL);
|
||||
#endif
|
||||
|
||||
WakeConditionVariable(&(cond->condition));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
|
||||
EINA_LOCK_ABORT_DEBUG((int)ok, cond_signal, cond);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_rwlock_new(Eina_RWLock *mutex)
|
||||
{
|
||||
InitializeSRWLock((mutex->mutex));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
else if ((ok == ERROR_NOT_ENOUGH_MEMORY) || (ok == ERROR_ACCESS_DENIED)
|
||||
|| (ok == ERROR_OUTOFMEMORY))
|
||||
{
|
||||
return EINA_FALSE;
|
||||
}
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, rwlock_init, mutex);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_rwlock_free(Eina_RWLock *mutex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_rwlock_take_read(Eina_RWLock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
AcquireSRWLockShared((mutex->mutex));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS)
|
||||
{
|
||||
mutex->mode = _Eina_RWLock_Mode_Shared;
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
else if (ok == ERROR_NOT_ENOUGH_MEMORY || ok == ERROR_OUTOFMEMORY)
|
||||
{
|
||||
return EINA_LOCK_FAIL;
|
||||
}
|
||||
else if (ok == ERROR_POSSIBLE_DEADLOCK)
|
||||
{
|
||||
EINA_LOCK_DEADLOCK_DEBUG(rwlock_rdlock, mutex);
|
||||
}
|
||||
else EINA_LOCK_ABORT_DEBUG((int)ok, rwlock_rdlock, mutex);
|
||||
return EINA_LOCK_FAIL;
|
||||
}
|
||||
static inline Eina_Lock_Result
|
||||
_eina_rwlock_take_write(Eina_RWLock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
AcquireSRWLockExclusive((mutex->mutex));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS)
|
||||
{
|
||||
mutex->mode = _Eina_RWLock_Mode_Exclusive;
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
else if (ok == ERROR_NOT_ENOUGH_MEMORY || ok == ERROR_OUTOFMEMORY)
|
||||
{
|
||||
return EINA_LOCK_FAIL;
|
||||
}
|
||||
else if (ok == ERROR_POSSIBLE_DEADLOCK)
|
||||
{
|
||||
EINA_LOCK_DEADLOCK_DEBUG(rwlock_rdlock, mutex);
|
||||
}
|
||||
else EINA_LOCK_ABORT_DEBUG((int)ok, rwlock_rdlock, mutex);
|
||||
return EINA_LOCK_FAIL;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_rwlock_release(Eina_RWLock *mutex)
|
||||
{
|
||||
DWORD ok;
|
||||
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
if (mutex->mode == _Eina_RWLock_Mode_Exclusive)
|
||||
{
|
||||
mutex->mode = _Eina_RWLock_Mode_None;
|
||||
ReleaseSRWLockExclusive((mutex->mutex));
|
||||
ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
|
||||
mutex->mode = _Eina_RWLock_Mode_Exclusive;
|
||||
}
|
||||
else if (mutex->mode == _Eina_RWLock_Mode_Shared)
|
||||
{
|
||||
mutex->mode = _Eina_RWLock_Mode_None;
|
||||
ReleaseSRWLockShared((mutex->mutex));
|
||||
ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
|
||||
mutex->mode = _Eina_RWLock_Mode_Shared;
|
||||
}
|
||||
if (ok == ERROR_ACCESS_DENIED) return EINA_LOCK_FAIL;
|
||||
|
||||
EINA_LOCK_ABORT_DEBUG((int)ok, rwlock_unlock, mutex);
|
||||
return EINA_LOCK_FAIL;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
{
|
||||
* key = TlsAlloc();
|
||||
DWORD ok = GetLastError();
|
||||
if (key != TLS_OUT_OF_INDEXES || ok != ERROR_SUCCESS) return EINA_TRUE;
|
||||
else return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_tls_free(Eina_TLS key)
|
||||
{
|
||||
TlsFree(key);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
_eina_tls_get(Eina_TLS key)
|
||||
{
|
||||
return TlsGetValue(key);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_tls_set(Eina_TLS key, const void *data)
|
||||
{
|
||||
int ok = TlsSetValue(key, (void *) data);
|
||||
DWORD err = GetLastError();
|
||||
if (ok != 0 && err == ERROR_SUCCESS) return EINA_TRUE;
|
||||
else return EINA_TRUE;
|
||||
}
|
||||
|
||||
#ifdef EINA_HAVE_WIN32_BARRIER
|
||||
struct _Eina_Barrier
|
||||
{
|
||||
LPSYNCHRONIZATION_BARRIER barrier;
|
||||
};
|
||||
#else
|
||||
struct _Eina_Barrier
|
||||
{
|
||||
int needed; /**< The number of waiting threads that will cause the barrier to signal and reset. */
|
||||
int called; /**< The number of threads that are waiting on this barrier. */
|
||||
Eina_Lock cond_lock; /**< The lock for the barrier */
|
||||
Eina_Condition cond; /**< The condition variable for the barrier */
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_barrier_new(Eina_Barrier *barrier, int needed)
|
||||
{
|
||||
#ifdef EINA_HAVE_WIN32_BARRIER
|
||||
InitializeSynchronizationBarrier(&(barrier->barrier), (LONG) needed, 0);
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
else if ((ok == ERROR_NOT_ENOUGH_MEMORY) || (ok == ERROR_ACCESS_DENIED)
|
||||
|| (ok == ERROR_OUTOFMEMORY))
|
||||
{
|
||||
return EINA_FALSE;
|
||||
}
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, barrier_init, barrier);
|
||||
return EINA_FALSE;
|
||||
#else
|
||||
barrier->needed = needed;
|
||||
barrier->called = 0;
|
||||
if (eina_lock_new(&(barrier->cond_lock)))
|
||||
{
|
||||
if (eina_condition_new(&(barrier->cond), &(barrier->cond_lock)))
|
||||
return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_barrier_free(Eina_Barrier *barrier)
|
||||
{
|
||||
#ifdef EINA_HAVE_WIN32_BARRIER
|
||||
DeleteSynchronizationBarrier(&(barrier->barrier));
|
||||
DWORD ok = GetLastError();
|
||||
if (ok != ERROR_SUCCESS) EINA_LOCK_ABORT_DEBUG(ok, barrier_destroy, barrier);
|
||||
#else
|
||||
eina_condition_free(&(barrier->cond));
|
||||
eina_lock_free(&(barrier->cond_lock));
|
||||
barrier->needed = 0;
|
||||
barrier->called = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_barrier_wait(Eina_Barrier *barrier)
|
||||
{
|
||||
#ifdef EINA_HAVE_WIN32_BARRIER
|
||||
EnterSyncronizationBarrier(&(barrier->barrier)
|
||||
, SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
else EINA_LOCK_ABORT_DEBUG((int)ok, barrier_wait, barrier);
|
||||
return EINA_TRUE;
|
||||
#else
|
||||
eina_lock_take(&(barrier->cond_lock));
|
||||
barrier->called++;
|
||||
if (barrier->called == barrier->needed)
|
||||
{
|
||||
barrier->called = 0;
|
||||
eina_condition_broadcast(&(barrier->cond));
|
||||
}
|
||||
else eina_condition_wait(&(barrier->cond));
|
||||
eina_lock_release(&(barrier->cond_lock));
|
||||
return EINA_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#ifdef EINA_HAVE_WIN32_SPINLOCK
|
||||
int ok = InitializeCriticalSectionAndSpinCount(spinlock, INFINITE);
|
||||
DWORD err = GetLastError();
|
||||
if (ok != 0) return EINA_TRUE;
|
||||
else if ((err == ERROR_NOT_ENOUGH_MEMORY) || (err == ERROR_ACCESS_DENIED)
|
||||
|| (err == ERROR_OUTOFMEMORY))
|
||||
{
|
||||
return EINA_FALSE;
|
||||
}
|
||||
else EINA_LOCK_ABORT_DEBUG((int)err, spin_init, spinlock);
|
||||
return EINA_FALSE;
|
||||
#else
|
||||
return eina_lock_new(spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#ifdef EINA_HAVE_WIN32_SPINLOCK
|
||||
DeleteCriticalSection(spinlock);
|
||||
DWORD ok = GetLastError();
|
||||
if (ok != ERROR_SUCCESS) EINA_LOCK_ABORT_DEBUG(ok, spin_destroy, spinlock);
|
||||
#else
|
||||
eina_lock_free(spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#ifdef EINA_HAVE_WIN32_SPINLOCK
|
||||
int ok = TryEnterCriticalSection(spinlock);
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
|
||||
else if (ok == 0 || err == ERROR_TIMEOUT) EINA_LOCK_FAIL;
|
||||
else EINA_LOCK_ABORT_DEBUG((int)err, trylock, mutex);
|
||||
return EINA_LOCK_FAIL
|
||||
#else
|
||||
return eina_lock_take_try(spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_spinlock_take(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#ifdef EINA_HAVE_WIN32_SPINLOCK
|
||||
# ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (eina_spinlock_take_try(spinlock) == EINA_LOCK_SUCCEED)
|
||||
return EINA_LOCK_SUCCEED;
|
||||
# endif
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int ok = EnterCriticalSection(spinlock);
|
||||
if (ok != 0) break;
|
||||
else {
|
||||
DWORD err = GetLastError();
|
||||
EINA_LOCK_ABORT_DEBUG((int)err, spin_lock, spinlock);
|
||||
}
|
||||
}
|
||||
|
||||
return EINA_LOCK_SUCCEED;
|
||||
#else
|
||||
return eina_lock_take(spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
_eina_spinlock_release(Eina_Spinlock *spinlock)
|
||||
{
|
||||
#if defined(EINA_HAVE_WIN32_SPINLOCK)
|
||||
LeaveCriticalSection(spinlock);
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
|
||||
else if (ok == ERROR_ACCESS_DENIED) return EINA_LOCK_FAIL;
|
||||
else EINA_LOCK_ABORT_DEBUG((int)ok, spin_unlock, spinlock);
|
||||
return EINA_LOCK_FAIL;
|
||||
#else
|
||||
return eina_lock_release(spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
||||
{
|
||||
if (sem && (count_init >= 0))
|
||||
{
|
||||
sem = CreateSemaphoreA(NULL, count_init, count_init, NULL);
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_semaphore_free(Eina_Semaphore *sem)
|
||||
{
|
||||
if (sem)
|
||||
{
|
||||
CloseHandle(sem);
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS) return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_semaphore_lock(Eina_Semaphore *sem)
|
||||
{
|
||||
if (sem)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
WaitForSingleObject(sem, INFINITE);
|
||||
DWORD ok = GetLastError();
|
||||
if (ok == ERROR_SUCCESS)
|
||||
return EINA_TRUE;
|
||||
else if (ok == WAIT_OBJECT_0 || ok == WAIT_TIMEOUT)
|
||||
continue;
|
||||
else if (errno == ERROR_POSSIBLE_DEADLOCK)
|
||||
{
|
||||
EINA_LOCK_DEADLOCK_DEBUG(sem_wait, sem);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
|
||||
{
|
||||
if (sem)
|
||||
return (ReleaseSemaphore(sem, 1, NULL) != 0) ? EINA_TRUE : EINA_FALSE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -7,51 +7,6 @@
|
|||
#include "eina_config.h"
|
||||
#include "Eina.h"
|
||||
|
||||
#ifdef EINA_HAVE_OSX_SPINLOCK
|
||||
|
||||
/*
|
||||
* macOS 10.12 introduced the os_unfair_lock API which
|
||||
* deprecates OSSpinLock, while keeping compatible.
|
||||
*
|
||||
* The Spinlock API is not inlined because it would imply including
|
||||
* stdbool.h, which is not wanted: it would introduce new macros,
|
||||
* and break compilation of existing programs.
|
||||
*/
|
||||
# if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
||||
# include <os/lock.h>
|
||||
# define SPINLOCK_GET(LCK) ((os_unfair_lock_t)(LCK))
|
||||
# else
|
||||
# include <libkern/OSAtomic.h>
|
||||
# define SPINLOCK_GET(LCK) ((OSSpinLock *)(LCK))
|
||||
# define os_unfair_lock_lock(LCK) OSSpinLockLock(LCK)
|
||||
# define os_unfair_lock_unlock(LCK) OSSpinLockUnlock(LCK)
|
||||
# define os_unfair_lock_trylock(LCK) OSSpinLockTry(LCK)
|
||||
# endif
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
_eina_spinlock_macos_take(Eina_Spinlock *spinlock)
|
||||
{
|
||||
os_unfair_lock_lock(SPINLOCK_GET(spinlock));
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
_eina_spinlock_macos_take_try(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return (os_unfair_lock_trylock(SPINLOCK_GET(spinlock)) == true)
|
||||
? EINA_LOCK_SUCCEED
|
||||
: EINA_LOCK_FAIL;
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
_eina_spinlock_macos_release(Eina_Spinlock *spinlock)
|
||||
{
|
||||
os_unfair_lock_unlock(SPINLOCK_GET(spinlock));
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
#endif /* EINA_HAVE_OSX_SPINLOCK */
|
||||
|
||||
|
||||
Eina_Bool fork_resetting;
|
||||
|
||||
EAPI void
|
||||
|
@ -85,198 +40,220 @@ eina_lock_debug(const Eina_Lock *mutex)
|
|||
#endif
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive)
|
||||
EAPI Eina_Bool eina_lock_new(Eina_Lock *mutex)
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
Eina_Bool ok = EINA_FALSE;
|
||||
|
||||
if (pthread_mutexattr_init(&attr) != 0) return EINA_FALSE;
|
||||
if (recursive)
|
||||
{
|
||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) goto fail_release;
|
||||
}
|
||||
Eina_Bool ret = _eina_lock_new(mutex, EINA_FALSE);
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
else if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) goto fail_release;
|
||||
mutex->recursive = EINA_FALSE;
|
||||
mutex->lock_thread_id = 0;
|
||||
mutex->lock_bt_num = 0;
|
||||
mutex->locked = 0;
|
||||
#endif
|
||||
if (pthread_mutex_init(&(mutex->mutex), &attr) != 0) goto fail_release;
|
||||
ok = EINA_TRUE;
|
||||
fail_release:
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
return ok;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
_eina_lock_free(Eina_Lock *mutex)
|
||||
{
|
||||
int ok;
|
||||
|
||||
ok = pthread_mutex_destroy(&(mutex->mutex));
|
||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, mutex_destroy, mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||
eina_lock_recursive_new(Eina_Lock *mutex)
|
||||
{
|
||||
pthread_condattr_t attr;
|
||||
int ok;
|
||||
|
||||
Eina_Bool ret = _eina_lock_new(mutex, EINA_TRUE);
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
assert(mutex != NULL);
|
||||
mutex->recursive = EINA_TRUE;
|
||||
mutex->lock_thread_id = 0;
|
||||
mutex->lock_bt_num = 0;
|
||||
mutex->locked = 0;
|
||||
#endif
|
||||
|
||||
cond->lock = mutex;
|
||||
pthread_condattr_init(&attr);
|
||||
|
||||
/* OSX doesn't provide clockid_t or clock_gettime. */
|
||||
#if defined(__clockid_t_defined)
|
||||
cond->clkid = (clockid_t) 0;
|
||||
/* We try here to chose the best clock for cond_timedwait */
|
||||
# if defined(CLOCK_MONOTONIC_RAW)
|
||||
if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC_RAW))
|
||||
cond->clkid = CLOCK_MONOTONIC_RAW;
|
||||
# endif
|
||||
# if defined(CLOCK_MONOTONIC)
|
||||
if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
|
||||
cond->clkid = CLOCK_MONOTONIC;
|
||||
# endif
|
||||
# if defined(CLOCK_REALTIME)
|
||||
if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_REALTIME))
|
||||
cond->clkid = CLOCK_REALTIME;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
ok = pthread_cond_init(&cond->condition, &attr);
|
||||
if (ok != 0)
|
||||
{
|
||||
pthread_condattr_destroy(&attr);
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
if (ok == EBUSY)
|
||||
fprintf(stderr, "EINA ERROR: eina_condition_new on already initialized Eina_Condition\n");
|
||||
#endif
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
pthread_condattr_destroy(&attr);
|
||||
return EINA_TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
_eina_condition_free(Eina_Condition *cond)
|
||||
eina_lock_free(Eina_Lock *mutex)
|
||||
{
|
||||
pthread_cond_destroy(&(cond->condition));
|
||||
_eina_lock_free(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_lock_take_try(Eina_Lock *mutex)
|
||||
{
|
||||
return _eina_lock_take_try(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_lock_take(Eina_Lock *mutex)
|
||||
{
|
||||
return _eina_lock_take(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_lock_release(Eina_Lock *mutex)
|
||||
{
|
||||
return _eina_lock_release(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_rwlock_new(Eina_RWLock *mutex)
|
||||
eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||
{
|
||||
int ok;
|
||||
|
||||
ok = pthread_rwlock_init(&(mutex->mutex), NULL);
|
||||
if (ok == 0) return EINA_TRUE;
|
||||
else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, rwlock_init, mutex);
|
||||
return EINA_FALSE;
|
||||
return _eina_condition_new(cond, mutex);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
_eina_rwlock_free(Eina_RWLock *mutex)
|
||||
eina_condition_free(Eina_Condition *cond)
|
||||
{
|
||||
pthread_rwlock_destroy(&(mutex->mutex));
|
||||
_eina_condition_free(cond);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_barrier_new(Eina_Barrier *barrier, int needed)
|
||||
eina_condition_wait(Eina_Condition *cond)
|
||||
{
|
||||
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
||||
int ok = pthread_barrier_init(&(barrier->barrier), NULL, needed);
|
||||
if (ok == 0) return EINA_TRUE;
|
||||
else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, barrier_init, barrier);
|
||||
return EINA_FALSE;
|
||||
#else
|
||||
barrier->needed = needed;
|
||||
barrier->called = 0;
|
||||
if (eina_lock_new(&(barrier->cond_lock)))
|
||||
{
|
||||
if (eina_condition_new(&(barrier->cond), &(barrier->cond_lock)))
|
||||
return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
#endif
|
||||
return _eina_condition_wait(cond);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_condition_timedwait(Eina_Condition *cond, double t)
|
||||
{
|
||||
return _eina_condition_timedwait(cond, t);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_condition_broadcast(Eina_Condition *cond)
|
||||
{
|
||||
return _eina_condition_broadcast(cond);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_condition_signal(Eina_Condition *cond)
|
||||
{
|
||||
return _eina_condition_signal(cond);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_rwlock_new(Eina_RWLock *mutex)
|
||||
{
|
||||
return _eina_rwlock_new(mutex);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
_eina_barrier_free(Eina_Barrier *barrier)
|
||||
eina_rwlock_free(Eina_RWLock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
||||
int ok = pthread_barrier_destroy(&(barrier->barrier));
|
||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, barrier_destroy, barrier);
|
||||
#else
|
||||
eina_condition_free(&(barrier->cond));
|
||||
eina_lock_free(&(barrier->cond_lock));
|
||||
barrier->needed = 0;
|
||||
barrier->called = 0;
|
||||
#endif
|
||||
_eina_rwlock_free(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_rwlock_take_read(Eina_RWLock *mutex)
|
||||
{
|
||||
return _eina_rwlock_take_read(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_rwlock_take_write(Eina_RWLock *mutex)
|
||||
{
|
||||
return _eina_rwlock_take_write(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_rwlock_release(Eina_RWLock *mutex)
|
||||
{
|
||||
return _eina_rwlock_release(mutex);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||
eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
{
|
||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||
int ok = pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE);
|
||||
if (ok == 0) return EINA_TRUE;
|
||||
else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
|
||||
else EINA_LOCK_ABORT_DEBUG(ok, spin_init, spinlock);
|
||||
return EINA_FALSE;
|
||||
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
||||
*spinlock = 0;
|
||||
return EINA_TRUE;
|
||||
#else
|
||||
return eina_lock_new(spinlock);
|
||||
#endif
|
||||
return _eina_tls_cb_new(key, delete_cb);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
{
|
||||
return _eina_tls_cb_new(key, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
_eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||
eina_tls_free(Eina_TLS key)
|
||||
{
|
||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||
int ok = pthread_spin_destroy(spinlock);
|
||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, spin_destroy, spinlock);
|
||||
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
||||
/* Not applicable */
|
||||
(void) spinlock;
|
||||
#else
|
||||
eina_lock_free(spinlock);
|
||||
#endif
|
||||
_eina_tls_free(key);
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
eina_tls_get(Eina_TLS key)
|
||||
{
|
||||
return _eina_tls_get(key);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
||||
eina_tls_set(Eina_TLS key, const void *data)
|
||||
{
|
||||
if (sem && (count_init >= 0))
|
||||
{
|
||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||
kern_return_t kr = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, count_init);
|
||||
return (kr == KERN_SUCCESS) ? EINA_TRUE : EINA_FALSE;
|
||||
#else
|
||||
return (sem_init(sem, 0, count_init) == 0) ? EINA_TRUE : EINA_FALSE;
|
||||
#endif
|
||||
}
|
||||
return EINA_FALSE;
|
||||
return _eina_tls_set(key, data);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_semaphore_free(Eina_Semaphore *sem)
|
||||
eina_barrier_new(Eina_Barrier *barrier, int needed)
|
||||
{
|
||||
if (sem)
|
||||
{
|
||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||
return (semaphore_destroy(mach_task_self(), *sem) == KERN_SUCCESS)
|
||||
? EINA_TRUE : EINA_FALSE;
|
||||
#else
|
||||
return (sem_destroy(sem) == 0) ? EINA_TRUE : EINA_FALSE;
|
||||
#endif
|
||||
}
|
||||
return EINA_FALSE;
|
||||
return _eina_barrier_new(barrier, needed);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
eina_barrier_free(Eina_Barrier *barrier)
|
||||
{
|
||||
_eina_barrier_free(barrier);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_barrier_wait(Eina_Barrier *barrier)
|
||||
{
|
||||
return _eina_barrier_wait(barrier);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return _eina_spinlock_new(spinlock);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||
{
|
||||
_eina_spinlock_free(spinlock);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return _eina_spinlock_take_try(spinlock);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_spinlock_take(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return _eina_spinlock_take(spinlock);
|
||||
}
|
||||
|
||||
EAPI Eina_Lock_Result
|
||||
eina_spinlock_release(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return _eina_spinlock_release(spinlock);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
||||
{
|
||||
return _eina_semaphore_new(sem, count_init);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_semaphore_free(Eina_Semaphore *sem)
|
||||
{
|
||||
return _eina_semaphore_free(sem);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_semaphore_lock(Eina_Semaphore *sem)
|
||||
{
|
||||
return _eina_semaphore_lock(sem);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
|
||||
{
|
||||
return _eina_semaphore_release(sem, count_release);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,11 @@ typedef enum
|
|||
*/
|
||||
typedef void (*Eina_TLS_Delete_Cb)(void *ptr);
|
||||
|
||||
#include "eina_inline_lock_posix.x"
|
||||
#ifdef _WIN32
|
||||
# include "eina_inline_lock_win32.x"
|
||||
#else
|
||||
# include "eina_inline_lock_posix.x"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A type definition for warning that a function was called from
|
||||
|
@ -117,7 +121,7 @@ EAPI extern Eina_Error EINA_ERROR_NOT_MAIN_LOOP;
|
|||
*
|
||||
* @see eina_lock_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_lock_new(Eina_Lock *mutex);
|
||||
EAPI Eina_Bool eina_lock_new(Eina_Lock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Initializes a new #Eina_Lock that is recursive.
|
||||
|
@ -133,7 +137,7 @@ static inline Eina_Bool eina_lock_new(Eina_Lock *mutex);
|
|||
* @see eina_lock_free()
|
||||
* @since 1.19
|
||||
*/
|
||||
static inline Eina_Bool eina_lock_recursive_new(Eina_Lock *mutex);
|
||||
EAPI Eina_Bool eina_lock_recursive_new(Eina_Lock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Deallocates an #Eina_Lock.
|
||||
|
@ -144,7 +148,7 @@ static inline Eina_Bool eina_lock_recursive_new(Eina_Lock *mutex);
|
|||
*
|
||||
* @see eina_lock_new()
|
||||
*/
|
||||
static inline void eina_lock_free(Eina_Lock *mutex);
|
||||
EAPI void eina_lock_free(Eina_Lock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Attempts to take a lock.
|
||||
|
@ -162,7 +166,7 @@ static inline void eina_lock_free(Eina_Lock *mutex);
|
|||
* @see eina_lock_take_try()
|
||||
* @see eina_lock_release()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
|
||||
EAPI Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Attempts to take a lock if possible.
|
||||
|
@ -178,7 +182,7 @@ static inline Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
|
|||
* @see eina_lock_take()
|
||||
* @see eina_lock_release()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
|
||||
EAPI Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Releases a lock.
|
||||
|
@ -194,7 +198,7 @@ static inline Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
|
|||
* @see eina_lock_take()
|
||||
* @see eina_lock_take_try()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_lock_release(Eina_Lock *mutex);
|
||||
EAPI Eina_Lock_Result eina_lock_release(Eina_Lock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Prints debug information about a lock.
|
||||
|
@ -226,7 +230,7 @@ EAPI void eina_lock_debug(const Eina_Lock *mutex);
|
|||
*
|
||||
* @see eina_condition_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
|
||||
EAPI Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Deallocates a condition variable.
|
||||
|
@ -237,7 +241,7 @@ static inline Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mute
|
|||
*
|
||||
* @see eina_condition_new()
|
||||
*/
|
||||
static inline void eina_condition_free(Eina_Condition *cond);
|
||||
EAPI void eina_condition_free(Eina_Condition *cond);
|
||||
|
||||
/**
|
||||
* @brief Causes a thread to wait until signaled by the condition.
|
||||
|
@ -249,7 +253,7 @@ static inline void eina_condition_free(Eina_Condition *cond);
|
|||
*
|
||||
* @see eina_condition_timedwait()
|
||||
*/
|
||||
static inline Eina_Bool eina_condition_wait(Eina_Condition *cond);
|
||||
EAPI Eina_Bool eina_condition_wait(Eina_Condition *cond);
|
||||
|
||||
/**
|
||||
* @brief Causes a thread to wait until signaled by the condition or a
|
||||
|
@ -265,7 +269,7 @@ static inline Eina_Bool eina_condition_wait(Eina_Condition *cond);
|
|||
*
|
||||
* @see eina_condition_wait()
|
||||
*/
|
||||
static inline Eina_Bool eina_condition_timedwait(Eina_Condition *cond, double t);
|
||||
EAPI Eina_Bool eina_condition_timedwait(Eina_Condition *cond, double t);
|
||||
|
||||
/**
|
||||
* @brief Signals all threads waiting for a condition.
|
||||
|
@ -279,7 +283,7 @@ static inline Eina_Bool eina_condition_timedwait(Eina_Condition *cond, double t)
|
|||
*
|
||||
* @see eina_condition_signal()
|
||||
*/
|
||||
static inline Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
|
||||
EAPI Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
|
||||
|
||||
/**
|
||||
* @brief Signals a thread waiting for a condition.
|
||||
|
@ -296,7 +300,7 @@ static inline Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
|
|||
*
|
||||
* @see eina_condition_broadcast()
|
||||
*/
|
||||
static inline Eina_Bool eina_condition_signal(Eina_Condition *cond);
|
||||
EAPI Eina_Bool eina_condition_signal(Eina_Condition *cond);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -311,7 +315,7 @@ static inline Eina_Bool eina_condition_signal(Eina_Condition *cond);
|
|||
*
|
||||
* @see eina_rwlock_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_rwlock_new(Eina_RWLock *mutex);
|
||||
EAPI Eina_Bool eina_rwlock_new(Eina_RWLock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Deallocates an #Eina_RWLock.
|
||||
|
@ -322,7 +326,7 @@ static inline Eina_Bool eina_rwlock_new(Eina_RWLock *mutex);
|
|||
*
|
||||
* @see eina_rwlock_new()
|
||||
*/
|
||||
static inline void eina_rwlock_free(Eina_RWLock *mutex);
|
||||
EAPI void eina_rwlock_free(Eina_RWLock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Attempts to take a read lock.
|
||||
|
@ -338,7 +342,7 @@ static inline void eina_rwlock_free(Eina_RWLock *mutex);
|
|||
*
|
||||
* @see eina_rwlock_release()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_rwlock_take_read(Eina_RWLock *mutex);
|
||||
EAPI Eina_Lock_Result eina_rwlock_take_read(Eina_RWLock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Attempts to take a write lock.
|
||||
|
@ -354,7 +358,7 @@ static inline Eina_Lock_Result eina_rwlock_take_read(Eina_RWLock *mutex);
|
|||
*
|
||||
* @see eina_rwlock_release()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_rwlock_take_write(Eina_RWLock *mutex);
|
||||
EAPI Eina_Lock_Result eina_rwlock_take_write(Eina_RWLock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Releases a lock.
|
||||
|
@ -368,7 +372,7 @@ static inline Eina_Lock_Result eina_rwlock_take_write(Eina_RWLock *mutex);
|
|||
* @see eina_rwlock_take_read()
|
||||
* @see eina_rwlock_take_write()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
|
||||
EAPI Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
|
||||
|
||||
/**
|
||||
* @brief Initializes a new #Eina_TLS, or thread level storage, to store thread
|
||||
|
@ -386,7 +390,7 @@ static inline Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
|
|||
* @see eina_tls_cb_new()
|
||||
* @see eina_tls_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_tls_new(Eina_TLS *key);
|
||||
EAPI Eina_Bool eina_tls_new(Eina_TLS *key);
|
||||
|
||||
/**
|
||||
* @brief Initializes a new #Eina_TLS, or thread level storage, to store thread
|
||||
|
@ -403,7 +407,7 @@ static inline Eina_Bool eina_tls_new(Eina_TLS *key);
|
|||
* @see eina_tls_new()
|
||||
* @see eina_tls_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb);
|
||||
EAPI Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb);
|
||||
|
||||
/**
|
||||
* @brief Frees an allocated #Eina_TLS.
|
||||
|
@ -415,7 +419,7 @@ static inline Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete
|
|||
* @see eina_tls_new()
|
||||
* @see eina_tls_cb_new()
|
||||
*/
|
||||
static inline void eina_tls_free(Eina_TLS key);
|
||||
EAPI void eina_tls_free(Eina_TLS key);
|
||||
|
||||
/**
|
||||
* @brief Gets the value in #Eina_TLS for this thread.
|
||||
|
@ -428,7 +432,7 @@ static inline void eina_tls_free(Eina_TLS key);
|
|||
*
|
||||
* @see eina_tls_set()
|
||||
*/
|
||||
static inline void *eina_tls_get(Eina_TLS key);
|
||||
EAPI void *eina_tls_get(Eina_TLS key);
|
||||
|
||||
/**
|
||||
* @brief Sets the value in Eina_TLS for this thread.
|
||||
|
@ -442,7 +446,7 @@ static inline void *eina_tls_get(Eina_TLS key);
|
|||
*
|
||||
* @see eina_tls_get()
|
||||
*/
|
||||
static inline Eina_Bool eina_tls_set(Eina_TLS key, const void *data);
|
||||
EAPI Eina_Bool eina_tls_set(Eina_TLS key, const void *data);
|
||||
|
||||
/**
|
||||
* @brief Initializes a new #Eina_Semaphore.
|
||||
|
@ -456,7 +460,7 @@ static inline Eina_Bool eina_tls_set(Eina_TLS key, const void *data);
|
|||
*
|
||||
* @see eina_semaphore_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_semaphore_new(Eina_Semaphore *sem, int count_init);
|
||||
EAPI Eina_Bool eina_semaphore_new(Eina_Semaphore *sem, int count_init);
|
||||
|
||||
/**
|
||||
* @brief Frees an allocated #Eina_Semaphore.
|
||||
|
@ -469,7 +473,7 @@ static inline Eina_Bool eina_semaphore_new(Eina_Semaphore *sem, int count_init);
|
|||
*
|
||||
* @see eina_semaphore_new()
|
||||
*/
|
||||
static inline Eina_Bool eina_semaphore_free(Eina_Semaphore *sem);
|
||||
EAPI Eina_Bool eina_semaphore_free(Eina_Semaphore *sem);
|
||||
|
||||
/**
|
||||
* @brief Gets a lock on an #Eina_Semaphore.
|
||||
|
@ -482,7 +486,7 @@ static inline Eina_Bool eina_semaphore_free(Eina_Semaphore *sem);
|
|||
*
|
||||
* @see eina_semaphore_release()
|
||||
*/
|
||||
static inline Eina_Bool eina_semaphore_lock(Eina_Semaphore *sem);
|
||||
EAPI Eina_Bool eina_semaphore_lock(Eina_Semaphore *sem);
|
||||
|
||||
/**
|
||||
* @brief Releases a lock on an #Eina_Semaphore.
|
||||
|
@ -496,7 +500,7 @@ static inline Eina_Bool eina_semaphore_lock(Eina_Semaphore *sem);
|
|||
*
|
||||
* @see eina_semaphore_lock()
|
||||
*/
|
||||
static inline Eina_Bool eina_semaphore_release(Eina_Semaphore *sem, int count_release);
|
||||
EAPI Eina_Bool eina_semaphore_release(Eina_Semaphore *sem, int count_release);
|
||||
|
||||
/**
|
||||
* @brief Initializes a new #Eina_Barrier.
|
||||
|
@ -511,7 +515,7 @@ static inline Eina_Bool eina_semaphore_release(Eina_Semaphore *sem, int count_re
|
|||
*
|
||||
* @see eina_barrier_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_barrier_new(Eina_Barrier *barrier, int needed);
|
||||
EAPI Eina_Bool eina_barrier_new(Eina_Barrier *barrier, int needed);
|
||||
|
||||
/**
|
||||
* @brief Frees an allocated #Eina_Barrier.
|
||||
|
@ -521,7 +525,7 @@ static inline Eina_Bool eina_barrier_new(Eina_Barrier *barrier, int needed);
|
|||
*
|
||||
* @see eina_barrier_new()
|
||||
*/
|
||||
static inline void eina_barrier_free(Eina_Barrier *barrier);
|
||||
EAPI void eina_barrier_free(Eina_Barrier *barrier);
|
||||
|
||||
/**
|
||||
* @brief Increments the count of threads that are waiting on @p barrier.
|
||||
|
@ -532,7 +536,7 @@ static inline void eina_barrier_free(Eina_Barrier *barrier);
|
|||
* @return #EINA_TRUE on success, else #EINA_FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
static inline Eina_Bool eina_barrier_wait(Eina_Barrier *barrier);
|
||||
EAPI Eina_Bool eina_barrier_wait(Eina_Barrier *barrier);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -549,7 +553,7 @@ static inline Eina_Bool eina_barrier_wait(Eina_Barrier *barrier);
|
|||
*
|
||||
* @see eina_spinlock_free()
|
||||
*/
|
||||
static inline Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock);
|
||||
EAPI Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock);
|
||||
|
||||
/**
|
||||
* @brief Attempts to take a spinlock.
|
||||
|
@ -567,7 +571,7 @@ static inline Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock);
|
|||
* @see eina_spinlock_take_try()
|
||||
* @see eina_spinlock_release()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock);
|
||||
EAPI Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock);
|
||||
|
||||
/**
|
||||
* @brief Attempts to take a spinlock if possible.
|
||||
|
@ -583,7 +587,7 @@ static inline Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock);
|
|||
* @see eina_spinlock_take_try()
|
||||
* @see eina_spinlock_release()
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock);
|
||||
EAPI Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock);
|
||||
|
||||
/**
|
||||
* @brief Releases a spinlock.
|
||||
|
@ -599,7 +603,7 @@ static inline Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock);
|
|||
* @see eina_spinlock_take_try()
|
||||
|
||||
*/
|
||||
static inline Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock);
|
||||
EAPI Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock);
|
||||
|
||||
/**
|
||||
* @brief Deallocates an #Eina_Spinlock.
|
||||
|
@ -609,7 +613,7 @@ static inline Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock);
|
|||
* @param[in] spinlock The #Eina_Spinlock to be deallocated.
|
||||
*
|
||||
*/
|
||||
static inline void eina_spinlock_free(Eina_Spinlock *spinlock);
|
||||
EAPI void eina_spinlock_free(Eina_Spinlock *spinlock);
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
# define EINA_MAIN_LOOP_CHECK_RETURN_VAL(val) \
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#endif
|
||||
|
||||
#include "eina_lock.h"
|
||||
#include "eina_thread.h"
|
||||
#include "eina_config.h"
|
||||
#include "eina_private.h"
|
||||
#include "eina_types.h"
|
||||
|
@ -99,7 +100,7 @@ EAPI Eina_Error EINA_ERROR_NOT_IMPLEMENTED = 0;
|
|||
EAPI unsigned int eina_seed = 0;
|
||||
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
EAPI Eina_Thread _eina_main_loop;
|
||||
EAPI Eina_Thread _eina_main_loop;
|
||||
#endif
|
||||
|
||||
#ifdef MT
|
||||
|
@ -108,7 +109,7 @@ static int _mt_enabled = 0;
|
|||
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
EAPI int _eina_threads_debug = 0;
|
||||
EAPI pthread_mutex_t _eina_tracking_lock;
|
||||
EAPI Eina_Lock _eina_tracking_lock;
|
||||
EAPI Eina_Inlist *_eina_tracking = NULL;
|
||||
extern Eina_Lock _sysmon_lock;
|
||||
#endif
|
||||
|
@ -230,7 +231,7 @@ _eina_threads_do_shutdown(void)
|
|||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
const Eina_Lock *lk;
|
||||
|
||||
pthread_mutex_lock(&_eina_tracking_lock);
|
||||
eina_lock_take(&_eina_tracking_lock);
|
||||
if (_eina_tracking)
|
||||
{
|
||||
if (((Eina_Lock*)_eina_tracking != (&_sysmon_lock)) || (_eina_tracking->next))
|
||||
|
@ -248,7 +249,7 @@ _eina_threads_do_shutdown(void)
|
|||
abort();
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&_eina_tracking_lock);
|
||||
eina_lock_release(&_eina_tracking_lock);
|
||||
#endif
|
||||
|
||||
eina_share_common_threads_shutdown();
|
||||
|
@ -317,7 +318,7 @@ eina_init(void)
|
|||
}
|
||||
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
pthread_mutex_init(&_eina_tracking_lock, NULL);
|
||||
eina_lock_take(&_eina_tracking_lock, NULL);
|
||||
|
||||
if (getenv("EINA_DEBUG_THREADS"))
|
||||
_eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS"));
|
||||
|
@ -367,7 +368,7 @@ eina_shutdown(void)
|
|||
if (_eina_threads_activated && (!_eina_main_thread_count))
|
||||
_eina_threads_do_shutdown();
|
||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||
pthread_mutex_destroy(&_eina_tracking_lock);
|
||||
eina_lock_free(&_eina_tracking_lock);
|
||||
#endif
|
||||
eina_freeq_free(eina_freeq_main_get());
|
||||
#ifdef MT
|
||||
|
@ -388,7 +389,7 @@ eina_threads_init(void)
|
|||
{
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
int ret;
|
||||
# ifdef EINA_HAVE_DEBUG_THREADS
|
||||
# ifdef EINA_HAVE_DEBUG_THREADS
|
||||
assert(eina_thread_equal(_eina_main_loop, eina_thread_self()));
|
||||
# endif
|
||||
|
||||
|
@ -438,7 +439,7 @@ eina_main_loop_is(void)
|
|||
#ifdef EFL_HAVE_THREADS
|
||||
# ifdef __GNUC__
|
||||
/* pthread_self() can't be optimized, it's a single asm "movl" */
|
||||
if (__builtin_types_compatible_p(pthread_t, unsigned long int))
|
||||
if (__builtin_types_compatible_p(Eina_Thread, unsigned long int))
|
||||
return (eina_thread_self() == _eina_main_loop);
|
||||
else
|
||||
# endif
|
||||
|
|
|
@ -85,8 +85,6 @@ public_sub_headers = [
|
|||
'eina_inline_value.x',
|
||||
'eina_value_util.h',
|
||||
'eina_inline_value_util.x',
|
||||
'eina_inline_lock_barrier.x',
|
||||
'eina_inline_lock_posix.x',
|
||||
'eina_tmpstr.h',
|
||||
'eina_alloca.h',
|
||||
'eina_cow.h',
|
||||
|
@ -197,15 +195,17 @@ sources = [
|
|||
]
|
||||
|
||||
if sys_windows == true
|
||||
public_sub_headers += 'eina_thread_win32.h'
|
||||
public_sub_headers += 'eina_inline_thread_win32.x'
|
||||
public_sub_headers += 'eina_thread_win32.h'
|
||||
public_sub_headers += 'eina_inline_thread_win32.x'
|
||||
sources += 'eina_file_win32.c'
|
||||
sources += 'eina_sched_win32.c'
|
||||
sources += 'eina_sched_win32.c'
|
||||
public_sub_headers += 'eina_inline_lock_win32.x'
|
||||
else
|
||||
public_sub_headers += 'eina_thread_posix.h'
|
||||
public_sub_headers += 'eina_thread_posix.h'
|
||||
public_sub_headers += 'eina_inline_thread_posix.x'
|
||||
sources += 'eina_file.c'
|
||||
sources += 'eina_sched_posix.c'
|
||||
sources += 'eina_sched_posix.c'
|
||||
public_sub_headers += 'eina_inline_lock_posix.x'
|
||||
endif
|
||||
|
||||
eina_config = configuration_data()
|
||||
|
@ -347,7 +347,7 @@ if cc.has_header('byteswap.h')
|
|||
endif
|
||||
|
||||
if cc.has_header_symbol('pthread.h', 'pthread_spin_init')
|
||||
eina_config.set('EINA_HAVE_POSIX_SPINLOCK', '1')
|
||||
eina_config.set('EINA_HAVE_PTHREAD_SPINLOCK', '1')
|
||||
endif
|
||||
|
||||
if sys_osx == true
|
||||
|
@ -359,6 +359,15 @@ if sys_osx == true
|
|||
endif
|
||||
endif
|
||||
|
||||
if sys_windows == true
|
||||
if cc.has_header_symbol('synchapi.h', 'SetCriticalSectionSpinCount')
|
||||
eina_config.set('EINA_HAVE_WIN32_SPINLOCK', '1')
|
||||
endif
|
||||
if cc.has_header_symbol('synchapi.h', 'InitializeSynchronizationBarrier')
|
||||
eina_config.set('EINA_HAVE_WIN32_BARRIER', '1')
|
||||
endif
|
||||
endif
|
||||
|
||||
if host_machine.endian() == 'big'
|
||||
eina_config.set('EINA_HAVE_WORDS_BIGENDIAN', '1')
|
||||
endif
|
||||
|
@ -423,4 +432,4 @@ pkgconfig.generate(eina_lib,
|
|||
version : version_major + '.' + version_minor + '.' + version_micro,
|
||||
libraries : eina_pub_deps,
|
||||
)
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -10,7 +10,6 @@ if sys_windows
|
|||
'locale.h',
|
||||
'math.h',
|
||||
'pthread.h',
|
||||
'semaphore.h',
|
||||
'stdlib.h',
|
||||
'string.h',
|
||||
'strings.h',
|
||||
|
|
|
@ -5,24 +5,15 @@
|
|||
|
||||
UNIMPLEMENTED typedef unsigned long long pthread_t;
|
||||
|
||||
UNIMPLEMENTED_STRUCT_T(pthread_mutexattr)
|
||||
UNIMPLEMENTED_STRUCT_T(pthread_condattr)
|
||||
UNIMPLEMENTED_STRUCT_T(pthread_attr)
|
||||
UNIMPLEMENTED_STRUCT_T(pthread_rwlock)
|
||||
UNIMPLEMENTED_STRUCT_T(pthread_cond)
|
||||
UNIMPLEMENTED_STRUCT_T(pthread_mutex)
|
||||
UNIMPLEMENTED_STRUCT_T(sem)
|
||||
|
||||
UNIMPLEMENTED struct sched_param {
|
||||
int sched_priority;
|
||||
};
|
||||
|
||||
UNIMPLEMENTED typedef int pthread_key_t;
|
||||
|
||||
#define SCHED_RR 5
|
||||
#define SCHED_FIFO 6
|
||||
|
||||
#define PTHREAD_BARRIER_SERIAL_THREAD 1
|
||||
#define PTHREAD_CANCEL_ASYNCHRONOUS 2
|
||||
#define PTHREAD_CANCEL_ENABLE 3
|
||||
#define PTHREAD_CANCEL_DEFERRED 4
|
||||
|
@ -32,12 +23,6 @@ UNIMPLEMENTED typedef int pthread_key_t;
|
|||
#define PTHREAD_CREATE_JOINABLE 8
|
||||
#define PTHREAD_EXPLICIT_SCHED 9
|
||||
#define PTHREAD_INHERIT_SCHED 10
|
||||
#define PTHREAD_MUTEX_DEFAULT 11
|
||||
#define PTHREAD_MUTEX_ERRORCHECK 12
|
||||
#define PTHREAD_MUTEX_NORMAL 13
|
||||
#define PTHREAD_MUTEX_RECURSIVE 14
|
||||
#define PTHREAD_MUTEX_ROBUST 15
|
||||
#define PTHREAD_MUTEX_STALLED 16
|
||||
#define PTHREAD_ONCE_INIT 17
|
||||
#define PTHREAD_PRIO_INHERIT 18
|
||||
#define PTHREAD_PRIO_NONE 19
|
||||
|
@ -47,202 +32,4 @@ UNIMPLEMENTED typedef int pthread_key_t;
|
|||
#define PTHREAD_SCOPE_PROCESS 23
|
||||
#define PTHREAD_SCOPE_SYSTEM 24
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutex_trylock(void* m)
|
||||
{
|
||||
#warning pthread_mutex_trylock is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutex_lock(void* m)
|
||||
{
|
||||
#warning pthread_mutex_lock is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutex_unlock(void* m)
|
||||
{
|
||||
#warning pthread_mutex_unlock is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cond_wait(void* c, void* m)
|
||||
{
|
||||
#warning pthread_cond_wait is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cond_timedwait(void* c, void* m, int t)
|
||||
{
|
||||
#warning pthread_cond_timedwait is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cond_broadcast(void* c)
|
||||
{
|
||||
#warning pthread_cond_broadcast is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cond_signal(void* c)
|
||||
{
|
||||
#warning pthread_cond_signal is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_rwlock_init(void* a, ...)
|
||||
{
|
||||
#warning pthread_rwlock_init is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutexattr_settype(void* a, ...)
|
||||
{
|
||||
#warning pthread_mutexattr_settype is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutex_init(void* a, ...)
|
||||
{
|
||||
#warning pthread_mutex_init is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutex_destroy(void* a, ...)
|
||||
{
|
||||
#warning pthread_mutex_destroy is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_condattr_init(void* a, ...)
|
||||
{
|
||||
#warning pthread_condattr_init is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cond_init(void* a, ...)
|
||||
{
|
||||
#warning pthread_cond_init is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_condattr_destroy(void* a, ...)
|
||||
{
|
||||
#warning pthread_condattr_destroy is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cond_destroy(void* a, ...)
|
||||
{
|
||||
#warning pthread_cond_destroy is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_rwlock_destroy(void* a, ...)
|
||||
{
|
||||
#warning pthread_rwlock_destroy is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_rwlock_rdlock(void* c)
|
||||
{
|
||||
#warning pthread_rwlock_rdlock is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_rwlock_wrlock(void* c)
|
||||
{
|
||||
#warning pthread_rwlock_wrlock is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_rwlock_unlock(void* c)
|
||||
{
|
||||
#warning pthread_rwlock_unlock is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_key_create(void* c, void * d)
|
||||
{
|
||||
#warning pthread_key_create is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_key_delete(void* c)
|
||||
{
|
||||
#warning pthread_key_delete is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_getspecific(void* c)
|
||||
{
|
||||
#warning pthread_getspecific is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_setspecific(void* c, const void* d)
|
||||
{
|
||||
#warning pthread_setspecific is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutexattr_init(void* c, ...)
|
||||
{
|
||||
#warning pthread_mutexattr_init is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_getschedparam(void* a, ...)
|
||||
{
|
||||
#warning pthread_getschedparam is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_setschedparam(void* c, void* d, void* e)
|
||||
{
|
||||
#warning pthread_ is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_setcancelstate(void* a, ...)
|
||||
{
|
||||
#warning pthread_setcancelstate is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_testcancel()
|
||||
{
|
||||
#warning pthread_testcancel is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cleanup_pop(void* a, ...)
|
||||
{
|
||||
#warning pthread_cleanup_pop is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_cleanup_push(void* a, ...)
|
||||
{
|
||||
#warning pthread_cleanup_push is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_attr_init(void* a, ...)
|
||||
{
|
||||
#warning pthread_attr_init is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_setcanceltype(void* a, ...)
|
||||
{
|
||||
#warning pthread_setcanceltype is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED inline int pthread_mutexattr_destroy(void* a, ...)
|
||||
{
|
||||
#warning pthread_mutexattr_destroy is not implemented.
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
#ifndef SEMAPHORE_H
|
||||
#define SEMAPHORE_H
|
||||
|
||||
#include "unimplemented.h"
|
||||
|
||||
UNIMPLEMENTED_STRUCT_T(sem)
|
||||
|
||||
UNIMPLEMENTED inline int sem_close(sem_t* sem)
|
||||
{
|
||||
#warning sem_close is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_destroy(sem_t* sem)
|
||||
{
|
||||
#warning sem_destroy is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_getvalue(sem_t* restrict sem, int* restrict x)
|
||||
{
|
||||
#warning sem_getvalue is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_init(sem_t* sem, int x, unsigned y)
|
||||
{
|
||||
#warning sem_init is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline sem_t* sem_open(const char* name, int x, ...)
|
||||
{
|
||||
#warning sem_open is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_post(sem_t* sem)
|
||||
{
|
||||
#warning sem_post is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_timedwait(sem_t* restrict sem, const struct timespec* restrict timeout)
|
||||
{
|
||||
#warning sem_timedwait is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_trywait(sem_t* sem)
|
||||
{
|
||||
#warning sem_trywait is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_unlink(const char* name)
|
||||
{
|
||||
#warning sem_unlink is not implemented
|
||||
return 0;
|
||||
}
|
||||
UNIMPLEMENTED inline int sem_wait(sem_t* sem)
|
||||
{
|
||||
#warning sem_wait is not implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue