From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- .../eina/src/include/eina_inline_lock_posix.x | 509 +++++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 libraries/eina/src/include/eina_inline_lock_posix.x (limited to 'libraries/eina/src/include/eina_inline_lock_posix.x') diff --git a/libraries/eina/src/include/eina_inline_lock_posix.x b/libraries/eina/src/include/eina_inline_lock_posix.x new file mode 100644 index 0000000..77f5b8b --- /dev/null +++ b/libraries/eina/src/include/eina_inline_lock_posix.x @@ -0,0 +1,509 @@ +/* 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 . + */ + +#ifndef EINA_INLINE_LOCK_POSIX_X_ +#define EINA_INLINE_LOCK_POSIX_X_ + +#include +#ifndef __USE_UNIX98 +# define __USE_UNIX98 +# include +# undef __USE_UNIX98 +#else +# include +#endif + +#include + +#ifdef EINA_HAVE_DEBUG_THREADS +#include +#include +#include +#include +#define EINA_LOCK_DEBUG_BT_NUM 64 +typedef void (*Eina_Lock_Bt_Func) (); + +#include "eina_inlist.h" +#endif + +typedef struct _Eina_Lock Eina_Lock; +typedef struct _Eina_RWLock Eina_RWLock; +typedef struct _Eina_Condition Eina_Condition; +typedef pthread_key_t Eina_TLS; + +struct _Eina_Lock +{ +#ifdef EINA_HAVE_DEBUG_THREADS + EINA_INLIST; +#endif + pthread_mutex_t mutex; +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_t lock_thread_id; + Eina_Lock_Bt_Func lock_bt[EINA_LOCK_DEBUG_BT_NUM]; + int lock_bt_num; + Eina_Bool locked : 1; +#endif +}; + +struct _Eina_Condition +{ + Eina_Lock *lock; + pthread_cond_t condition; +}; + +struct _Eina_RWLock +{ + pthread_rwlock_t mutex; +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_t lock_thread_wid; +#endif +}; + +EAPI extern Eina_Bool _eina_threads_activated; + +#ifdef EINA_HAVE_DEBUG_THREADS +# include + +EAPI extern int _eina_threads_debug; +EAPI extern pthread_t _eina_main_loop; +EAPI extern pthread_mutex_t _eina_tracking_lock; +EAPI extern Eina_Inlist *_eina_tracking; +#endif + +static inline void +eina_lock_debug(const Eina_Lock *mutex) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + printf("lock %p, locked: %i, by %i\n", + mutex, (int)mutex->locked, (int)mutex->lock_thread_id); + backtrace_symbols_fd((void **)mutex->lock_bt, mutex->lock_bt_num, 1); +#else + (void) mutex; +#endif +} + +static inline Eina_Bool +eina_lock_new(Eina_Lock *mutex) +{ + pthread_mutexattr_t attr; + +#ifdef EINA_HAVE_DEBUG_THREADS + if (!_eina_threads_activated) + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + + if (pthread_mutexattr_init(&attr) != 0) + return EINA_FALSE; + /* NOTE: PTHREAD_MUTEX_RECURSIVE is not allowed at all, you will break on/off + feature for sure with that change. */ +#ifdef EINA_HAVE_DEBUG_THREADS + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + return EINA_FALSE; + memset(mutex, 0, sizeof(Eina_Lock)); +#endif + if (pthread_mutex_init(&(mutex->mutex), &attr) != 0) + return EINA_FALSE; + + pthread_mutexattr_destroy(&attr); + + return EINA_TRUE; +} + +static inline void +eina_lock_free(Eina_Lock *mutex) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + if (!_eina_threads_activated) + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + + pthread_mutex_destroy(&(mutex->mutex)); +#ifdef EINA_HAVE_DEBUG_THREADS + memset(mutex, 0, sizeof(Eina_Lock)); +#endif +} + +static inline Eina_Lock_Result +eina_lock_take(Eina_Lock *mutex) +{ + Eina_Lock_Result ret = EINA_LOCK_FAIL; + int ok; + +#ifdef EINA_HAVE_ON_OFF_THREADS + if (!_eina_threads_activated) + { +#ifdef EINA_HAVE_DEBUG_THREADS + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + return EINA_LOCK_SUCCEED; + } +#endif + +#ifdef EINA_HAVE_DEBUG_THREADS + if (_eina_threads_debug) + { + struct timeval t0, t1; + int dt; + + gettimeofday(&t0, NULL); + ok = pthread_mutex_lock(&(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; + dt /= 1000; + + if (dt > _eina_threads_debug) abort(); + } + else + { +#endif + ok = pthread_mutex_lock(&(mutex->mutex)); +#ifdef EINA_HAVE_DEBUG_THREADS + } +#endif + + if (ok == 0) ret = EINA_LOCK_SUCCEED; + else if (ok == EDEADLK) + { + printf("ERROR ERROR: DEADLOCK on lock %p\n", mutex); + eina_lock_debug(mutex); + ret = EINA_LOCK_DEADLOCK; // magic +#ifdef EINA_HAVE_DEBUG_THREADS + if (_eina_threads_debug) abort(); +#endif + } + +#ifdef EINA_HAVE_DEBUG_THREADS + mutex->locked = 1; + mutex->lock_thread_id = pthread_self(); + mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM); + + 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; +} + +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) + { +#ifdef EINA_HAVE_DEBUG_THREADS + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + return EINA_LOCK_SUCCEED; + } +#endif + +#ifdef EINA_HAVE_DEBUG_THREADS + if (!_eina_threads_activated) + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + + ok = pthread_mutex_trylock(&(mutex->mutex)); + if (ok == 0) ret = EINA_LOCK_SUCCEED; + else if (ok == EDEADLK) + { + printf("ERROR ERROR: DEADLOCK on trylock %p\n", mutex); + ret = EINA_LOCK_DEADLOCK; // magic + } +#ifdef EINA_HAVE_DEBUG_THREADS + if (ret == EINA_LOCK_SUCCEED) + { + mutex->locked = 1; + mutex->lock_thread_id = pthread_self(); + mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM); + + 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; +} + +static inline Eina_Lock_Result +eina_lock_release(Eina_Lock *mutex) +{ + Eina_Lock_Result ret; + +#ifdef EINA_HAVE_ON_OFF_THREADS + if (!_eina_threads_activated) + { +#ifdef EINA_HAVE_DEBUG_THREADS + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + return EINA_LOCK_SUCCEED; + } +#endif + +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_mutex_lock(&_eina_tracking_lock); + _eina_tracking = eina_inlist_remove(_eina_tracking, + EINA_INLIST_GET(mutex)); + pthread_mutex_unlock(&_eina_tracking_lock); + + 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; +#endif + ret = (pthread_mutex_unlock(&(mutex->mutex)) == 0) ? + EINA_LOCK_SUCCEED : EINA_LOCK_FAIL; + return ret; +} + +static inline Eina_Bool +eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + assert(mutex != NULL); + if (!_eina_threads_activated) + assert(pthread_equal(_eina_main_loop, pthread_self())); + memset(cond, 0, sizeof (Eina_Condition)); +#endif + + cond->lock = mutex; + if (pthread_cond_init(&cond->condition, NULL) != 0) + { +#ifdef EINA_HAVE_DEBUG_THREADS + if (errno == EBUSY) + printf("eina_condition_new on already initialized Eina_Condition\n"); +#endif + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static inline void +eina_condition_free(Eina_Condition *cond) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + if (!_eina_threads_activated) + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + + pthread_cond_destroy(&(cond->condition)); +#ifdef EINA_HAVE_DEBUG_THREADS + memset(cond, 0, sizeof (Eina_Condition)); +#endif +} + +static inline Eina_Bool +eina_condition_wait(Eina_Condition *cond) +{ + Eina_Bool r; + +#ifdef EINA_HAVE_DEBUG_THREADS + assert(_eina_threads_activated); + assert(cond->lock != NULL); + + pthread_mutex_lock(&_eina_tracking_lock); + _eina_tracking = eina_inlist_remove(_eina_tracking, + EINA_INLIST_GET(cond->lock)); + pthread_mutex_unlock(&_eina_tracking_lock); +#endif + + r = pthread_cond_wait(&(cond->condition), + &(cond->lock->mutex)) == 0 ? EINA_TRUE : EINA_FALSE; + +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_mutex_lock(&_eina_tracking_lock); + _eina_tracking = eina_inlist_append(_eina_tracking, + EINA_INLIST_GET(cond->lock)); + pthread_mutex_unlock(&_eina_tracking_lock); +#endif + + return r; +} + +static inline Eina_Bool +eina_condition_timedwait(Eina_Condition *cond, double t) +{ + struct timespec tv; + Eina_Bool r; + +#ifdef EINA_HAVE_DEBUG_THREADS + assert(_eina_threads_activated); + assert(cond->lock != NULL); + + pthread_mutex_lock(&_eina_tracking_lock); + _eina_tracking = eina_inlist_remove(_eina_tracking, + EINA_INLIST_GET(cond->lock)); + pthread_mutex_unlock(&_eina_tracking_lock); +#endif + + tv.tv_sec = t; + tv.tv_nsec = (t - (double) tv.tv_sec) * 1000000000; + + r = pthread_cond_timedwait(&(cond->condition), + &(cond->lock->mutex), + &tv) == 0 ? + EINA_TRUE : EINA_FALSE; + +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_mutex_lock(&_eina_tracking_lock); + _eina_tracking = eina_inlist_append(_eina_tracking, + EINA_INLIST_GET(cond->lock)); + pthread_mutex_unlock(&_eina_tracking_lock); +#endif + + return r; +} + +static inline Eina_Bool +eina_condition_broadcast(Eina_Condition *cond) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + assert(cond->lock != NULL); +#endif + + return pthread_cond_broadcast(&(cond->condition)) == 0 ? EINA_TRUE : EINA_FALSE; +} + +static inline Eina_Bool +eina_condition_signal(Eina_Condition *cond) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + assert(cond->lock != NULL); +#endif + + return pthread_cond_signal(&(cond->condition)) == 0 ? EINA_TRUE : EINA_FALSE; +} + +static inline Eina_Bool +eina_rwlock_new(Eina_RWLock *mutex) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + if (!_eina_threads_activated) + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + + if (pthread_rwlock_init(&(mutex->mutex), NULL) != 0) + return EINA_FALSE; + return EINA_TRUE; +} + +static inline void +eina_rwlock_free(Eina_RWLock *mutex) +{ +#ifdef EINA_HAVE_DEBUG_THREADS + if (!_eina_threads_activated) + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + + pthread_rwlock_destroy(&(mutex->mutex)); +} + +static inline Eina_Lock_Result +eina_rwlock_take_read(Eina_RWLock *mutex) +{ +#ifdef EINA_HAVE_ON_OFF_THREADS + if (!_eina_threads_activated) + { +#ifdef EINA_HAVE_DEBUG_THREADS + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + return EINA_LOCK_SUCCEED; + } +#endif + + if (pthread_rwlock_rdlock(&(mutex->mutex)) != 0) + return EINA_LOCK_FAIL; + return EINA_LOCK_SUCCEED; +} + +static inline Eina_Lock_Result +eina_rwlock_take_write(Eina_RWLock *mutex) +{ +#ifdef EINA_HAVE_ON_OFF_THREADS + if (!_eina_threads_activated) + { +#ifdef EINA_HAVE_DEBUG_THREADS + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + return EINA_LOCK_SUCCEED; + } +#endif + + if (pthread_rwlock_wrlock(&(mutex->mutex)) != 0) + return EINA_LOCK_FAIL; + return EINA_LOCK_SUCCEED; +} + +static inline Eina_Lock_Result +eina_rwlock_release(Eina_RWLock *mutex) +{ +#ifdef EINA_HAVE_ON_OFF_THREADS + if (!_eina_threads_activated) + { +#ifdef EINA_HAVE_DEBUG_THREADS + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + return EINA_LOCK_SUCCEED; + } +#endif + + if (pthread_rwlock_unlock(&(mutex->mutex)) != 0) + return EINA_LOCK_FAIL; + return EINA_LOCK_SUCCEED; +} + +static inline Eina_Bool +eina_tls_new(Eina_TLS *key) +{ + if (pthread_key_create(key, NULL) != 0) + return EINA_FALSE; + return EINA_TRUE; +} + +static inline void +eina_tls_free(Eina_TLS key) +{ + pthread_key_delete(key); +} + +static inline void * +eina_tls_get(Eina_TLS key) +{ + return pthread_getspecific(key); +} + +static inline Eina_Bool +eina_tls_set(Eina_TLS key, const void *data) +{ + if (pthread_setspecific(key, data) != 0) + return EINA_FALSE; + return EINA_TRUE; +} + +#endif -- cgit v1.1