forked from enlightenment/efl
eina - redo a lot of the static inlines to have better instr cache usage
this moves a lot of logic that is rare away from the linear/flat asm path of code so we et fewer l1 cache misses when executing chuncks of our code. this also reduces the code size and takes some funcs like in eina_inline_lock_posix.x and makes them real functions to reduce code size thus better l1 cache usage - only for new/free of locks. spinlocks, semaphores etc. as these will have no advantage being inlined but simply bloat out code size instead. overall this actually reduces efl lib binary sizes 0.4%, so that's a good sign. this passes make check and i think i got it right... let me know if i didn't. i'm also not sure i should just keep the static inlines and not make the formerly static inline funcs full EAPI ones now... good q.
This commit is contained in:
parent
3efdd5df54
commit
41c332b726
|
@ -136,6 +136,7 @@ lib/eina/eina_inlist.c \
|
||||||
lib/eina/eina_iterator.c \
|
lib/eina/eina_iterator.c \
|
||||||
lib/eina/eina_lalloc.c \
|
lib/eina/eina_lalloc.c \
|
||||||
lib/eina/eina_list.c \
|
lib/eina/eina_list.c \
|
||||||
|
lib/eina/eina_lock.c \
|
||||||
lib/eina/eina_log.c \
|
lib/eina/eina_log.c \
|
||||||
lib/eina/eina_magic.c \
|
lib/eina/eina_magic.c \
|
||||||
lib/eina/eina_main.c \
|
lib/eina/eina_main.c \
|
||||||
|
|
|
@ -44,29 +44,26 @@ EAPI Eina_Bool eina_array_grow(Eina_Array *array);
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_array_push(Eina_Array *array, const void *data)
|
eina_array_push(Eina_Array *array, const void *data)
|
||||||
{
|
{
|
||||||
if (!data) return EINA_FALSE;
|
if (data)
|
||||||
|
{
|
||||||
|
if (EINA_UNLIKELY((array->count + 1) > array->total)) goto do_grow;
|
||||||
|
do_grow_back:
|
||||||
|
|
||||||
if (EINA_UNLIKELY((array->count + 1) > array->total))
|
array->data[array->count++] = (void*) data;
|
||||||
if (!eina_array_grow(array))
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
array->data[array->count++] = (void*) data;
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
return EINA_TRUE;
|
return EINA_FALSE;
|
||||||
|
do_grow:
|
||||||
|
if (!eina_array_grow(array)) return EINA_FALSE;
|
||||||
|
goto do_grow_back;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
eina_array_pop(Eina_Array *array)
|
eina_array_pop(Eina_Array *array)
|
||||||
{
|
{
|
||||||
void *ret = NULL;
|
if (array->count > 0) return array->data[--array->count];
|
||||||
|
return NULL;
|
||||||
if (array->count <= 0)
|
|
||||||
goto on_empty;
|
|
||||||
|
|
||||||
ret = array->data[--array->count];
|
|
||||||
|
|
||||||
on_empty:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
|
@ -104,12 +101,11 @@ eina_array_foreach(Eina_Array *array, Eina_Each_Cb cb, void *fdata)
|
||||||
Eina_Bool ret = EINA_TRUE;
|
Eina_Bool ret = EINA_TRUE;
|
||||||
|
|
||||||
EINA_ARRAY_ITER_NEXT(array, i, data, iterator)
|
EINA_ARRAY_ITER_NEXT(array, i, data, iterator)
|
||||||
if (cb(array, data, fdata) != EINA_TRUE)
|
{
|
||||||
{
|
if (cb(array, data, fdata) == EINA_TRUE) continue;
|
||||||
ret = EINA_FALSE;
|
ret = EINA_FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,13 @@ eina_hash_djb2(const char *key, int len)
|
||||||
unsigned int hash_num = 5381 ^ eina_seed;
|
unsigned int hash_num = 5381 ^ eina_seed;
|
||||||
const unsigned char *ptr;
|
const unsigned char *ptr;
|
||||||
|
|
||||||
if (!key) return 0;
|
if (key)
|
||||||
for (ptr = (unsigned char *)key; len; ptr++, len--)
|
{
|
||||||
hash_num = ((hash_num << 5) + hash_num) ^ *ptr; /* hash * 33 ^ c */
|
for (ptr = (unsigned char *)key; len; ptr++, len--)
|
||||||
|
hash_num = ((hash_num << 5) + hash_num) ^ *ptr; /* hash * 33 ^ c */
|
||||||
return (int)hash_num;
|
return (int)hash_num;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -47,14 +49,14 @@ eina_hash_djb2_len(const char *key, int *plen)
|
||||||
int len = 0;
|
int len = 0;
|
||||||
const unsigned char *ptr;
|
const unsigned char *ptr;
|
||||||
|
|
||||||
if (!key) return 0;
|
if (key)
|
||||||
|
{
|
||||||
for (ptr = (unsigned char *)key; *ptr; ptr++, len++)
|
for (ptr = (unsigned char *)key; *ptr; ptr++, len++)
|
||||||
hash_num = ((hash_num << 5) + hash_num) ^ *ptr; /* hash * 33 ^ c */
|
hash_num = ((hash_num << 5) + hash_num) ^ *ptr; /* hash * 33 ^ c */
|
||||||
|
*plen = len + 1;
|
||||||
*plen = len + 1;
|
return (int)hash_num;
|
||||||
|
}
|
||||||
return (int)hash_num;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
|
|
@ -24,11 +24,12 @@ eina_inlist_first(const Eina_Inlist *list)
|
||||||
{
|
{
|
||||||
Eina_Inlist *l;
|
Eina_Inlist *l;
|
||||||
|
|
||||||
if (!list) return NULL;
|
if (list)
|
||||||
|
{
|
||||||
for (l = (Eina_Inlist*)list; l->prev; l = l->prev);
|
for (l = (Eina_Inlist*)list; l->prev; l = l->prev);
|
||||||
|
return l;
|
||||||
return l;
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Inlist *
|
static inline Eina_Inlist *
|
||||||
|
@ -36,11 +37,12 @@ eina_inlist_last(const Eina_Inlist *list)
|
||||||
{
|
{
|
||||||
Eina_Inlist *l;
|
Eina_Inlist *l;
|
||||||
|
|
||||||
if (!list) return NULL;
|
if (list)
|
||||||
|
{
|
||||||
for (l = (Eina_Inlist*)list; l->next; l = l->next);
|
for (l = (Eina_Inlist*)list; l->next; l = l->next);
|
||||||
|
return l;
|
||||||
return l;
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* EINA_INLIST_INLINE_H_ */
|
#endif /* EINA_INLIST_INLINE_H_ */
|
||||||
|
|
|
@ -22,53 +22,55 @@
|
||||||
static inline Eina_List *
|
static inline Eina_List *
|
||||||
eina_list_last(const Eina_List *list)
|
eina_list_last(const Eina_List *list)
|
||||||
{
|
{
|
||||||
if (!list) return NULL;
|
if (list) return list->accounting->last;
|
||||||
return list->accounting->last;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_List *
|
static inline Eina_List *
|
||||||
eina_list_next(const Eina_List *list)
|
eina_list_next(const Eina_List *list)
|
||||||
{
|
{
|
||||||
if (!list) return NULL;
|
if (list) return list->next;
|
||||||
return list->next;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_List *
|
static inline Eina_List *
|
||||||
eina_list_prev(const Eina_List *list)
|
eina_list_prev(const Eina_List *list)
|
||||||
{
|
{
|
||||||
if (!list) return NULL;
|
if (list) return list->prev;
|
||||||
return list->prev;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
eina_list_data_get(const Eina_List *list)
|
eina_list_data_get(const Eina_List *list)
|
||||||
{
|
{
|
||||||
if (!list) return NULL;
|
if (list) return list->data;
|
||||||
return list->data;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
eina_list_data_set(Eina_List *list, const void *data)
|
eina_list_data_set(Eina_List *list, const void *data)
|
||||||
{
|
{
|
||||||
void *tmp;
|
if (list)
|
||||||
if (!list) return NULL;
|
{
|
||||||
tmp = list->data;
|
void *tmp = list->data;
|
||||||
list->data = (void*) data;
|
list->data = (void *) data;
|
||||||
return tmp;
|
return tmp;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
eina_list_count(const Eina_List *list)
|
eina_list_count(const Eina_List *list)
|
||||||
{
|
{
|
||||||
if (!list) return 0;
|
if (list) return list->accounting->count;
|
||||||
return list->accounting->count;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
eina_list_last_data_get(const Eina_List *list)
|
eina_list_last_data_get(const Eina_List *list)
|
||||||
{
|
{
|
||||||
if (!list) return NULL;
|
if (list) return eina_list_data_get(eina_list_last(list));
|
||||||
return eina_list_data_get(eina_list_last(list));
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* EINA_LIST_INLINE_H_ */
|
#endif /* EINA_LIST_INLINE_H_ */
|
||||||
|
|
|
@ -9,27 +9,6 @@ struct _Eina_Barrier
|
||||||
Eina_Condition cond; /**< The condition variable for the barrier */
|
Eina_Condition cond; /**< The condition variable for the barrier */
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline Eina_Bool
|
|
||||||
eina_barrier_new(Eina_Barrier *barrier, int needed)
|
|
||||||
{
|
|
||||||
barrier->needed = needed;
|
|
||||||
barrier->called = 0;
|
|
||||||
if (!eina_lock_new(&(barrier->cond_lock)))
|
|
||||||
return EINA_FALSE;
|
|
||||||
if (!eina_condition_new(&(barrier->cond), &(barrier->cond_lock)))
|
|
||||||
return EINA_FALSE;
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
eina_barrier_free(Eina_Barrier *barrier)
|
|
||||||
{
|
|
||||||
eina_condition_free(&(barrier->cond));
|
|
||||||
eina_lock_free(&(barrier->cond_lock));
|
|
||||||
barrier->needed = 0;
|
|
||||||
barrier->called = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_barrier_wait(Eina_Barrier *barrier)
|
eina_barrier_wait(Eina_Barrier *barrier)
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,21 +63,16 @@
|
||||||
typedef void (*Eina_Lock_Bt_Func) ();
|
typedef void (*Eina_Lock_Bt_Func) ();
|
||||||
|
|
||||||
#include "eina_inlist.h"
|
#include "eina_inlist.h"
|
||||||
#define EINA_LOCK_ABORT_DEBUG(err, fn, ptr) do { \
|
|
||||||
printf("EINA ERROR: '%s' on %s %p\n", strerror(err), #fn, ptr); \
|
|
||||||
abort(); \
|
|
||||||
} while (0)
|
|
||||||
#define EINA_LOCK_DEADLOCK_DEBUG(fn, ptr) do { \
|
|
||||||
printf("EINA ERROR: DEADLOCK on %s %p\n", #fn, ptr); \
|
|
||||||
abort(); \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define EINA_LOCK_ABORT_DEBUG(err, fn, ptr) \
|
|
||||||
printf("EINA ERROR: '%s' on %s %p\n", strerror(err), #fn, ptr)
|
|
||||||
#define EINA_LOCK_DEADLOCK_DEBUG(fn, ptr) \
|
|
||||||
printf("EINA ERROR: DEADLOCK on %s %p\n", #fn, ptr)
|
|
||||||
#endif
|
#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 */
|
/* For cond_timedwait */
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
@ -103,6 +98,8 @@ typedef semaphore_t Eina_Semaphore;
|
||||||
typedef sem_t Eina_Semaphore;
|
typedef sem_t Eina_Semaphore;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EAPI void eina_lock_debug(const Eina_Lock *mutex);
|
||||||
|
|
||||||
/** @privatesection @{ */
|
/** @privatesection @{ */
|
||||||
struct _Eina_Lock
|
struct _Eina_Lock
|
||||||
{
|
{
|
||||||
|
@ -145,91 +142,34 @@ EAPI extern pthread_mutex_t _eina_tracking_lock;
|
||||||
EAPI extern Eina_Inlist *_eina_tracking;
|
EAPI extern Eina_Inlist *_eina_tracking;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void
|
|
||||||
eina_lock_debug(const Eina_Lock *mutex)
|
EAPI Eina_Bool _eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive);
|
||||||
{
|
EAPI void _eina_lock_free(Eina_Lock *mutex);
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
EAPI Eina_Bool _eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
|
||||||
printf("lock %p, locked: %i, by %ti\n",
|
EAPI void _eina_condition_free(Eina_Condition *cond);
|
||||||
mutex, (int)mutex->locked, (ptrdiff_t)mutex->lock_thread_id);
|
EAPI Eina_Bool _eina_rwlock_new(Eina_RWLock *mutex);
|
||||||
backtrace_symbols_fd((void **)mutex->lock_bt, mutex->lock_bt_num, 1);
|
EAPI void _eina_rwlock_free(Eina_RWLock *mutex);
|
||||||
#else
|
EAPI Eina_Bool _eina_spinlock_new(Eina_Spinlock *spinlock);
|
||||||
(void) mutex;
|
EAPI void _eina_spinlock_free(Eina_Spinlock *spinlock);
|
||||||
#endif
|
EAPI Eina_Bool _eina_semaphore_new(Eina_Semaphore *sem, int count_init);
|
||||||
}
|
EAPI Eina_Bool _eina_semaphore_free(Eina_Semaphore *sem);
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_lock_new(Eina_Lock *mutex)
|
eina_lock_new(Eina_Lock *mutex)
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t attr;
|
return _eina_lock_new(mutex, EINA_FALSE);
|
||||||
Eina_Bool ok = EINA_FALSE;
|
|
||||||
|
|
||||||
#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)
|
|
||||||
goto fail_release;
|
|
||||||
memset(mutex, 0, sizeof(Eina_Lock));
|
|
||||||
#endif
|
|
||||||
if (pthread_mutex_init(&(mutex->mutex), &attr) != 0)
|
|
||||||
goto fail_release;
|
|
||||||
|
|
||||||
ok = EINA_TRUE;
|
|
||||||
fail_release:
|
|
||||||
pthread_mutexattr_destroy(&attr);
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_lock_recursive_new(Eina_Lock *mutex)
|
eina_lock_recursive_new(Eina_Lock *mutex)
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t attr;
|
return _eina_lock_new(mutex, EINA_TRUE);
|
||||||
Eina_Bool ok = EINA_FALSE;
|
|
||||||
|
|
||||||
#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;
|
|
||||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
|
|
||||||
goto fail_release;
|
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
||||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
|
|
||||||
goto fail_release;
|
|
||||||
memset(mutex, 0, sizeof(Eina_Lock));
|
|
||||||
#endif
|
|
||||||
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
|
static inline void
|
||||||
eina_lock_free(Eina_Lock *mutex)
|
eina_lock_free(Eina_Lock *mutex)
|
||||||
{
|
{
|
||||||
int ok;
|
_eina_lock_free(mutex);
|
||||||
|
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
||||||
if (!_eina_threads_activated)
|
|
||||||
assert(pthread_equal(_eina_main_loop, pthread_self()));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ok = pthread_mutex_destroy(&(mutex->mutex));
|
|
||||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, mutex_destroy, mutex);
|
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
||||||
memset(mutex, 0, sizeof(Eina_Lock));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Lock_Result
|
static inline Eina_Lock_Result
|
||||||
|
@ -278,9 +218,8 @@ eina_lock_take(Eina_Lock *mutex)
|
||||||
if (ok == 0) ret = EINA_LOCK_SUCCEED;
|
if (ok == 0) ret = EINA_LOCK_SUCCEED;
|
||||||
else if (ok == EDEADLK)
|
else if (ok == EDEADLK)
|
||||||
{
|
{
|
||||||
printf("EINA ERROR: DEADLOCK on lock %p\n", mutex);
|
|
||||||
eina_lock_debug(mutex);
|
eina_lock_debug(mutex);
|
||||||
ret = EINA_LOCK_DEADLOCK; // magic
|
ret = EINA_LOCK_DEADLOCK;
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
if (_eina_threads_debug) abort();
|
if (_eina_threads_debug) abort();
|
||||||
#endif
|
#endif
|
||||||
|
@ -326,8 +265,8 @@ eina_lock_take_try(Eina_Lock *mutex)
|
||||||
if (ok == 0) ret = EINA_LOCK_SUCCEED;
|
if (ok == 0) ret = EINA_LOCK_SUCCEED;
|
||||||
else if (ok == EDEADLK)
|
else if (ok == EDEADLK)
|
||||||
{
|
{
|
||||||
printf("EINA ERROR: DEADLOCK on trylock %p\n", mutex);
|
eina_lock_debug(mutex);
|
||||||
ret = EINA_LOCK_DEADLOCK; // magic
|
ret = EINA_LOCK_DEADLOCK;
|
||||||
}
|
}
|
||||||
else if (ok != EBUSY) EINA_LOCK_ABORT_DEBUG(ok, trylock, mutex);
|
else if (ok != EBUSY) EINA_LOCK_ABORT_DEBUG(ok, trylock, mutex);
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
@ -383,64 +322,13 @@ eina_lock_release(Eina_Lock *mutex)
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||||
{
|
{
|
||||||
pthread_condattr_t attr;
|
return _eina_condition_new(cond, mutex);
|
||||||
int ok;
|
|
||||||
|
|
||||||
#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;
|
|
||||||
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)
|
|
||||||
printf("eina_condition_new on already initialized Eina_Condition\n");
|
|
||||||
#endif
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_condattr_destroy(&attr);
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
eina_condition_free(Eina_Condition *cond)
|
eina_condition_free(Eina_Condition *cond)
|
||||||
{
|
{
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
_eina_condition_free(cond);
|
||||||
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
|
static inline Eina_Bool
|
||||||
|
@ -455,7 +343,7 @@ eina_condition_wait(Eina_Condition *cond)
|
||||||
|
|
||||||
pthread_mutex_lock(&_eina_tracking_lock);
|
pthread_mutex_lock(&_eina_tracking_lock);
|
||||||
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
||||||
EINA_INLIST_GET(cond->lock));
|
EINA_INLIST_GET(cond->lock));
|
||||||
pthread_mutex_unlock(&_eina_tracking_lock);
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -467,7 +355,7 @@ eina_condition_wait(Eina_Condition *cond)
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
pthread_mutex_lock(&_eina_tracking_lock);
|
pthread_mutex_lock(&_eina_tracking_lock);
|
||||||
_eina_tracking = eina_inlist_append(_eina_tracking,
|
_eina_tracking = eina_inlist_append(_eina_tracking,
|
||||||
EINA_INLIST_GET(cond->lock));
|
EINA_INLIST_GET(cond->lock));
|
||||||
pthread_mutex_unlock(&_eina_tracking_lock);
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -483,69 +371,60 @@ eina_condition_timedwait(Eina_Condition *cond, double t)
|
||||||
int err;
|
int err;
|
||||||
Eina_Bool r = EINA_FALSE;
|
Eina_Bool r = EINA_FALSE;
|
||||||
|
|
||||||
if (t < 0)
|
if (t >= 0.0)
|
||||||
{
|
{
|
||||||
errno = EINVAL;
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__clockid_t_defined)
|
#if defined(__clockid_t_defined)
|
||||||
if (cond->clkid)
|
if (cond->clkid)
|
||||||
{
|
{
|
||||||
if (clock_gettime(cond->clkid, &ts) != 0)
|
if (clock_gettime(cond->clkid, &ts) != 0) return EINA_FALSE;
|
||||||
return EINA_FALSE;
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* Obsolete for Linux.
|
/* Obsolete for Linux.
|
||||||
* TODO: use pthread_cond_timedwait_relative_np for OSX. */
|
* TODO: use pthread_cond_timedwait_relative_np for OSX. */
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
if (gettimeofday(&tv, NULL) != 0)
|
if (gettimeofday(&tv, NULL) != 0) return EINA_FALSE;
|
||||||
return EINA_FALSE;
|
ts.tv_sec = tv.tv_sec;
|
||||||
|
ts.tv_nsec = tv.tv_usec * 1000L;
|
||||||
ts.tv_sec = tv.tv_sec;
|
}
|
||||||
ts.tv_nsec = tv.tv_usec * 1000L;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
assert(_eina_threads_activated);
|
assert(_eina_threads_activated);
|
||||||
assert(cond->lock != NULL);
|
assert(cond->lock != NULL);
|
||||||
|
|
||||||
pthread_mutex_lock(&_eina_tracking_lock);
|
pthread_mutex_lock(&_eina_tracking_lock);
|
||||||
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
_eina_tracking = eina_inlist_remove(_eina_tracking,
|
||||||
EINA_INLIST_GET(cond->lock));
|
EINA_INLIST_GET(cond->lock));
|
||||||
pthread_mutex_unlock(&_eina_tracking_lock);
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sec = (time_t)t;
|
sec = (time_t)t;
|
||||||
nsec = (t - (double) sec) * 1000000000L;
|
nsec = (t - (double)sec) * 1000000000L;
|
||||||
ts.tv_sec += sec;
|
ts.tv_sec += sec;
|
||||||
ts.tv_nsec += nsec;
|
ts.tv_nsec += nsec;
|
||||||
if (ts.tv_nsec > 1000000000L)
|
if (ts.tv_nsec > 1000000000L)
|
||||||
{
|
{
|
||||||
ts.tv_sec++;
|
ts.tv_sec++;
|
||||||
ts.tv_nsec -= 1000000000L;
|
ts.tv_nsec -= 1000000000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pthread_cond_timedwait(&(cond->condition),
|
err = pthread_cond_timedwait(&(cond->condition),
|
||||||
&(cond->lock->mutex),
|
&(cond->lock->mutex),
|
||||||
&ts);
|
&ts);
|
||||||
if (err == 0)
|
if (err == 0) r = EINA_TRUE;
|
||||||
r = EINA_TRUE;
|
else if (err == EPERM) eina_error_set(EPERM);
|
||||||
else if (err == EPERM)
|
else if (err == ETIMEDOUT) eina_error_set(ETIMEDOUT);
|
||||||
eina_error_set(EPERM);
|
else EINA_LOCK_ABORT_DEBUG(err, cond_timedwait, cond);
|
||||||
else if (err == ETIMEDOUT)
|
|
||||||
eina_error_set(ETIMEDOUT);
|
|
||||||
else EINA_LOCK_ABORT_DEBUG(err, cond_timedwait, cond);
|
|
||||||
|
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
pthread_mutex_lock(&_eina_tracking_lock);
|
pthread_mutex_lock(&_eina_tracking_lock);
|
||||||
_eina_tracking = eina_inlist_append(_eina_tracking,
|
_eina_tracking = eina_inlist_append(_eina_tracking,
|
||||||
EINA_INLIST_GET(cond->lock));
|
EINA_INLIST_GET(cond->lock));
|
||||||
pthread_mutex_unlock(&_eina_tracking_lock);
|
pthread_mutex_unlock(&_eina_tracking_lock);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
errno = EINVAL;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,29 +463,13 @@ eina_condition_signal(Eina_Condition *cond)
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_rwlock_new(Eina_RWLock *mutex)
|
eina_rwlock_new(Eina_RWLock *mutex)
|
||||||
{
|
{
|
||||||
int ok;
|
return _eina_rwlock_new(mutex);
|
||||||
|
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
|
||||||
if (!_eina_threads_activated)
|
|
||||||
assert(pthread_equal(_eina_main_loop, pthread_self()));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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
|
static inline void
|
||||||
eina_rwlock_free(Eina_RWLock *mutex)
|
eina_rwlock_free(Eina_RWLock *mutex)
|
||||||
{
|
{
|
||||||
#ifdef EINA_HAVE_DEBUG_THREADS
|
_eina_rwlock_free(mutex);
|
||||||
if (!_eina_threads_activated)
|
|
||||||
assert(pthread_equal(_eina_main_loop, pthread_self()));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pthread_rwlock_destroy(&(mutex->mutex));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Lock_Result
|
static inline Eina_Lock_Result
|
||||||
|
@ -680,9 +543,8 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
||||||
static inline Eina_Bool
|
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)
|
if (pthread_key_create(key, delete_cb) == 0) return EINA_TRUE;
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
|
@ -706,9 +568,8 @@ eina_tls_get(Eina_TLS key)
|
||||||
static inline Eina_Bool
|
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)
|
if (pthread_setspecific(key, data) == 0) return EINA_TRUE;
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -720,31 +581,12 @@ struct _Eina_Barrier
|
||||||
pthread_barrier_t barrier;
|
pthread_barrier_t barrier;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline Eina_Bool
|
|
||||||
eina_barrier_new(Eina_Barrier *barrier, int needed)
|
|
||||||
{
|
|
||||||
int ok;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
eina_barrier_free(Eina_Barrier *barrier)
|
|
||||||
{
|
|
||||||
int ok;
|
|
||||||
ok = pthread_barrier_destroy(&(barrier->barrier));
|
|
||||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, barrier_destroy, barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_barrier_wait(Eina_Barrier *barrier)
|
eina_barrier_wait(Eina_Barrier *barrier)
|
||||||
{
|
{
|
||||||
int ok;
|
int ok = pthread_barrier_wait(&(barrier->barrier));
|
||||||
ok = pthread_barrier_wait(&(barrier->barrier));
|
if (ok == 0) return EINA_TRUE;
|
||||||
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, barrier_wait, barrier);
|
else EINA_LOCK_ABORT_DEBUG(ok, barrier_wait, barrier);
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,24 +594,32 @@ eina_barrier_wait(Eina_Barrier *barrier)
|
||||||
#include "eina_inline_lock_barrier.x"
|
#include "eina_inline_lock_barrier.x"
|
||||||
#endif
|
#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)
|
||||||
|
{
|
||||||
|
return _eina_barrier_new(barrier, needed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
eina_barrier_free(Eina_Barrier *barrier)
|
||||||
|
{
|
||||||
|
_eina_barrier_free(barrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_spinlock_new(Eina_Spinlock *spinlock)
|
eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||||
{
|
{
|
||||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
return _eina_spinlock_new(spinlock);
|
||||||
int ok;
|
}
|
||||||
ok = pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE);
|
|
||||||
if (ok == 0) return EINA_TRUE;
|
static inline void
|
||||||
else if (ok == EAGAIN || ok == ENOMEM) return EINA_FALSE;
|
eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||||
else EINA_LOCK_ABORT_DEBUG(ok, spin_init, spinlock);
|
{
|
||||||
return EINA_FALSE;
|
_eina_spinlock_free(spinlock);
|
||||||
#elif defined(EINA_HAVE_OSX_SPINLOCK)
|
|
||||||
/* OSSpinLock is an integer type. The convention is that unlocked is
|
|
||||||
* zero, and locked is nonzero. */
|
|
||||||
*spinlock = 0;
|
|
||||||
return EINA_TRUE;
|
|
||||||
#else
|
|
||||||
return eina_lock_new(spinlock);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Lock_Result
|
static inline Eina_Lock_Result
|
||||||
|
@ -778,12 +628,11 @@ eina_spinlock_take(Eina_Spinlock *spinlock)
|
||||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
while (EINA_TRUE)
|
for (;;)
|
||||||
{
|
{
|
||||||
t = pthread_spin_trylock(spinlock);
|
t = pthread_spin_lock(spinlock);
|
||||||
if (t == 0) break;
|
if (t == 0) break;
|
||||||
else if (t == EBUSY) sched_yield();
|
else EINA_LOCK_ABORT_DEBUG(t, spin_lock, spinlock);
|
||||||
else EINA_LOCK_ABORT_DEBUG(t, spin_trylock, spinlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EINA_LOCK_SUCCEED;
|
return EINA_LOCK_SUCCEED;
|
||||||
|
@ -802,9 +651,7 @@ static inline Eina_Lock_Result
|
||||||
eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
||||||
{
|
{
|
||||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
||||||
int t;
|
int t = pthread_spin_trylock(spinlock);
|
||||||
|
|
||||||
t = pthread_spin_trylock(spinlock);
|
|
||||||
if (t == 0) return EINA_LOCK_SUCCEED;
|
if (t == 0) return EINA_LOCK_SUCCEED;
|
||||||
else if (t == EBUSY) return EINA_LOCK_FAIL;
|
else if (t == EBUSY) return EINA_LOCK_FAIL;
|
||||||
else EINA_LOCK_ABORT_DEBUG(t, spin_trylock, spinlock);
|
else EINA_LOCK_ABORT_DEBUG(t, spin_trylock, spinlock);
|
||||||
|
@ -823,8 +670,7 @@ 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_POSIX_SPINLOCK)
|
||||||
int ok;
|
int ok = pthread_spin_unlock(spinlock);
|
||||||
ok = pthread_spin_unlock(spinlock);
|
|
||||||
if (ok == 0) return EINA_LOCK_SUCCEED;
|
if (ok == 0) return EINA_LOCK_SUCCEED;
|
||||||
else if (ok == EPERM) return EINA_LOCK_FAIL;
|
else if (ok == EPERM) return EINA_LOCK_FAIL;
|
||||||
else EINA_LOCK_ABORT_DEBUG(ok, spin_unlock, spinlock);
|
else EINA_LOCK_ABORT_DEBUG(ok, spin_unlock, spinlock);
|
||||||
|
@ -839,96 +685,52 @@ eina_spinlock_release(Eina_Spinlock *spinlock)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
eina_spinlock_free(Eina_Spinlock *spinlock)
|
|
||||||
{
|
|
||||||
#if defined(EINA_HAVE_POSIX_SPINLOCK)
|
|
||||||
int ok;
|
|
||||||
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
|
static inline Eina_Bool
|
||||||
eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
||||||
{
|
{
|
||||||
if (!sem || (count_init < 0))
|
return _eina_semaphore_new(sem, count_init);
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
|
||||||
kern_return_t kr;
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_semaphore_free(Eina_Semaphore *sem)
|
eina_semaphore_free(Eina_Semaphore *sem)
|
||||||
{
|
{
|
||||||
if (!sem)
|
return _eina_semaphore_free(sem);
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
|
||||||
return (semaphore_destroy(*sem, mach_task_self()) == KERN_SUCCESS)
|
|
||||||
? EINA_TRUE : EINA_FALSE;
|
|
||||||
#else
|
|
||||||
return (sem_destroy(sem) == 0) ? EINA_TRUE : EINA_FALSE;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_semaphore_lock(Eina_Semaphore *sem)
|
eina_semaphore_lock(Eina_Semaphore *sem)
|
||||||
{
|
{
|
||||||
Eina_Bool ok = EINA_FALSE;
|
if (sem)
|
||||||
|
|
||||||
if (!sem)
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
if (
|
for (;;)
|
||||||
|
{
|
||||||
|
if (
|
||||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||||
semaphore_wait(*sem)
|
semaphore_wait(*sem)
|
||||||
#else
|
#else
|
||||||
sem_wait(sem)
|
sem_wait(sem)
|
||||||
#endif
|
#endif
|
||||||
== 0)
|
== 0)
|
||||||
{
|
return EINA_TRUE;
|
||||||
ok = EINA_TRUE;
|
else if (errno != EINTR) goto err;
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (errno != EINTR)
|
|
||||||
{
|
|
||||||
if (errno == EDEADLK)
|
|
||||||
EINA_LOCK_DEADLOCK_DEBUG(sem_wait, sem);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ok;
|
return EINA_FALSE;
|
||||||
|
err:
|
||||||
|
if (errno == EDEADLK) EINA_LOCK_DEADLOCK_DEBUG(sem_wait, sem);
|
||||||
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
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 (sem)
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||||
return (semaphore_signal(*sem) == KERN_SUCCESS) ? EINA_TRUE : EINA_FALSE;
|
return (semaphore_signal(*sem) == KERN_SUCCESS) ? EINA_TRUE : EINA_FALSE;
|
||||||
#else
|
#else
|
||||||
return (sem_post(sem) == 0) ? EINA_TRUE : EINA_FALSE;
|
return (sem_post(sem) == 0) ? EINA_TRUE : EINA_FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef _XOPEN_SOURCE
|
#undef _XOPEN_SOURCE
|
||||||
|
|
|
@ -84,9 +84,9 @@ static inline Eina_Bool
|
||||||
eina_log_domain_level_check(int domain, int level)
|
eina_log_domain_level_check(int domain, int level)
|
||||||
{
|
{
|
||||||
int dom_level = eina_log_domain_registered_level_get(domain);
|
int dom_level = eina_log_domain_registered_level_get(domain);
|
||||||
if (EINA_UNLIKELY(dom_level == EINA_LOG_LEVEL_UNKNOWN))
|
if (EINA_LIKELY(dom_level != EINA_LOG_LEVEL_UNKNOWN))
|
||||||
return EINA_FALSE;
|
return dom_level >= level;
|
||||||
return dom_level >= level;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -94,16 +94,14 @@ static inline void *
|
||||||
eina_mempool_calloc(Eina_Mempool *mp, unsigned int size)
|
eina_mempool_calloc(Eina_Mempool *mp, unsigned int size)
|
||||||
{
|
{
|
||||||
void *r = mp->backend.alloc(mp->backend_data, size);
|
void *r = mp->backend.alloc(mp->backend_data, size);
|
||||||
if (!r) return NULL;
|
if (r) memset(r, 0, size);
|
||||||
memset(r, 0, size);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
eina_mempool_free(Eina_Mempool *mp, void *element)
|
eina_mempool_free(Eina_Mempool *mp, void *element)
|
||||||
{
|
{
|
||||||
if (!element) return ;
|
if (element) mp->backend.free(mp->backend_data, element);
|
||||||
mp->backend.free(mp->backend_data, element);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
|
@ -111,31 +109,33 @@ eina_mempool_alignof(unsigned int size)
|
||||||
{
|
{
|
||||||
unsigned int align;
|
unsigned int align;
|
||||||
|
|
||||||
if (EINA_UNLIKELY(size <= 2))
|
|
||||||
{
|
|
||||||
align = 2;
|
|
||||||
}
|
|
||||||
else if (EINA_UNLIKELY(size < 8))
|
|
||||||
{
|
|
||||||
align = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#if __WORDSIZE == 32
|
#if __WORDSIZE == 32
|
||||||
|
if (size >= 8)
|
||||||
{
|
{
|
||||||
align = 8;
|
align = 8;
|
||||||
|
calc:
|
||||||
|
return ((size / align) + (size % align ? 1 : 0)) * align;
|
||||||
}
|
}
|
||||||
#else
|
#else // __WORDSIZE == 64
|
||||||
if (EINA_UNLIKELY(size < 16))
|
if (size >= 16)
|
||||||
{
|
|
||||||
align = 8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
align = 16;
|
align = 16;
|
||||||
|
calc:
|
||||||
|
return ((size / align) + (size % align ? 1 : 0)) * align;
|
||||||
|
}
|
||||||
|
else if (size >= 8)
|
||||||
|
{
|
||||||
|
align = 8;
|
||||||
|
goto calc;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
else if (size >= 4)
|
||||||
return ((size / align) + (size % align ? 1 : 0)) * align;
|
{
|
||||||
|
align = 4;
|
||||||
|
goto calc;
|
||||||
|
}
|
||||||
|
align = 2;
|
||||||
|
goto calc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,13 +34,11 @@ eina_rbtree_inline_lookup(const Eina_Rbtree *root, const void *key, int length,
|
||||||
|
|
||||||
while (root)
|
while (root)
|
||||||
{
|
{
|
||||||
result = cmp(root, key, length, (void*) data);
|
result = cmp(root, key, length, (void *)data);
|
||||||
if (result == 0) return (Eina_Rbtree*) root;
|
if (result != 0) root = root->son[result < 0 ? 0 : 1];
|
||||||
|
else break;
|
||||||
root = root->son[result < 0 ? 0 : 1];
|
|
||||||
}
|
}
|
||||||
|
return (Eina_Rbtree *)root;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,9 +22,8 @@
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_rectangle_is_valid(const Eina_Rectangle *r)
|
eina_rectangle_is_valid(const Eina_Rectangle *r)
|
||||||
{
|
{
|
||||||
if (r->w <= 0 || r->h <= 0)
|
if ((r->w > 0) && (r->h > 0)) return EINA_TRUE;
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -36,7 +35,7 @@ eina_spans_intersect(int c1, int l1, int c2, int l2)
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_rectangle_is_empty(const Eina_Rectangle *r)
|
eina_rectangle_is_empty(const Eina_Rectangle *r)
|
||||||
{
|
{
|
||||||
return ((r->w < 1) || (r->h < 1)) ? EINA_TRUE : EINA_FALSE;
|
return !eina_rectangle_is_valid(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -98,39 +97,34 @@ eina_rectangle_union(Eina_Rectangle *dst, const Eina_Rectangle *src)
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_rectangle_intersection(Eina_Rectangle *dst, const Eina_Rectangle *src)
|
eina_rectangle_intersection(Eina_Rectangle *dst, const Eina_Rectangle *src)
|
||||||
{
|
{
|
||||||
if (!(eina_rectangle_is_valid(dst)) || !(eina_rectangle_is_valid(src)))
|
if (eina_rectangle_is_valid(dst) && eina_rectangle_is_valid(src) &&
|
||||||
return EINA_FALSE;
|
eina_rectangles_intersect(dst, src))
|
||||||
|
{
|
||||||
|
/* left */
|
||||||
|
if (dst->x < src->x)
|
||||||
|
{
|
||||||
|
dst->w += dst->x - src->x;
|
||||||
|
dst->x = src->x;
|
||||||
|
if (dst->w < 0) dst->w = 0;
|
||||||
|
}
|
||||||
|
/* right */
|
||||||
|
if ((dst->x + dst->w) > (src->x + src->w))
|
||||||
|
dst->w = src->x + src->w - dst->x;
|
||||||
|
/* top */
|
||||||
|
if (dst->y < src->y)
|
||||||
|
{
|
||||||
|
dst->h += dst->y - src->y;
|
||||||
|
dst->y = src->y;
|
||||||
|
if (dst->h < 0) dst->h = 0;
|
||||||
|
}
|
||||||
|
/* bottom */
|
||||||
|
if ((dst->y + dst->h) > (src->y + src->h))
|
||||||
|
dst->h = src->y + src->h - dst->y;
|
||||||
|
|
||||||
if (!(eina_rectangles_intersect(dst, src)))
|
if ((dst->w == 0) || (dst->h == 0)) return EINA_FALSE;
|
||||||
return EINA_FALSE;
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
/* left */
|
return EINA_FALSE;
|
||||||
if (dst->x < src->x)
|
|
||||||
{
|
|
||||||
dst->w += dst->x - src->x;
|
|
||||||
dst->x = src->x;
|
|
||||||
if (dst->w < 0)
|
|
||||||
dst->w = 0;
|
|
||||||
}
|
|
||||||
/* right */
|
|
||||||
if ((dst->x + dst->w) > (src->x + src->w))
|
|
||||||
dst->w = src->x + src->w - dst->x;
|
|
||||||
/* top */
|
|
||||||
if (dst->y < src->y)
|
|
||||||
{
|
|
||||||
dst->h += dst->y - src->y;
|
|
||||||
dst->y = src->y;
|
|
||||||
if (dst->h < 0)
|
|
||||||
dst->h = 0;
|
|
||||||
}
|
|
||||||
/* bottom */
|
|
||||||
if ((dst->y + dst->h) > (src->y + src->h))
|
|
||||||
dst->h = src->y + src->h - dst->y;
|
|
||||||
|
|
||||||
if (dst->w == 0 || dst->h == 0)
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -218,57 +212,57 @@ eina_rectangle_height_cut(Eina_Rectangle *thiz, Eina_Rectangle *slice, Eina_Rect
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_rectangle_subtract(Eina_Rectangle *thiz, Eina_Rectangle *other, Eina_Rectangle out[4])
|
eina_rectangle_subtract(Eina_Rectangle *thiz, Eina_Rectangle *other, Eina_Rectangle out[4])
|
||||||
{
|
{
|
||||||
Eina_Rectangle intersection;
|
Eina_Rectangle intersection;
|
||||||
Eina_Rectangle leftover = EINA_RECTANGLE_INIT;
|
Eina_Rectangle leftover = EINA_RECTANGLE_INIT;
|
||||||
Eina_Rectangle tmp;
|
Eina_Rectangle tmp;
|
||||||
int cut = 0;
|
int cut = 0;
|
||||||
|
|
||||||
if (!eina_rectangle_is_valid(thiz))
|
if (eina_rectangle_is_valid(thiz))
|
||||||
return EINA_FALSE;
|
{
|
||||||
|
eina_rectangle_coords_from(&out[0], 0, 0, 0, 0);
|
||||||
|
eina_rectangle_coords_from(&out[1], 0, 0, 0, 0);
|
||||||
|
eina_rectangle_coords_from(&out[2], 0, 0, 0, 0);
|
||||||
|
eina_rectangle_coords_from(&out[3], 0, 0, 0, 0);
|
||||||
|
intersection = *thiz;
|
||||||
|
if (!eina_rectangle_intersection(&intersection, other))
|
||||||
|
{
|
||||||
|
out[0] = *thiz;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
eina_rectangle_coords_from(&out[0], 0, 0, 0, 0);
|
/* cut in height */
|
||||||
eina_rectangle_coords_from(&out[1], 0, 0, 0, 0);
|
{
|
||||||
eina_rectangle_coords_from(&out[2], 0, 0, 0, 0);
|
cut = thiz->h - (intersection.y - thiz->y);
|
||||||
eina_rectangle_coords_from(&out[3], 0, 0, 0, 0);
|
if (cut > thiz->h) cut = thiz->h;
|
||||||
intersection = *thiz;
|
eina_rectangle_height_cut(thiz, &leftover, &out[0], cut);
|
||||||
if (!eina_rectangle_intersection(&intersection, other))
|
}
|
||||||
{
|
/* cut in y */
|
||||||
out[0] = *thiz;
|
tmp = leftover;
|
||||||
return EINA_TRUE;
|
if (eina_rectangle_intersection(&tmp, &intersection))
|
||||||
}
|
{
|
||||||
|
cut = leftover.h - (eina_rectangle_max_y(&leftover) - eina_rectangle_max_y(&tmp));
|
||||||
/* cut in height */
|
if (cut > leftover.h) cut = leftover.h;
|
||||||
{
|
eina_rectangle_y_cut(&leftover, &leftover, &out[1], cut);
|
||||||
cut = thiz->h - (intersection.y - thiz->y);
|
}
|
||||||
if (cut > thiz->h) { cut = thiz->h; }
|
/* cut in width */
|
||||||
eina_rectangle_height_cut(thiz, &leftover, &out[0], cut);
|
tmp = leftover;
|
||||||
}
|
if (eina_rectangle_intersection(&tmp, &intersection))
|
||||||
/* cut in y */
|
{
|
||||||
tmp = leftover;
|
cut = leftover.w - (tmp.x - leftover.x);
|
||||||
if (eina_rectangle_intersection(&tmp, &intersection))
|
if (cut > leftover.w) cut = leftover.w;
|
||||||
{
|
eina_rectangle_width_cut(&leftover, &leftover, &out[2], cut);
|
||||||
cut = leftover.h - (eina_rectangle_max_y(&leftover) - eina_rectangle_max_y(&tmp));
|
}
|
||||||
if (cut > leftover.h) { cut = leftover.h; }
|
/* cut in x */
|
||||||
eina_rectangle_y_cut(&leftover, &leftover, &out[1], cut);
|
tmp = leftover;
|
||||||
}
|
if (eina_rectangle_intersection(&tmp, &intersection))
|
||||||
/* cut in width */
|
{
|
||||||
tmp = leftover;
|
cut = leftover.w - (eina_rectangle_max_x(&leftover) - eina_rectangle_max_x(&tmp));
|
||||||
if (eina_rectangle_intersection(&tmp, &intersection))
|
if (cut > leftover.w) cut = leftover.w;
|
||||||
{
|
eina_rectangle_x_cut(&leftover, &leftover, &out[3], cut);
|
||||||
cut = leftover.w - (tmp.x - leftover.x);
|
}
|
||||||
if (cut > leftover.w) { cut = leftover.w; }
|
return EINA_TRUE;
|
||||||
eina_rectangle_width_cut(&leftover, &leftover, &out[2], cut);
|
}
|
||||||
}
|
return EINA_FALSE;
|
||||||
/* cut in x */
|
|
||||||
tmp = leftover;
|
|
||||||
if (eina_rectangle_intersection(&tmp, &intersection))
|
|
||||||
{
|
|
||||||
cut = leftover.w - (eina_rectangle_max_x(&leftover) - eina_rectangle_max_x(&tmp));
|
|
||||||
if (cut > leftover.w) { cut = leftover.w; }
|
|
||||||
eina_rectangle_x_cut(&leftover, &leftover, &out[3], cut);
|
|
||||||
}
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -38,10 +38,8 @@ eina_slice_dup(const Eina_Slice slice)
|
||||||
if (ret.len == 0) return ret;
|
if (ret.len == 0) return ret;
|
||||||
|
|
||||||
ret.mem = malloc(ret.len);
|
ret.mem = malloc(ret.len);
|
||||||
if (!ret.mem)
|
if (ret.mem) memcpy(ret.mem, slice.mem, ret.len);
|
||||||
ret.len = 0;
|
else ret.len = 0;
|
||||||
else
|
|
||||||
memcpy(ret.mem, slice.mem, ret.len);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -99,16 +97,13 @@ eina_slice_seek(const Eina_Slice slice, ssize_t offset, int whence)
|
||||||
offset += slice.len;
|
offset += slice.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whence != SEEK_SET)
|
if (whence == SEEK_SET)
|
||||||
return ret;
|
{
|
||||||
|
if ((size_t)offset > slice.len) offset = slice.len;
|
||||||
if (offset < 0)
|
else if (offset < 0) offset = 0;
|
||||||
offset = 0;
|
ret.len = slice.len - offset;
|
||||||
else if ((size_t)offset > slice.len)
|
ret.mem = (const void *)(slice.bytes + offset);
|
||||||
offset = slice.len;
|
}
|
||||||
|
|
||||||
ret.len = slice.len - offset;
|
|
||||||
ret.mem = (const void *)(slice.bytes + offset);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,88 +121,88 @@ eina_rw_slice_seek(const Eina_Rw_Slice rw_slice, ssize_t offset, int whence)
|
||||||
offset += rw_slice.len;
|
offset += rw_slice.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whence != SEEK_SET)
|
if (whence == SEEK_SET)
|
||||||
return ret;
|
{
|
||||||
|
if ((size_t)offset > rw_slice.len) offset = rw_slice.len;
|
||||||
if (offset < 0)
|
else if (offset < 0) offset = 0;
|
||||||
offset = 0;
|
ret.len = rw_slice.len - offset;
|
||||||
else if ((size_t)offset > rw_slice.len)
|
ret.mem = (void *)(rw_slice.bytes + offset);
|
||||||
offset = rw_slice.len;
|
}
|
||||||
|
|
||||||
ret.len = rw_slice.len - offset;
|
|
||||||
ret.mem = (void *)(rw_slice.bytes + offset);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const void *
|
static inline const void *
|
||||||
eina_slice_strchr(const Eina_Slice slice, int c)
|
eina_slice_strchr(const Eina_Slice slice, int c)
|
||||||
{
|
{
|
||||||
if (slice.len == 0) return NULL;
|
if (slice.len != 0) return memchr(slice.mem, c, slice.len);
|
||||||
return memchr(slice.mem, c, slice.len);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline const void *
|
static inline const void *
|
||||||
eina_slice_find(const Eina_Slice slice, const Eina_Slice needle)
|
eina_slice_find(const Eina_Slice slice, const Eina_Slice needle)
|
||||||
{
|
{
|
||||||
Eina_Slice s, n;
|
Eina_Slice s, n;
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
|
||||||
if (slice.len == 0) return NULL;
|
if ((slice.len != 0) && (needle.len != 0) && (slice.len >= needle.len))
|
||||||
if (needle.len == 0) return NULL;
|
|
||||||
if (slice.len < needle.len) return NULL;
|
|
||||||
if (needle.len == 1) return eina_slice_strchr(slice, needle.bytes[0]);
|
|
||||||
if ((slice.len == needle.len) &&
|
|
||||||
(memcmp(slice.mem, needle.mem, needle.len) == 0))
|
|
||||||
return slice.mem;
|
|
||||||
|
|
||||||
s.mem = slice.mem;
|
|
||||||
s.len = slice.len - (needle.len - 1);
|
|
||||||
|
|
||||||
c = needle.bytes[0];
|
|
||||||
n.mem = (const void *)(needle.bytes + 1);
|
|
||||||
n.len = needle.len - 1;
|
|
||||||
|
|
||||||
while (s.len > 0)
|
|
||||||
{
|
{
|
||||||
const uint8_t *p = (const uint8_t *)eina_slice_strchr(s, c);
|
if (needle.len == 1) return eina_slice_strchr(slice, needle.bytes[0]);
|
||||||
size_t offset;
|
if ((slice.len == needle.len) &&
|
||||||
|
(memcmp(slice.mem, needle.mem, needle.len) == 0))
|
||||||
|
return slice.mem;
|
||||||
|
|
||||||
if (!p) return NULL;
|
s.mem = slice.mem;
|
||||||
|
s.len = slice.len - (needle.len - 1);
|
||||||
|
|
||||||
p++;
|
c = needle.bytes[0];
|
||||||
if (memcmp(p, n.mem, n.len) == 0)
|
n.mem = (const void *)(needle.bytes + 1);
|
||||||
return (const void *)(p - 1);
|
n.len = needle.len - 1;
|
||||||
|
|
||||||
offset = p - s.bytes;
|
while (s.len > 0)
|
||||||
s.bytes += offset;
|
{
|
||||||
s.len -= offset;
|
const uint8_t *p = (const uint8_t *)eina_slice_strchr(s, c);
|
||||||
|
size_t offset;
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
if (memcmp(p, n.mem, n.len) == 0)
|
||||||
|
return (const void *)(p - 1);
|
||||||
|
|
||||||
|
offset = p - s.bytes;
|
||||||
|
s.bytes += offset;
|
||||||
|
s.len -= offset;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_slice_startswith(const Eina_Slice slice, const Eina_Slice prefix)
|
eina_slice_startswith(const Eina_Slice slice, const Eina_Slice prefix)
|
||||||
{
|
{
|
||||||
if (prefix.len == 0) return EINA_FALSE;
|
if ((prefix.len != 0) && (slice.len >= prefix.len))
|
||||||
if (slice.len < prefix.len) return EINA_FALSE;
|
return memcmp(slice.mem, prefix.mem, prefix.len) == 0;
|
||||||
return memcmp(slice.mem, prefix.mem, prefix.len) == 0;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_slice_endswith(const Eina_Slice slice, const Eina_Slice suffix)
|
eina_slice_endswith(const Eina_Slice slice, const Eina_Slice suffix)
|
||||||
{
|
{
|
||||||
if (suffix.len == 0) return EINA_FALSE;
|
if ((suffix.len != 0) && (slice.len > suffix.len))
|
||||||
if (slice.len < suffix.len) return EINA_FALSE;
|
return memcmp(slice.bytes + slice.len - suffix.len,
|
||||||
return memcmp(slice.bytes + slice.len - suffix.len,
|
suffix.mem, suffix.len) == 0;
|
||||||
suffix.mem, suffix.len) == 0;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
eina_rw_slice_strchr(const Eina_Rw_Slice rw_slice, int c)
|
eina_rw_slice_strchr(const Eina_Rw_Slice rw_slice, int c)
|
||||||
{
|
{
|
||||||
if (rw_slice.len == 0) return NULL;
|
if (rw_slice.len != 0) return memchr(rw_slice.mem, c, rw_slice.len);
|
||||||
return memchr(rw_slice.mem, c, rw_slice.len);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *
|
static inline void *
|
||||||
|
@ -219,18 +214,18 @@ eina_rw_slice_find(const Eina_Rw_Slice rw_slice, const Eina_Slice needle)
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_rw_slice_startswith(const Eina_Rw_Slice rw_slice, const Eina_Slice prefix)
|
eina_rw_slice_startswith(const Eina_Rw_Slice rw_slice, const Eina_Slice prefix)
|
||||||
{
|
{
|
||||||
if (prefix.len == 0) return EINA_FALSE;
|
if ((prefix.len != 0) && (rw_slice.len >= prefix.len))
|
||||||
if (rw_slice.len < prefix.len) return EINA_FALSE;
|
return memcmp(rw_slice.mem, prefix.mem, prefix.len) == 0;
|
||||||
return memcmp(rw_slice.mem, prefix.mem, prefix.len) == 0;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_rw_slice_endswith(const Eina_Rw_Slice rw_slice, const Eina_Slice suffix)
|
eina_rw_slice_endswith(const Eina_Rw_Slice rw_slice, const Eina_Slice suffix)
|
||||||
{
|
{
|
||||||
if (suffix.len == 0) return EINA_FALSE;
|
if ((suffix.len != 0) && (rw_slice.len >= suffix.len))
|
||||||
if (rw_slice.len < suffix.len) return EINA_FALSE;
|
return memcmp(rw_slice.bytes + rw_slice.len - suffix.len,
|
||||||
return memcmp(rw_slice.bytes + rw_slice.len - suffix.len,
|
suffix.mem, suffix.len) == 0;
|
||||||
suffix.mem, suffix.len) == 0;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const void *
|
static inline const void *
|
||||||
|
@ -248,19 +243,17 @@ eina_rw_slice_end_get(const Eina_Rw_Slice rw_slice)
|
||||||
static inline char *
|
static inline char *
|
||||||
eina_slice_strdup(const Eina_Slice slice)
|
eina_slice_strdup(const Eina_Slice slice)
|
||||||
{
|
{
|
||||||
if (slice.len == 0)
|
if (slice.len != 0)
|
||||||
return strdup("");
|
|
||||||
else
|
|
||||||
return strndup((const char *)slice.mem, slice.len);
|
return strndup((const char *)slice.mem, slice.len);
|
||||||
|
return strdup("");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
eina_rw_slice_strdup(const Eina_Rw_Slice rw_slice)
|
eina_rw_slice_strdup(const Eina_Rw_Slice rw_slice)
|
||||||
{
|
{
|
||||||
if (rw_slice.len == 0)
|
if (rw_slice.len != 0)
|
||||||
return strdup("");
|
|
||||||
else
|
|
||||||
return strndup((const char *)rw_slice.mem, rw_slice.len);
|
return strndup((const char *)rw_slice.mem, rw_slice.len);
|
||||||
|
return strdup("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _EINA_INLINE_SLICE_H */
|
#endif /* _EINA_INLINE_SLICE_H */
|
||||||
|
|
|
@ -92,8 +92,7 @@ static inline Eina_Bool
|
||||||
eina_streq(const char *a, const char *b)
|
eina_streq(const char *a, const char *b)
|
||||||
{
|
{
|
||||||
if (a == b) return EINA_TRUE;
|
if (a == b) return EINA_TRUE;
|
||||||
if (!a) return EINA_FALSE;
|
if ((!a) || (!b)) return EINA_FALSE;
|
||||||
if (!b) return EINA_FALSE;
|
|
||||||
return !strcmp(a, b);
|
return !strcmp(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,270 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "eina_config.h"
|
||||||
|
#include "Eina.h"
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
_eina_lock_debug_abort(int err, const char *fn, const volatile void *ptr)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EINA ERROR: '%s' on %s %p\n", strerror(err), fn, ptr);
|
||||||
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
_eina_lock_debug_deadlock(const char *fn, const volatile void *ptr)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EINA ERROR: DEADLOCK on %s %p\n", fn, ptr);
|
||||||
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
eina_lock_debug(const Eina_Lock *mutex)
|
||||||
|
{
|
||||||
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
fprintf(stderr, "EINA ERROR: DEADLOCK on lock %p, locked: %i, by %ti\n",
|
||||||
|
mutex, (int)mutex->locked, (ptrdiff_t)mutex->lock_thread_id);
|
||||||
|
backtrace_symbols_fd((void **)mutex->lock_bt, mutex->lock_bt_num, 1);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "EINA ERROR: DEADLOCK on lock %p\n", mutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
_eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive)
|
||||||
|
{
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
Eina_Bool ok = EINA_FALSE;
|
||||||
|
|
||||||
|
#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;
|
||||||
|
if (recursive)
|
||||||
|
{
|
||||||
|
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) goto fail_release;
|
||||||
|
}
|
||||||
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) goto fail_release;
|
||||||
|
memset(mutex, 0, sizeof(Eina_Lock));
|
||||||
|
#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;
|
||||||
|
|
||||||
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
if (!_eina_threads_activated)
|
||||||
|
assert(pthread_equal(_eina_main_loop, pthread_self()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ok = pthread_mutex_destroy(&(mutex->mutex));
|
||||||
|
if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, mutex_destroy, mutex);
|
||||||
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
memset(mutex, 0, sizeof(Eina_Lock));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
_eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||||
|
{
|
||||||
|
pthread_condattr_t attr;
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
#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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI 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
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
_eina_rwlock_new(Eina_RWLock *mutex)
|
||||||
|
{
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
#ifdef EINA_HAVE_DEBUG_THREADS
|
||||||
|
if (!_eina_threads_activated)
|
||||||
|
assert(pthread_equal(_eina_main_loop, pthread_self()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
_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
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI 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
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
_eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||||
|
{
|
||||||
|
#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)
|
||||||
|
/* OSSpinLock is an integer type. The convention is that unlocked is
|
||||||
|
* * zero, and locked is nonzero. */
|
||||||
|
*spinlock = 0;
|
||||||
|
return EINA_TRUE;
|
||||||
|
#else
|
||||||
|
return eina_lock_new(spinlock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
_eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||||
|
{
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
_eina_semaphore_new(Eina_Semaphore *sem, int 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
_eina_semaphore_free(Eina_Semaphore *sem)
|
||||||
|
{
|
||||||
|
if (sem)
|
||||||
|
{
|
||||||
|
#if defined(EINA_HAVE_OSX_SEMAPHORE)
|
||||||
|
return (semaphore_destroy(*sem, mach_task_self()) == KERN_SUCCESS)
|
||||||
|
? EINA_TRUE : EINA_FALSE;
|
||||||
|
#else
|
||||||
|
return (sem_destroy(sem) == 0) ? EINA_TRUE : EINA_FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
|
@ -211,7 +211,7 @@ static inline Eina_Lock_Result eina_lock_release(Eina_Lock *mutex);
|
||||||
*
|
*
|
||||||
* @note If @c EINA_HAVE_DEBUG_THREADS is not defined, this function does nothing.
|
* @note If @c EINA_HAVE_DEBUG_THREADS is not defined, this function does nothing.
|
||||||
*/
|
*/
|
||||||
static inline void eina_lock_debug(const Eina_Lock *mutex);
|
EAPI void eina_lock_debug(const Eina_Lock *mutex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes a new condition variable.
|
* @brief Initializes a new condition variable.
|
||||||
|
|
Loading…
Reference in New Issue