2011-04-22 14:26:36 -07:00
|
|
|
/* EINA - EFL data type library
|
|
|
|
* Copyright (C) 2011 Vincent Torri
|
|
|
|
*
|
|
|
|
* 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_POSIX_X_
|
|
|
|
#define EINA_INLINE_LOCK_POSIX_X_
|
|
|
|
|
2014-01-03 18:25:19 -08:00
|
|
|
#ifdef _XOPEN_SOURCE
|
|
|
|
# define EINA_XOPEN_SOURCE _XOPEN_SOURCE
|
|
|
|
# undef _XOPEN_SOURCE
|
|
|
|
#endif
|
|
|
|
#define _XOPEN_SOURCE 600
|
|
|
|
|
2013-10-10 01:22:28 -07:00
|
|
|
#ifdef EINA_HAVE_POSIX_SPINLOCK
|
|
|
|
# include <sched.h>
|
|
|
|
#endif
|
|
|
|
|
2011-05-01 06:24:08 -07:00
|
|
|
#include <errno.h>
|
2011-04-24 19:30:42 -07:00
|
|
|
#ifndef __USE_UNIX98
|
|
|
|
# define __USE_UNIX98
|
|
|
|
# include <pthread.h>
|
2011-04-25 01:48:20 -07:00
|
|
|
# undef __USE_UNIX98
|
2011-04-24 19:30:42 -07:00
|
|
|
#else
|
|
|
|
# include <pthread.h>
|
|
|
|
#endif
|
2011-04-22 14:26:36 -07:00
|
|
|
|
eina: overhaul Mac OS X semaphores
Mac OS X does not support POSIX unnamed semaphores, only named
semaphores, which are persistant IPC: when the program exits,
and if semaphores where not released, they stay forever...
All EFL programs were "leaking" a semaphore, due to how
eina_log_monitor manages its resources. Therefore, after building
EFL a lot (which run eolian_gen, eolian_cxx, elua, edje_cc, ...)
we were not able to create any semaphore...
Now, we get rid of these semaphores and use Mac OS X's own
semaphores. Code is less cumbersome, and we don't have any
disavantage of the named semaphores.
Fixes T4423
@fix
2016-08-26 08:41:20 -07:00
|
|
|
#ifdef EINA_HAVE_OSX_SEMAPHORE
|
|
|
|
# include <mach/mach.h>
|
|
|
|
#endif
|
|
|
|
|
2011-12-30 05:38:53 -08:00
|
|
|
#include <semaphore.h>
|
|
|
|
|
2011-07-13 01:51:19 -07:00
|
|
|
#include <sys/time.h>
|
2011-12-06 13:33:39 -08:00
|
|
|
#include <stdio.h>
|
2011-05-04 06:53:22 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2015-12-10 02:02:28 -08:00
|
|
|
|
2016-08-08 07:02:39 -07:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2011-05-04 06:53:22 -07:00
|
|
|
#include <assert.h>
|
2011-05-01 06:24:08 -07:00
|
|
|
#include <execinfo.h>
|
|
|
|
#define EINA_LOCK_DEBUG_BT_NUM 64
|
|
|
|
typedef void (*Eina_Lock_Bt_Func) ();
|
2011-05-04 06:53:22 -07:00
|
|
|
|
|
|
|
#include "eina_inlist.h"
|
2016-09-18 16:58:56 -07:00
|
|
|
#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);
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
#define EINA_LOCK_ABORT_DEBUG(err, fn, ptr) \
|
2016-09-18 16:58:56 -07:00
|
|
|
_eina_lock_debug_abort(err, #fn, ptr)
|
2015-12-10 02:02:28 -08:00
|
|
|
#define EINA_LOCK_DEADLOCK_DEBUG(fn, ptr) \
|
2016-09-18 16:58:56 -07:00
|
|
|
_eina_lock_debug_deadlock(#fn, ptr)
|
2011-05-01 06:24:08 -07:00
|
|
|
|
2014-10-30 04:09:43 -07:00
|
|
|
/* For cond_timedwait */
|
|
|
|
#include <time.h>
|
|
|
|
#include <sys/time.h>
|
2014-10-27 07:47:51 -07:00
|
|
|
|
2016-08-01 01:38:05 -07:00
|
|
|
#include <eina_error.h>
|
|
|
|
|
2011-05-01 06:24:08 -07:00
|
|
|
typedef struct _Eina_Lock Eina_Lock;
|
2011-06-23 02:58:54 -07:00
|
|
|
typedef struct _Eina_RWLock Eina_RWLock;
|
2011-05-09 03:32:56 -07:00
|
|
|
typedef struct _Eina_Condition Eina_Condition;
|
2011-10-16 22:06:01 -07:00
|
|
|
typedef pthread_key_t Eina_TLS;
|
2014-10-27 01:11:19 -07:00
|
|
|
|
2014-08-21 02:23:24 -07:00
|
|
|
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
2013-10-10 01:22:28 -07:00
|
|
|
typedef pthread_spinlock_t Eina_Spinlock;
|
2014-08-21 02:23:24 -07:00
|
|
|
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
2016-10-01 06:09:37 -07:00
|
|
|
typedef uintptr_t Eina_Spinlock;
|
2013-10-10 01:22:28 -07:00
|
|
|
#else
|
|
|
|
typedef Eina_Lock Eina_Spinlock;
|
|
|
|
#endif
|
2011-05-01 06:24:08 -07:00
|
|
|
|
2014-10-27 01:11:19 -07:00
|
|
|
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
eina: overhaul Mac OS X semaphores
Mac OS X does not support POSIX unnamed semaphores, only named
semaphores, which are persistant IPC: when the program exits,
and if semaphores where not released, they stay forever...
All EFL programs were "leaking" a semaphore, due to how
eina_log_monitor manages its resources. Therefore, after building
EFL a lot (which run eolian_gen, eolian_cxx, elua, edje_cc, ...)
we were not able to create any semaphore...
Now, we get rid of these semaphores and use Mac OS X's own
semaphores. Code is less cumbersome, and we don't have any
disavantage of the named semaphores.
Fixes T4423
@fix
2016-08-26 08:41:20 -07:00
|
|
|
typedef semaphore_t Eina_Semaphore;
|
2014-10-27 01:11:19 -07:00
|
|
|
#else
|
|
|
|
typedef sem_t Eina_Semaphore;
|
|
|
|
#endif
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
EAPI void eina_lock_debug(const Eina_Lock *mutex);
|
|
|
|
|
2014-03-25 01:30:42 -07:00
|
|
|
/** @privatesection @{ */
|
2011-05-01 06:24:08 -07:00
|
|
|
struct _Eina_Lock
|
|
|
|
{
|
2011-05-04 06:53:22 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2014-03-25 01:30:42 -07:00
|
|
|
EINA_INLIST; /**< Keeps track of the threads waiting for the lock */
|
2011-05-04 06:53:22 -07:00
|
|
|
#endif
|
2014-03-25 01:30:42 -07:00
|
|
|
pthread_mutex_t mutex; /**< The mutex that handles the locking */
|
2011-05-02 04:25:35 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2014-03-25 01:30:42 -07:00
|
|
|
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 */
|
2018-06-15 12:37:56 -07:00
|
|
|
Eina_Bool recursive : 1; /**< Indicates recursive lock */
|
2011-05-02 01:24:06 -07:00
|
|
|
#endif
|
2011-05-02 04:25:35 -07:00
|
|
|
};
|
2011-05-02 01:24:06 -07:00
|
|
|
|
2011-05-09 03:32:56 -07:00
|
|
|
struct _Eina_Condition
|
|
|
|
{
|
2014-03-25 01:30:42 -07:00
|
|
|
Eina_Lock *lock; /**< The lock for this condition */
|
|
|
|
pthread_cond_t condition; /**< The condition variable */
|
2014-11-01 23:02:32 -07:00
|
|
|
#if defined(__clockid_t_defined)
|
2014-10-30 04:09:43 -07:00
|
|
|
clockid_t clkid; /**< The attached clock for timedwait */
|
2014-11-01 23:02:32 -07:00
|
|
|
#endif
|
2011-05-09 03:32:56 -07:00
|
|
|
};
|
|
|
|
|
2011-06-23 02:58:54 -07:00
|
|
|
struct _Eina_RWLock
|
|
|
|
{
|
2014-03-25 01:30:42 -07:00
|
|
|
pthread_rwlock_t mutex; /**< The mutex that handles the locking */
|
2011-06-23 02:58:54 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2014-03-25 01:30:42 -07:00
|
|
|
pthread_t lock_thread_wid; /**< The ID of the thread that currently has the lock */
|
2011-06-23 02:58:54 -07:00
|
|
|
#endif
|
|
|
|
};
|
2014-03-25 01:30:42 -07:00
|
|
|
/** @} privatesection */
|
2011-06-23 02:58:54 -07:00
|
|
|
|
2011-04-24 13:22:17 -07:00
|
|
|
EAPI extern Eina_Bool _eina_threads_activated;
|
|
|
|
|
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
EAPI extern int _eina_threads_debug;
|
2011-05-02 04:25:35 -07:00
|
|
|
EAPI extern pthread_t _eina_main_loop;
|
2011-05-04 06:53:22 -07:00
|
|
|
EAPI extern pthread_mutex_t _eina_tracking_lock;
|
|
|
|
EAPI extern Eina_Inlist *_eina_tracking;
|
2011-04-24 13:22:17 -07:00
|
|
|
#endif
|
2011-04-24 08:54:09 -07:00
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
|
|
|
|
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);
|
2016-10-01 06:09:37 -07:00
|
|
|
#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
|
2011-05-09 05:54:47 -07:00
|
|
|
|
2011-05-02 06:51:20 -07:00
|
|
|
static inline Eina_Bool
|
2011-04-22 14:26:36 -07:00
|
|
|
eina_lock_new(Eina_Lock *mutex)
|
|
|
|
{
|
2018-06-15 12:37:56 -07:00
|
|
|
Eina_Bool ret = _eina_lock_new(mutex, EINA_FALSE);
|
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
mutex->recursive = EINA_FALSE;
|
2018-06-19 10:30:20 -07:00
|
|
|
mutex->lock_thread_id = 0;
|
|
|
|
mutex->lock_bt_num = 0;
|
|
|
|
mutex->locked = 0;
|
2018-06-15 12:37:56 -07:00
|
|
|
#endif
|
|
|
|
return ret;
|
2011-04-22 14:26:36 -07:00
|
|
|
}
|
|
|
|
|
2016-09-07 07:12:02 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
eina_lock_recursive_new(Eina_Lock *mutex)
|
|
|
|
{
|
2018-06-15 12:37:56 -07:00
|
|
|
Eina_Bool ret = _eina_lock_new(mutex, EINA_TRUE);
|
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
mutex->recursive = EINA_TRUE;
|
2018-06-19 10:30:20 -07:00
|
|
|
mutex->lock_thread_id = 0;
|
|
|
|
mutex->lock_bt_num = 0;
|
|
|
|
mutex->locked = 0;
|
2018-06-15 12:37:56 -07:00
|
|
|
#endif
|
|
|
|
return ret;
|
2016-09-07 07:12:02 -07:00
|
|
|
}
|
|
|
|
|
2011-04-22 14:26:36 -07:00
|
|
|
static inline void
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_free(Eina_Lock *mutex)
|
2011-04-22 14:26:36 -07:00
|
|
|
{
|
2018-06-15 12:38:20 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
if (mutex->locked)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
|
|
|
EINA_INLIST_GET(mutex));
|
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
|
|
|
}
|
|
|
|
#endif
|
2016-09-18 16:58:56 -07:00
|
|
|
_eina_lock_free(mutex);
|
2011-04-22 14:26:36 -07:00
|
|
|
}
|
|
|
|
|
2018-06-25 12:15:29 -07:00
|
|
|
static inline Eina_Lock_Result
|
|
|
|
eina_lock_take_try(Eina_Lock *mutex)
|
|
|
|
{
|
|
|
|
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
|
|
|
int ok;
|
|
|
|
|
|
|
|
#ifdef EINA_HAVE_ON_OFF_THREADS
|
|
|
|
if (!_eina_threads_activated)
|
|
|
|
{
|
|
|
|
return EINA_LOCK_SUCCEED;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ok = pthread_mutex_trylock(&(mutex->mutex));
|
|
|
|
if (ok == 0) ret = EINA_LOCK_SUCCEED;
|
|
|
|
else if (ok == EDEADLK)
|
|
|
|
{
|
|
|
|
eina_lock_debug(mutex);
|
|
|
|
ret = EINA_LOCK_DEADLOCK;
|
|
|
|
}
|
|
|
|
else if (ok != EBUSY) EINA_LOCK_ABORT_DEBUG(ok, 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 = pthread_self();
|
2018-06-25 12:18:11 -07:00
|
|
|
/* backtrace() can somehow generate EINVAL even though this is not documented anywhere? */
|
|
|
|
int err = errno;
|
2018-06-25 12:15:29 -07:00
|
|
|
mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
|
2018-06-25 12:18:11 -07:00
|
|
|
errno = err;
|
2018-06-25 12:15:29 -07:00
|
|
|
|
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_append(_eina_tracking,
|
|
|
|
EINA_INLIST_GET(mutex));
|
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-02 01:24:06 -07:00
|
|
|
static inline Eina_Lock_Result
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(Eina_Lock *mutex)
|
2011-04-22 14:26:36 -07:00
|
|
|
{
|
2011-05-02 06:51:20 -07:00
|
|
|
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
2011-05-02 01:34:22 -07:00
|
|
|
int ok;
|
2011-05-02 04:25:35 -07:00
|
|
|
|
2011-05-02 06:40:28 -07:00
|
|
|
#ifdef EINA_HAVE_ON_OFF_THREADS
|
|
|
|
if (!_eina_threads_activated)
|
|
|
|
{
|
2011-05-04 06:53:22 -07:00
|
|
|
return EINA_LOCK_SUCCEED;
|
2011-05-02 06:40:28 -07:00
|
|
|
}
|
|
|
|
#endif
|
2011-05-02 04:25:35 -07:00
|
|
|
|
2018-06-25 12:15:32 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
if (eina_lock_take_try(mutex) == EINA_LOCK_SUCCEED) return EINA_LOCK_SUCCEED;
|
|
|
|
#endif
|
|
|
|
|
2011-05-02 06:40:28 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2018-06-25 12:15:34 -07:00
|
|
|
if (_eina_threads_debug >= 100)
|
2011-05-01 06:24:08 -07:00
|
|
|
{
|
|
|
|
struct timeval t0, t1;
|
|
|
|
int dt;
|
2011-05-02 04:25:35 -07:00
|
|
|
|
2011-05-01 06:24:08 -07:00
|
|
|
gettimeofday(&t0, NULL);
|
2011-05-04 06:53:22 -07:00
|
|
|
ok = pthread_mutex_lock(&(mutex->mutex));
|
2011-05-01 06:24:08 -07:00
|
|
|
gettimeofday(&t1, NULL);
|
2011-05-02 04:25:35 -07:00
|
|
|
|
2011-05-01 06:24:08 -07:00
|
|
|
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;
|
2011-05-02 04:25:35 -07:00
|
|
|
|
2011-05-01 06:24:08 -07:00
|
|
|
if (dt > _eina_threads_debug) abort();
|
|
|
|
}
|
2011-05-04 06:53:22 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
ok = pthread_mutex_lock(&(mutex->mutex));
|
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
}
|
2011-04-24 13:22:17 -07:00
|
|
|
#endif
|
2011-05-04 06:53:22 -07:00
|
|
|
|
2011-05-02 06:51:20 -07:00
|
|
|
if (ok == 0) ret = EINA_LOCK_SUCCEED;
|
2011-05-02 01:34:22 -07:00
|
|
|
else if (ok == EDEADLK)
|
|
|
|
{
|
2011-05-09 05:54:47 -07:00
|
|
|
eina_lock_debug(mutex);
|
2016-09-18 16:58:56 -07:00
|
|
|
ret = EINA_LOCK_DEADLOCK;
|
2011-05-09 06:06:03 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2011-05-09 05:54:47 -07:00
|
|
|
if (_eina_threads_debug) abort();
|
2011-05-09 06:06:03 -07:00
|
|
|
#endif
|
2011-05-02 01:34:22 -07:00
|
|
|
}
|
2015-12-10 02:02:28 -08:00
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, lock, mutex);
|
2011-05-04 06:53:22 -07:00
|
|
|
|
2011-05-02 04:25:35 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2018-06-15 12:37:56 -07:00
|
|
|
/* recursive locks can't make use of any of this */
|
|
|
|
if (mutex->recursive) return ret;
|
2011-05-01 06:24:08 -07:00
|
|
|
mutex->locked = 1;
|
|
|
|
mutex->lock_thread_id = pthread_self();
|
2018-06-25 12:18:11 -07:00
|
|
|
/* backtrace() can somehow generate EINVAL even though this is not documented anywhere? */
|
|
|
|
int err = errno;
|
2011-05-01 06:24:08 -07:00
|
|
|
mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
|
2018-06-25 12:18:11 -07:00
|
|
|
errno = err;
|
2011-05-04 06:53:22 -07:00
|
|
|
|
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_append(_eina_tracking,
|
|
|
|
EINA_INLIST_GET(mutex));
|
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
2011-05-02 04:25:35 -07:00
|
|
|
#endif
|
2011-05-04 06:53:22 -07:00
|
|
|
|
2011-05-01 06:24:08 -07:00
|
|
|
return ret;
|
2011-04-22 14:26:36 -07:00
|
|
|
}
|
|
|
|
|
2011-05-02 01:24:06 -07:00
|
|
|
static inline Eina_Lock_Result
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(Eina_Lock *mutex)
|
2011-04-22 14:26:36 -07:00
|
|
|
{
|
2015-12-10 02:02:28 -08:00
|
|
|
Eina_Lock_Result ret = EINA_LOCK_FAIL;
|
|
|
|
int ok;
|
2011-05-02 04:25:35 -07:00
|
|
|
|
2011-05-02 06:40:28 -07:00
|
|
|
#ifdef EINA_HAVE_ON_OFF_THREADS
|
|
|
|
if (!_eina_threads_activated)
|
|
|
|
{
|
2011-05-04 06:53:22 -07:00
|
|
|
return EINA_LOCK_SUCCEED;
|
2011-05-02 06:40:28 -07:00
|
|
|
}
|
2011-05-02 04:25:35 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2018-06-15 12:37:56 -07:00
|
|
|
/* 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;
|
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
|
|
|
EINA_INLIST_GET(mutex));
|
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
|
|
|
}
|
2011-05-02 04:25:35 -07:00
|
|
|
#endif
|
2015-12-10 02:02:28 -08:00
|
|
|
ok = pthread_mutex_unlock(&(mutex->mutex));
|
|
|
|
if (ok == 0) ret = EINA_LOCK_SUCCEED;
|
|
|
|
else if (ok == EPERM) ret = EINA_LOCK_FAIL;
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, unlock, mutex);
|
2011-05-01 06:24:08 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-09 03:32:56 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
return _eina_condition_new(cond, mutex);
|
2011-05-09 03:32:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
eina_condition_free(Eina_Condition *cond)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
_eina_condition_free(cond);
|
2011-05-09 03:32:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
eina_condition_wait(Eina_Condition *cond)
|
|
|
|
{
|
2015-12-10 02:02:28 -08:00
|
|
|
Eina_Bool r = EINA_FALSE;
|
|
|
|
int ok;
|
2011-09-23 06:17:12 -07:00
|
|
|
|
2011-05-09 03:32:56 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
assert(_eina_threads_activated);
|
2011-05-09 07:41:39 -07:00
|
|
|
assert(cond->lock != NULL);
|
2011-09-23 06:17:12 -07:00
|
|
|
|
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
2016-09-18 16:58:56 -07:00
|
|
|
EINA_INLIST_GET(cond->lock));
|
2011-09-23 06:17:12 -07:00
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
|
|
|
#endif
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
ok = pthread_cond_wait(&(cond->condition), &(cond->lock->mutex));
|
|
|
|
if (ok == 0) r = EINA_TRUE;
|
|
|
|
else if (ok == EPERM) r = EINA_FALSE;
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, cond_wait, cond);
|
2011-09-23 06:17:12 -07:00
|
|
|
|
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_append(_eina_tracking,
|
2016-09-18 16:58:56 -07:00
|
|
|
EINA_INLIST_GET(cond->lock));
|
2011-09-23 06:17:12 -07:00
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
2011-05-09 03:32:56 -07:00
|
|
|
#endif
|
|
|
|
|
2011-09-23 06:17:12 -07:00
|
|
|
return r;
|
2011-05-30 08:24:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
eina_condition_timedwait(Eina_Condition *cond, double t)
|
|
|
|
{
|
2014-10-30 04:09:43 -07:00
|
|
|
struct timespec ts;
|
2014-10-27 07:47:51 -07:00
|
|
|
time_t sec;
|
|
|
|
long nsec;
|
2014-10-30 04:09:43 -07:00
|
|
|
int err;
|
2015-12-10 02:02:28 -08:00
|
|
|
Eina_Bool r = EINA_FALSE;
|
2014-10-27 07:47:51 -07:00
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
if (t >= 0.0)
|
2014-10-27 07:47:51 -07:00
|
|
|
{
|
2014-11-01 23:02:32 -07:00
|
|
|
#if defined(__clockid_t_defined)
|
2016-09-18 16:58:56 -07:00
|
|
|
if (cond->clkid)
|
|
|
|
{
|
|
|
|
if (clock_gettime(cond->clkid, &ts) != 0) return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else
|
2014-11-01 23:02:32 -07:00
|
|
|
#endif
|
2016-09-18 16:58:56 -07:00
|
|
|
{
|
|
|
|
/* Obsolete for Linux.
|
|
|
|
* TODO: use pthread_cond_timedwait_relative_np for OSX. */
|
|
|
|
struct timeval tv;
|
|
|
|
if (gettimeofday(&tv, NULL) != 0) return EINA_FALSE;
|
|
|
|
ts.tv_sec = tv.tv_sec;
|
|
|
|
ts.tv_nsec = tv.tv_usec * 1000L;
|
|
|
|
}
|
2014-10-30 04:09:43 -07:00
|
|
|
|
2011-05-30 08:24:06 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2016-09-18 16:58:56 -07:00
|
|
|
assert(_eina_threads_activated);
|
|
|
|
assert(cond->lock != NULL);
|
2011-09-23 06:17:12 -07:00
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
|
|
|
EINA_INLIST_GET(cond->lock));
|
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
2011-05-30 08:24:06 -07:00
|
|
|
#endif
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
sec = (time_t)t;
|
|
|
|
nsec = (t - (double)sec) * 1000000000L;
|
|
|
|
ts.tv_sec += sec;
|
|
|
|
ts.tv_nsec += nsec;
|
|
|
|
if (ts.tv_nsec > 1000000000L)
|
|
|
|
{
|
|
|
|
ts.tv_sec++;
|
|
|
|
ts.tv_nsec -= 1000000000L;
|
|
|
|
}
|
2011-05-30 08:24:06 -07:00
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
err = pthread_cond_timedwait(&(cond->condition),
|
|
|
|
&(cond->lock->mutex),
|
|
|
|
&ts);
|
|
|
|
if (err == 0) r = EINA_TRUE;
|
|
|
|
else if (err == EPERM) eina_error_set(EPERM);
|
|
|
|
else if (err == ETIMEDOUT) eina_error_set(ETIMEDOUT);
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(err, cond_timedwait, cond);
|
2011-09-23 06:17:12 -07:00
|
|
|
|
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
2016-09-18 16:58:56 -07:00
|
|
|
pthread_mutex_lock(&_eina_tracking_lock);
|
|
|
|
_eina_tracking = eina_inlist_append(_eina_tracking,
|
|
|
|
EINA_INLIST_GET(cond->lock));
|
|
|
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
2011-09-23 06:17:12 -07:00
|
|
|
#endif
|
2016-09-18 16:58:56 -07:00
|
|
|
}
|
|
|
|
errno = EINVAL;
|
2015-12-10 02:02:28 -08:00
|
|
|
return r;
|
2011-05-09 03:32:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
eina_condition_broadcast(Eina_Condition *cond)
|
|
|
|
{
|
2015-12-10 02:02:28 -08:00
|
|
|
int ok;
|
|
|
|
|
2011-05-09 07:41:39 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
assert(cond->lock != NULL);
|
|
|
|
#endif
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
ok = pthread_cond_broadcast(&(cond->condition));
|
|
|
|
if (ok == 0) return EINA_TRUE;
|
|
|
|
|
|
|
|
EINA_LOCK_ABORT_DEBUG(ok, cond_broadcast, cond);
|
|
|
|
return EINA_FALSE;
|
2011-05-09 03:32:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
eina_condition_signal(Eina_Condition *cond)
|
|
|
|
{
|
2015-12-10 02:02:28 -08:00
|
|
|
int ok;
|
|
|
|
|
2011-05-09 07:41:39 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
assert(cond->lock != NULL);
|
|
|
|
#endif
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
ok = pthread_cond_signal(&(cond->condition));
|
|
|
|
if (ok == 0) return EINA_TRUE;
|
|
|
|
|
|
|
|
EINA_LOCK_ABORT_DEBUG(ok, cond_signal, cond);
|
|
|
|
return EINA_FALSE;
|
2011-05-09 03:32:56 -07:00
|
|
|
}
|
|
|
|
|
2011-06-23 02:58:54 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
eina_rwlock_new(Eina_RWLock *mutex)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
return _eina_rwlock_new(mutex);
|
2011-06-23 02:58:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
eina_rwlock_free(Eina_RWLock *mutex)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
_eina_rwlock_free(mutex);
|
2011-06-23 02:58:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Lock_Result
|
|
|
|
eina_rwlock_take_read(Eina_RWLock *mutex)
|
|
|
|
{
|
2015-12-10 02:02:28 -08:00
|
|
|
int ok;
|
|
|
|
|
2011-06-23 02:58:54 -07:00
|
|
|
#ifdef EINA_HAVE_ON_OFF_THREADS
|
|
|
|
if (!_eina_threads_activated)
|
|
|
|
{
|
|
|
|
return EINA_LOCK_SUCCEED;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
ok = pthread_rwlock_rdlock(&(mutex->mutex));
|
|
|
|
if (ok == 0) return EINA_LOCK_SUCCEED;
|
|
|
|
else if (ok == EAGAIN || ok == ENOMEM) return EINA_LOCK_FAIL;
|
|
|
|
else if (ok == EDEADLK) EINA_LOCK_DEADLOCK_DEBUG(rwlock_rdlock, mutex);
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, rwlock_rdlock, mutex);
|
|
|
|
return EINA_LOCK_FAIL;
|
2011-06-23 02:58:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Lock_Result
|
|
|
|
eina_rwlock_take_write(Eina_RWLock *mutex)
|
|
|
|
{
|
2015-12-10 02:02:28 -08:00
|
|
|
int ok;
|
|
|
|
|
2011-06-23 02:58:54 -07:00
|
|
|
#ifdef EINA_HAVE_ON_OFF_THREADS
|
|
|
|
if (!_eina_threads_activated)
|
|
|
|
{
|
|
|
|
return EINA_LOCK_SUCCEED;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
ok = pthread_rwlock_wrlock(&(mutex->mutex));
|
|
|
|
if (ok == 0) return EINA_LOCK_SUCCEED;
|
|
|
|
else if (ok == ENOMEM) return EINA_LOCK_FAIL;
|
|
|
|
else if (ok == EDEADLK) EINA_LOCK_DEADLOCK_DEBUG(rwlock_wrlock, mutex);
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, rwlock_wrlock, mutex);
|
|
|
|
return EINA_LOCK_FAIL;
|
2011-06-23 02:58:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Lock_Result
|
|
|
|
eina_rwlock_release(Eina_RWLock *mutex)
|
|
|
|
{
|
2015-12-10 02:02:28 -08:00
|
|
|
int ok;
|
|
|
|
|
2011-06-23 02:58:54 -07:00
|
|
|
#ifdef EINA_HAVE_ON_OFF_THREADS
|
|
|
|
if (!_eina_threads_activated)
|
|
|
|
{
|
|
|
|
return EINA_LOCK_SUCCEED;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-12-10 02:02:28 -08:00
|
|
|
ok = pthread_rwlock_unlock(&(mutex->mutex));
|
|
|
|
if (ok == 0) return EINA_LOCK_SUCCEED;
|
|
|
|
else if (ok == EPERM) return EINA_LOCK_FAIL;
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, rwlock_unlock, mutex);
|
|
|
|
return EINA_LOCK_FAIL;
|
2011-06-23 02:58:54 -07:00
|
|
|
}
|
2011-05-09 03:32:56 -07:00
|
|
|
|
2014-01-22 21:50:08 -08:00
|
|
|
static inline Eina_Bool
|
|
|
|
eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
2011-10-16 22:06:01 -07:00
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
if (pthread_key_create(key, delete_cb) == 0) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2011-10-16 22:06:01 -07:00
|
|
|
}
|
|
|
|
|
2014-01-22 21:50:08 -08:00
|
|
|
static inline Eina_Bool
|
|
|
|
eina_tls_new(Eina_TLS *key)
|
|
|
|
{
|
|
|
|
return eina_tls_cb_new(key, NULL);
|
|
|
|
}
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
static inline void
|
2011-10-16 22:06:01 -07:00
|
|
|
eina_tls_free(Eina_TLS key)
|
|
|
|
{
|
|
|
|
pthread_key_delete(key);
|
|
|
|
}
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
static inline void *
|
2011-10-16 22:06:01 -07:00
|
|
|
eina_tls_get(Eina_TLS key)
|
|
|
|
{
|
|
|
|
return pthread_getspecific(key);
|
|
|
|
}
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
static inline Eina_Bool
|
2011-10-16 22:06:01 -07:00
|
|
|
eina_tls_set(Eina_TLS key, const void *data)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
if (pthread_setspecific(key, data) == 0) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2011-10-16 22:06:01 -07:00
|
|
|
}
|
|
|
|
|
2011-12-30 05:38:53 -08:00
|
|
|
|
2012-10-16 20:55:35 -07:00
|
|
|
#ifdef EINA_HAVE_PTHREAD_BARRIER
|
|
|
|
typedef struct _Eina_Barrier Eina_Barrier;
|
|
|
|
|
|
|
|
struct _Eina_Barrier
|
|
|
|
{
|
|
|
|
pthread_barrier_t barrier;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2016-09-18 16:58:56 -07:00
|
|
|
eina_barrier_wait(Eina_Barrier *barrier)
|
2012-10-16 20:55:35 -07:00
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
int ok = pthread_barrier_wait(&(barrier->barrier));
|
2015-12-10 02:02:28 -08:00
|
|
|
if (ok == 0) return EINA_TRUE;
|
2018-06-13 07:09:43 -07:00
|
|
|
else if (ok == PTHREAD_BARRIER_SERIAL_THREAD) return EINA_TRUE;
|
2016-09-18 16:58:56 -07:00
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, barrier_wait, barrier);
|
|
|
|
return EINA_TRUE;
|
2012-10-16 20:55:35 -07:00
|
|
|
}
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
#else
|
|
|
|
#include "eina_inline_lock_barrier.x"
|
|
|
|
#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)
|
2012-10-16 20:55:35 -07:00
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
return _eina_barrier_new(barrier, needed);
|
2012-10-16 20:55:35 -07:00
|
|
|
}
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
static inline void
|
|
|
|
eina_barrier_free(Eina_Barrier *barrier)
|
2012-10-16 20:55:35 -07:00
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
_eina_barrier_free(barrier);
|
2012-10-16 20:55:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-10 01:22:28 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
eina_spinlock_new(Eina_Spinlock *spinlock)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
return _eina_spinlock_new(spinlock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
eina_spinlock_free(Eina_Spinlock *spinlock)
|
|
|
|
{
|
|
|
|
_eina_spinlock_free(spinlock);
|
2013-10-10 01:22:28 -07:00
|
|
|
}
|
|
|
|
|
2018-06-25 12:15:29 -07:00
|
|
|
static inline Eina_Lock_Result
|
|
|
|
eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
|
|
|
{
|
|
|
|
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
|
|
|
int t = pthread_spin_trylock(spinlock);
|
|
|
|
if (t == 0) return EINA_LOCK_SUCCEED;
|
|
|
|
else if (t == EBUSY) return EINA_LOCK_FAIL;
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(t, spin_trylock, spinlock);
|
|
|
|
return EINA_LOCK_FAIL;
|
|
|
|
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
|
|
|
return _eina_spinlock_macos_take_try(spinlock);
|
|
|
|
#else
|
|
|
|
return eina_lock_take_try(spinlock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-10-10 01:22:28 -07:00
|
|
|
static inline Eina_Lock_Result
|
|
|
|
eina_spinlock_take(Eina_Spinlock *spinlock)
|
|
|
|
{
|
2014-08-21 02:23:24 -07:00
|
|
|
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
2013-10-10 01:22:28 -07:00
|
|
|
int t;
|
|
|
|
|
2018-06-25 12:15:32 -07:00
|
|
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
|
|
if (eina_spinlock_take_try(spinlock) == EINA_LOCK_SUCCEED) return EINA_LOCK_SUCCEED;
|
|
|
|
#endif
|
|
|
|
|
2016-09-18 16:58:56 -07:00
|
|
|
for (;;)
|
2015-12-10 02:02:28 -08:00
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
t = pthread_spin_lock(spinlock);
|
2015-12-10 02:02:28 -08:00
|
|
|
if (t == 0) break;
|
2016-09-18 16:58:56 -07:00
|
|
|
else EINA_LOCK_ABORT_DEBUG(t, spin_lock, spinlock);
|
2015-12-10 02:02:28 -08:00
|
|
|
}
|
2013-10-10 01:22:28 -07:00
|
|
|
|
2014-08-21 02:23:24 -07:00
|
|
|
return EINA_LOCK_SUCCEED;
|
|
|
|
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
2016-10-01 06:09:37 -07:00
|
|
|
return _eina_spinlock_macos_take(spinlock);
|
2013-10-10 01:22:28 -07:00
|
|
|
#else
|
|
|
|
return eina_lock_take(spinlock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Lock_Result
|
|
|
|
eina_spinlock_release(Eina_Spinlock *spinlock)
|
|
|
|
{
|
2014-08-21 02:23:24 -07:00
|
|
|
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
2016-09-18 16:58:56 -07:00
|
|
|
int ok = pthread_spin_unlock(spinlock);
|
2015-12-10 02:02:28 -08:00
|
|
|
if (ok == 0) return EINA_LOCK_SUCCEED;
|
|
|
|
else if (ok == EPERM) return EINA_LOCK_FAIL;
|
|
|
|
else EINA_LOCK_ABORT_DEBUG(ok, spin_unlock, spinlock);
|
|
|
|
return EINA_LOCK_FAIL;
|
2014-08-21 02:23:24 -07:00
|
|
|
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
2016-10-01 06:09:37 -07:00
|
|
|
return _eina_spinlock_macos_release(spinlock);
|
2013-10-10 01:22:28 -07:00
|
|
|
#else
|
|
|
|
return eina_lock_release(spinlock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-10-27 01:11:19 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
return _eina_semaphore_new(sem, count_init);
|
2014-10-27 01:11:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
eina_semaphore_free(Eina_Semaphore *sem)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
return _eina_semaphore_free(sem);
|
2014-10-27 01:11:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
eina_semaphore_lock(Eina_Semaphore *sem)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
if (sem)
|
2015-06-09 03:36:59 -07:00
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (
|
2014-10-27 01:11:19 -07:00
|
|
|
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
2016-09-18 16:58:56 -07:00
|
|
|
semaphore_wait(*sem)
|
2014-10-27 01:11:19 -07:00
|
|
|
#else
|
2016-09-18 16:58:56 -07:00
|
|
|
sem_wait(sem)
|
2014-10-27 01:11:19 -07:00
|
|
|
#endif
|
2016-09-18 16:58:56 -07:00
|
|
|
== 0)
|
|
|
|
return EINA_TRUE;
|
|
|
|
else if (errno != EINTR) goto err;
|
2015-06-09 03:36:59 -07:00
|
|
|
}
|
|
|
|
}
|
2016-09-18 16:58:56 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
err:
|
|
|
|
if (errno == EDEADLK) EINA_LOCK_DEADLOCK_DEBUG(sem_wait, sem);
|
|
|
|
return EINA_FALSE;
|
2014-10-27 01:11:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
|
|
|
|
{
|
2016-09-18 16:58:56 -07:00
|
|
|
if (sem)
|
2014-10-27 01:11:19 -07:00
|
|
|
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
2016-09-18 16:58:56 -07:00
|
|
|
return (semaphore_signal(*sem) == KERN_SUCCESS) ? EINA_TRUE : EINA_FALSE;
|
2014-10-27 01:11:19 -07:00
|
|
|
#else
|
2016-09-18 16:58:56 -07:00
|
|
|
return (sem_post(sem) == 0) ? EINA_TRUE : EINA_FALSE;
|
2014-10-27 01:11:19 -07:00
|
|
|
#endif
|
2016-09-18 16:58:56 -07:00
|
|
|
return EINA_FALSE;
|
2014-10-27 01:11:19 -07:00
|
|
|
}
|
|
|
|
|
2014-01-03 18:25:19 -08:00
|
|
|
#undef _XOPEN_SOURCE
|
|
|
|
// This is necessary to let third party still define this macro
|
|
|
|
#ifdef EINA_XOPEN_SOURCE
|
|
|
|
# define _XOPEN_SOURCE EINA_XOPEN_SOURCE
|
|
|
|
#endif
|
|
|
|
|
2011-04-22 14:26:36 -07:00
|
|
|
#endif
|