summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas <Coquinho@users.noreply.github.com>2020-04-30 14:11:51 -0300
committerGitHub <noreply@github.com>2020-04-30 14:11:51 -0300
commitea6d1c40eef1f5b02b3654ec6413d33106e3c078 (patch)
tree89a524de13f5b1582dad6d836c9888dbf30d7c2b
parent728e1afde96f2d58d18d5b7599a3c0dffbc55240 (diff)
Windows:eina: Add Thread synchronization (#34)
This should add all needed functions/structures for thread synchronization besides: - eina_condition initialization; - cond_timedwait.
-rw-r--r--src/lib/eina/eina_debug_bt.c4
-rw-r--r--src/lib/eina/eina_inline_lock_barrier.x26
-rw-r--r--src/lib/eina/eina_inline_lock_posix.x344
-rw-r--r--src/lib/eina/eina_inline_lock_win32.x747
-rw-r--r--src/lib/eina/eina_lock.c353
-rw-r--r--src/lib/eina/eina_lock.h74
-rw-r--r--src/lib/eina/eina_main.c17
-rw-r--r--src/lib/eina/meson.build27
-rw-r--r--src/lib/evil/unposix/meson.build1
-rw-r--r--src/lib/evil/unposix/pthread.h213
-rw-r--r--src/lib/evil/unposix/semaphore.h59
11 files changed, 1221 insertions, 644 deletions
diff --git a/src/lib/eina/eina_debug_bt.c b/src/lib/eina/eina_debug_bt.c
index df96833c7d..3b23c622c1 100644
--- a/src/lib/eina/eina_debug_bt.c
+++ b/src/lib/eina/eina_debug_bt.c
@@ -49,7 +49,7 @@
49// broken on OSX in that a HUP signal will maybe cause a crash... but compiling 49// broken on OSX in that a HUP signal will maybe cause a crash... but compiling
50// with -pg would have guaranteed always caused a crash before anyway. 50// with -pg would have guaranteed always caused a crash before anyway.
51// given OSX only supports "old-style" signals like: 51// given OSX only supports "old-style" signals like:
52// 52//
53// #define SIGHUP 1 /* hangup */ 53// #define SIGHUP 1 /* hangup */
54// #define SIGINT 2 /* interrupt */ 54// #define SIGINT 2 /* interrupt */
55// #define SIGQUIT 3 /* quit */ 55// #define SIGQUIT 3 /* quit */
@@ -90,7 +90,7 @@
90// #endif 90// #endif
91// #define SIGUSR1 30 /* user defined signal 1 */ 91// #define SIGUSR1 30 /* user defined signal 1 */
92// #define SIGUSR2 31 /* user defined signal 2 */ 92// #define SIGUSR2 31 /* user defined signal 2 */
93// 93//
94// (excerpt from OSX's signal.h - found at: 94// (excerpt from OSX's signal.h - found at:
95// http://github.com/st3fan/osx-10.9/blob/master/xnu-2422.1.72/bsd/sys/signal.h 95// http://github.com/st3fan/osx-10.9/blob/master/xnu-2422.1.72/bsd/sys/signal.h
96// pasting here due to how difficult it was to find a signal list for OSX) 96// pasting here due to how difficult it was to find a signal list for OSX)
diff --git a/src/lib/eina/eina_inline_lock_barrier.x b/src/lib/eina/eina_inline_lock_barrier.x
deleted file mode 100644
index 02f4bdc20d..0000000000
--- a/src/lib/eina/eina_inline_lock_barrier.x
+++ /dev/null
@@ -1,26 +0,0 @@
1typedef struct _Eina_Barrier Eina_Barrier;
2
3/** @private */
4struct _Eina_Barrier
5{
6 int needed; /**< The number of waiting threads that will cause the barrier to signal and reset. */
7 int called; /**< The number of threads that are waiting on this barrier. */
8 Eina_Lock cond_lock; /**< The lock for the barrier */
9 Eina_Condition cond; /**< The condition variable for the barrier */
10};
11
12static inline Eina_Bool
13eina_barrier_wait(Eina_Barrier *barrier)
14{
15 eina_lock_take(&(barrier->cond_lock));
16 barrier->called++;
17 if (barrier->called == barrier->needed)
18 {
19 barrier->called = 0;
20 eina_condition_broadcast(&(barrier->cond));
21 }
22 else
23 eina_condition_wait(&(barrier->cond));
24 eina_lock_release(&(barrier->cond_lock));
25 return EINA_TRUE;
26}
diff --git a/src/lib/eina/eina_inline_lock_posix.x b/src/lib/eina/eina_inline_lock_posix.x
index 911b5c1f3b..8dbcf7693e 100644
--- a/src/lib/eina/eina_inline_lock_posix.x
+++ b/src/lib/eina/eina_inline_lock_posix.x
@@ -25,7 +25,26 @@
25#endif 25#endif
26#define _XOPEN_SOURCE 600 26#define _XOPEN_SOURCE 600
27 27
28#ifdef EINA_HAVE_POSIX_SPINLOCK 28#ifdef EINA_HAVE_OSX_SPINLOCK
29/*
30 * macOS 10.12 introduced the os_unfair_lock API which
31 * deprecates OSSpinLock, while keeping compatible.
32 *
33 * The Spinlock API is not inlined because it would imply including
34 * stdbool.h, which is not wanted: it would introduce new macros,
35 * and break compilation of existing programs.
36 */
37# if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
38# include <os/lock.h>
39# define SPINLOCK_GET(LCK) ((os_unfair_lock_t)(LCK))
40# else
41# include <libkern/OSAtomic.h>
42# define SPINLOCK_GET(LCK) ((OSSpinLock *)(LCK))
43# define os_unfair_lock_lock(LCK) OSSpinLockLock(LCK)
44# define os_unfair_lock_unlock(LCK) OSSpinLockUnlock(LCK)
45# define os_unfair_lock_trylock(LCK) OSSpinLockTry(LCK)
46# endif
47#elif defined(EINA_HAVE_PTHREAD_SPINLOCK)
29# include <sched.h> 48# include <sched.h>
30#endif 49#endif
31 50
@@ -80,7 +99,7 @@ typedef struct _Eina_RWLock Eina_RWLock;
80typedef struct _Eina_Condition Eina_Condition; 99typedef struct _Eina_Condition Eina_Condition;
81typedef pthread_key_t Eina_TLS; 100typedef pthread_key_t Eina_TLS;
82 101
83#if defined(EINA_HAVE_POSIX_SPINLOCK) 102#ifdef EINA_HAVE_PTHREAD_SPINLOCK
84typedef pthread_spinlock_t Eina_Spinlock; 103typedef pthread_spinlock_t Eina_Spinlock;
85#elif defined(EINA_HAVE_OSX_SPINLOCK) 104#elif defined(EINA_HAVE_OSX_SPINLOCK)
86typedef uintptr_t Eina_Spinlock; 105typedef uintptr_t Eina_Spinlock;
@@ -99,17 +118,15 @@ EAPI void eina_lock_debug(const Eina_Lock *mutex);
99/** @privatesection @{ */ 118/** @privatesection @{ */
100struct _Eina_Lock 119struct _Eina_Lock
101{ 120{
102#ifdef EINA_HAVE_DEBUG_THREADS
103 EINA_INLIST; /**< Keeps track of the threads waiting for the lock */
104#endif
105 pthread_mutex_t mutex; /**< The mutex that handles the locking */ 121 pthread_mutex_t mutex; /**< The mutex that handles the locking */
106#ifdef EINA_HAVE_DEBUG_THREADS 122#ifdef EINA_HAVE_DEBUG_THREADS
123 EINA_INLIST; /**< Keeps track of the threads waiting for the lock */
107 pthread_t lock_thread_id; /**< The ID of the thread that currently has the lock */ 124 pthread_t lock_thread_id; /**< The ID of the thread that currently has the lock */
108 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 */ 125 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 */
109 int lock_bt_num; /**< Number of addresses in the backtrace */ 126 int lock_bt_num; /**< Number of addresses in the backtrace */
110 Eina_Bool locked : 1; /**< Indicates locked or not locked */ 127 Eina_Bool locked : 1; /**< Indicates locked or not locked */
111 Eina_Bool recursive : 1; /**< Indicates recursive lock */ 128 Eina_Bool recursive : 1; /**< Indicates recursive lock */
112#endif 129#endif /* EINA_HAVE_DEBUG_THREADS */
113}; 130};
114 131
115struct _Eina_Condition 132struct _Eina_Condition
@@ -139,51 +156,29 @@ EAPI extern pthread_mutex_t _eina_tracking_lock;
139EAPI extern Eina_Inlist *_eina_tracking; 156EAPI extern Eina_Inlist *_eina_tracking;
140#endif 157#endif
141 158
142
143EAPI Eina_Bool _eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive);
144EAPI void _eina_lock_free(Eina_Lock *mutex);
145EAPI Eina_Bool _eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
146EAPI void _eina_condition_free(Eina_Condition *cond);
147EAPI Eina_Bool _eina_rwlock_new(Eina_RWLock *mutex);
148EAPI void _eina_rwlock_free(Eina_RWLock *mutex);
149EAPI Eina_Bool _eina_spinlock_new(Eina_Spinlock *spinlock);
150EAPI void _eina_spinlock_free(Eina_Spinlock *spinlock);
151EAPI Eina_Bool _eina_semaphore_new(Eina_Semaphore *sem, int count_init);
152EAPI Eina_Bool _eina_semaphore_free(Eina_Semaphore *sem);
153#ifdef EINA_HAVE_OSX_SPINLOCK
154EAPI Eina_Lock_Result _eina_spinlock_macos_take(Eina_Spinlock *spinlock);
155EAPI Eina_Lock_Result _eina_spinlock_macos_take_try(Eina_Spinlock *spinlock);
156EAPI Eina_Lock_Result _eina_spinlock_macos_release(Eina_Spinlock *spinlock);
157#endif
158
159static inline Eina_Bool 159static inline Eina_Bool
160eina_lock_new(Eina_Lock *mutex) 160_eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive)
161{ 161{
162 Eina_Bool ret = _eina_lock_new(mutex, EINA_FALSE); 162 pthread_mutexattr_t attr;
163#ifdef EINA_HAVE_DEBUG_THREADS 163 Eina_Bool ok = EINA_FALSE;
164 mutex->recursive = EINA_FALSE;
165 mutex->lock_thread_id = 0;
166 mutex->lock_bt_num = 0;
167 mutex->locked = 0;
168#endif
169 return ret;
170}
171 164
172static inline Eina_Bool 165 if (pthread_mutexattr_init(&attr) != 0) return EINA_FALSE;
173eina_lock_recursive_new(Eina_Lock *mutex) 166 if (recursive)
174{ 167 {
175 Eina_Bool ret = _eina_lock_new(mutex, EINA_TRUE); 168 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) goto fail_release;
169 }
176#ifdef EINA_HAVE_DEBUG_THREADS 170#ifdef EINA_HAVE_DEBUG_THREADS
177 mutex->recursive = EINA_TRUE; 171 else if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) goto fail_release;
178 mutex->lock_thread_id = 0;
179 mutex->lock_bt_num = 0;
180 mutex->locked = 0;
181#endif 172#endif
182 return ret; 173 if (pthread_mutex_init(&(mutex->mutex), &attr) != 0) goto fail_release;
174 ok = EINA_TRUE;
175fail_release:
176 pthread_mutexattr_destroy(&attr);
177 return ok;
183} 178}
184 179
185static inline void 180static inline void
186eina_lock_free(Eina_Lock *mutex) 181_eina_lock_free(Eina_Lock *mutex)
187{ 182{
188#ifdef EINA_HAVE_DEBUG_THREADS 183#ifdef EINA_HAVE_DEBUG_THREADS
189 if (mutex->locked) 184 if (mutex->locked)
@@ -194,11 +189,15 @@ eina_lock_free(Eina_Lock *mutex)
194 pthread_mutex_unlock(&_eina_tracking_lock); 189 pthread_mutex_unlock(&_eina_tracking_lock);
195 } 190 }
196#endif 191#endif
197 _eina_lock_free(mutex); 192
193 int ok;
194 ok = pthread_mutex_destroy(&(mutex->mutex));
195 if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, mutex_destroy, mutex);
198} 196}
199 197
198
200static inline Eina_Lock_Result 199static inline Eina_Lock_Result
201eina_lock_take_try(Eina_Lock *mutex) 200_eina_lock_take_try(Eina_Lock *mutex)
202{ 201{
203 Eina_Lock_Result ret = EINA_LOCK_FAIL; 202 Eina_Lock_Result ret = EINA_LOCK_FAIL;
204 int ok; 203 int ok;
@@ -240,7 +239,7 @@ eina_lock_take_try(Eina_Lock *mutex)
240} 239}
241 240
242static inline Eina_Lock_Result 241static inline Eina_Lock_Result
243eina_lock_take(Eina_Lock *mutex) 242_eina_lock_take(Eina_Lock *mutex)
244{ 243{
245 Eina_Lock_Result ret = EINA_LOCK_FAIL; 244 Eina_Lock_Result ret = EINA_LOCK_FAIL;
246 int ok; 245 int ok;
@@ -313,7 +312,7 @@ eina_lock_take(Eina_Lock *mutex)
313} 312}
314 313
315static inline Eina_Lock_Result 314static inline Eina_Lock_Result
316eina_lock_release(Eina_Lock *mutex) 315_eina_lock_release(Eina_Lock *mutex)
317{ 316{
318 Eina_Lock_Result ret = EINA_LOCK_FAIL; 317 Eina_Lock_Result ret = EINA_LOCK_FAIL;
319 int ok; 318 int ok;
@@ -347,19 +346,59 @@ eina_lock_release(Eina_Lock *mutex)
347} 346}
348 347
349static inline Eina_Bool 348static inline Eina_Bool
350eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex) 349_eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
351{ 350{
352 return _eina_condition_new(cond, mutex); 351 pthread_condattr_t attr;
352 int ok;
353
354#ifdef EINA_HAVE_DEBUG_THREADS
355 assert(mutex != NULL);
356#endif
357
358 cond->lock = mutex;
359 pthread_condattr_init(&attr);
360
361 /* OSX doesn't provide clockid_t or clock_gettime. */
362#if defined(__clockid_t_defined)
363 cond->clkid = (clockid_t) 0;
364 /* We try here to chose the best clock for cond_timedwait */
365# if defined(CLOCK_MONOTONIC_RAW)
366 if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC_RAW))
367 cond->clkid = CLOCK_MONOTONIC_RAW;
368# endif
369# if defined(CLOCK_MONOTONIC)
370 if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
371 cond->clkid = CLOCK_MONOTONIC;
372# endif
373# if defined(CLOCK_REALTIME)
374 if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_REALTIME))
375 cond->clkid = CLOCK_REALTIME;
376# endif
377#endif
378
379 ok = pthread_cond_init(&cond->condition, &attr);
380 if (ok != 0)
381 {
382 pthread_condattr_destroy(&attr);
383#ifdef EINA_HAVE_DEBUG_THREADS
384 if (ok == EBUSY)
385 fprintf(stderr, "EINA ERROR: eina_condition_new on already initialized Eina_Condition\n");
386#endif
387 return EINA_FALSE;
388 }
389
390 pthread_condattr_destroy(&attr);
391 return EINA_TRUE;
353} 392}
354 393
355static inline void 394static inline void
356eina_condition_free(Eina_Condition *cond) 395_eina_condition_free(Eina_Condition *cond)
357{ 396{
358 _eina_condition_free(cond); 397 pthread_cond_destroy(&(cond->condition));
359} 398}
360 399
361static inline Eina_Bool 400static inline Eina_Bool
362eina_condition_wait(Eina_Condition *cond) 401_eina_condition_wait(Eina_Condition *cond)
363{ 402{
364 Eina_Bool r = EINA_FALSE; 403 Eina_Bool r = EINA_FALSE;
365 int ok; 404 int ok;
@@ -390,7 +429,7 @@ eina_condition_wait(Eina_Condition *cond)
390} 429}
391 430
392static inline Eina_Bool 431static inline Eina_Bool
393eina_condition_timedwait(Eina_Condition *cond, double t) 432_eina_condition_timedwait(Eina_Condition *cond, double t)
394{ 433{
395 struct timespec ts; 434 struct timespec ts;
396 time_t sec; 435 time_t sec;
@@ -456,7 +495,7 @@ eina_condition_timedwait(Eina_Condition *cond, double t)
456} 495}
457 496
458static inline Eina_Bool 497static inline Eina_Bool
459eina_condition_broadcast(Eina_Condition *cond) 498_eina_condition_broadcast(Eina_Condition *cond)
460{ 499{
461 int ok; 500 int ok;
462 501
@@ -472,7 +511,7 @@ eina_condition_broadcast(Eina_Condition *cond)
472} 511}
473 512
474static inline Eina_Bool 513static inline Eina_Bool
475eina_condition_signal(Eina_Condition *cond) 514_eina_condition_signal(Eina_Condition *cond)
476{ 515{
477 int ok; 516 int ok;
478 517
@@ -488,19 +527,25 @@ eina_condition_signal(Eina_Condition *cond)
488} 527}
489 528
490static inline Eina_Bool 529static inline Eina_Bool
491eina_rwlock_new(Eina_RWLock *mutex) 530_eina_rwlock_new(Eina_RWLock *mutex)
492{ 531{
493 return _eina_rwlock_new(mutex); 532 int ok;
533
534 ok = pthread_rwlock_init(&(mutex->mutex), NULL);
535 if (ok == 0) return EINA_TRUE;
536 else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
537 else EINA_LOCK_ABORT_DEBUG(ok, rwlock_init, mutex);
538 return EINA_FALSE;
494} 539}
495 540
496static inline void 541static inline void
497eina_rwlock_free(Eina_RWLock *mutex) 542_eina_rwlock_free(Eina_RWLock *mutex)
498{ 543{
499 _eina_rwlock_free(mutex); 544 pthread_rwlock_destroy(&(mutex->mutex));
500} 545}
501 546
502static inline Eina_Lock_Result 547static inline Eina_Lock_Result
503eina_rwlock_take_read(Eina_RWLock *mutex) 548_eina_rwlock_take_read(Eina_RWLock *mutex)
504{ 549{
505 int ok; 550 int ok;
506 551
@@ -520,7 +565,7 @@ eina_rwlock_take_read(Eina_RWLock *mutex)
520} 565}
521 566
522static inline Eina_Lock_Result 567static inline Eina_Lock_Result
523eina_rwlock_take_write(Eina_RWLock *mutex) 568_eina_rwlock_take_write(Eina_RWLock *mutex)
524{ 569{
525 int ok; 570 int ok;
526 571
@@ -540,7 +585,7 @@ eina_rwlock_take_write(Eina_RWLock *mutex)
540} 585}
541 586
542static inline Eina_Lock_Result 587static inline Eina_Lock_Result
543eina_rwlock_release(Eina_RWLock *mutex) 588_eina_rwlock_release(Eina_RWLock *mutex)
544{ 589{
545 int ok; 590 int ok;
546 591
@@ -559,92 +604,167 @@ eina_rwlock_release(Eina_RWLock *mutex)
559} 604}
560 605
561static inline Eina_Bool 606static inline Eina_Bool
562eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb) 607_eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
563{ 608{
564 if (pthread_key_create(key, delete_cb) == 0) return EINA_TRUE; 609 if (pthread_key_create(key, delete_cb) == 0) return EINA_TRUE;
565 return EINA_FALSE; 610 return EINA_FALSE;
566} 611}
567 612
568static inline Eina_Bool
569eina_tls_new(Eina_TLS *key)
570{
571 return eina_tls_cb_new(key, NULL);
572}
573
574static inline void 613static inline void
575eina_tls_free(Eina_TLS key) 614_eina_tls_free(Eina_TLS key)
576{ 615{
577 pthread_key_delete(key); 616 pthread_key_delete(key);
578} 617}
579 618
580static inline void * 619static inline void *
581eina_tls_get(Eina_TLS key) 620_eina_tls_get(Eina_TLS key)
582{ 621{
583 return pthread_getspecific(key); 622 return pthread_getspecific(key);
584} 623}
585 624
586static inline Eina_Bool 625static inline Eina_Bool
587eina_tls_set(Eina_TLS key, const void *data) 626_eina_tls_set(Eina_TLS key, const void *data)
588{ 627{
589 if (pthread_setspecific(key, data) == 0) return EINA_TRUE; 628 if (pthread_setspecific(key, data) == 0) return EINA_TRUE;
590 return EINA_FALSE; 629 return EINA_FALSE;
591} 630}
592 631
593
594#ifdef EINA_HAVE_PTHREAD_BARRIER
595typedef struct _Eina_Barrier Eina_Barrier; 632typedef struct _Eina_Barrier Eina_Barrier;
596 633
634#ifdef EINA_HAVE_PTHREAD_BARRIER
597struct _Eina_Barrier 635struct _Eina_Barrier
598{ 636{
599 pthread_barrier_t barrier; 637 pthread_barrier_t barrier;
600}; 638};
639#else
640struct _Eina_Barrier
641{
642 int needed; /**< The number of waiting threads that will cause the barrier to signal and reset. */
643 int called; /**< The number of threads that are waiting on this barrier. */
644 Eina_Lock cond_lock; /**< The lock for the barrier */
645 Eina_Condition cond; /**< The condition variable for the barrier */
646};
647#endif
601 648
602static inline Eina_Bool 649static inline Eina_Bool
603eina_barrier_wait(Eina_Barrier *barrier) 650_eina_barrier_new(Eina_Barrier *barrier, int needed)
604{ 651{
652#ifdef EINA_HAVE_PTHREAD_BARRIER
653 int ok = pthread_barrier_init(&(barrier->barrier), NULL, needed);
654 if (ok == 0) return EINA_TRUE;
655 else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
656 else EINA_LOCK_ABORT_DEBUG(ok, barrier_init, barrier);
657 return EINA_FALSE;
658#else
659 barrier->needed = needed;
660 barrier->called = 0;
661 if (eina_lock_new(&(barrier->cond_lock)))
662 {
663 if (eina_condition_new(&(barrier->cond), &(barrier->cond_lock)))
664 return EINA_TRUE;
665 }
666 return EINA_FALSE;
667#endif
668}
669
670static inline void
671_eina_barrier_free(Eina_Barrier *barrier)
672{
673#ifdef EINA_HAVE_PTHREAD_BARRIER
674 int ok = pthread_barrier_destroy(&(barrier->barrier));
675 if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, barrier_destroy, barrier);
676#else
677 eina_condition_free(&(barrier->cond));
678 eina_lock_free(&(barrier->cond_lock));
679 barrier->needed = 0;
680 barrier->called = 0;
681#endif
682}
683
684static inline Eina_Bool
685_eina_barrier_wait(Eina_Barrier *barrier)
686{
687#ifdef EINA_HAVE_PTHREAD_BARRIER
605 int ok = pthread_barrier_wait(&(barrier->barrier)); 688 int ok = pthread_barrier_wait(&(barrier->barrier));
606 if (ok == 0) return EINA_TRUE; 689 if (ok == 0) return EINA_TRUE;
607 else if (ok == PTHREAD_BARRIER_SERIAL_THREAD) return EINA_TRUE; 690 else if (ok == PTHREAD_BARRIER_SERIAL_THREAD) return EINA_TRUE;
608 else EINA_LOCK_ABORT_DEBUG(ok, barrier_wait, barrier); 691 else EINA_LOCK_ABORT_DEBUG(ok, barrier_wait, barrier);
609 return EINA_TRUE; 692 return EINA_TRUE;
610}
611
612#else 693#else
613#include "eina_inline_lock_barrier.x" 694 eina_lock_take(&(barrier->cond_lock));
614#endif 695 barrier->called++;
696 if (barrier->called == barrier->needed)
697 {
698 barrier->called = 0;
699 eina_condition_broadcast(&(barrier->cond));
700 }
701 else
702 eina_condition_wait(&(barrier->cond));
703 eina_lock_release(&(barrier->cond_lock));
704 return EINA_TRUE;
615 705
616EAPI Eina_Bool _eina_barrier_new(Eina_Barrier *barrier, int needed); 706#endif
617EAPI void _eina_barrier_free(Eina_Barrier *barrier); 707}
618 708
619static inline Eina_Bool 709static inline Eina_Bool
620eina_barrier_new(Eina_Barrier *barrier, int needed) 710_eina_spinlock_new(Eina_Spinlock *spinlock)
621{ 711{
622 return _eina_barrier_new(barrier, needed); 712#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
713 int ok = pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE);
714 if (ok == 0) return EINA_TRUE;
715 else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE;
716 else EINA_LOCK_ABORT_DEBUG(ok, spin_init, spinlock);
717 return EINA_FALSE;
718#elif defined(EINA_HAVE_OSX_SPINLOCK)
719 *spinlock = 0;
720 return EINA_TRUE;
721#else
722 return eina_lock_new(spinlock);
723#endif
623} 724}
624 725
625static inline void 726static inline void
626eina_barrier_free(Eina_Barrier *barrier) 727_eina_spinlock_free(Eina_Spinlock *spinlock)
627{ 728{
628 _eina_barrier_free(barrier); 729#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
730 int ok = pthread_spin_destroy(spinlock);
731 if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, spin_destroy, spinlock);
732#elif defined(EINA_HAVE_OSX_SPINLOCK)
733 /* Not applicable */
734 (void) spinlock;
735#else
736 eina_lock_free(spinlock);
737#endif
629} 738}
630 739
740#ifdef EINA_HAVE_OSX_SPINLOCK
741static inline Eina_Lock_Result
742_eina_spinlock_macos_take(Eina_Spinlock *spinlock)
743{
744 os_unfair_lock_lock(SPINLOCK_GET(spinlock));
745 return EINA_LOCK_SUCCEED;
746}
631 747
632static inline Eina_Bool 748static inline Eina_Lock_Result
633eina_spinlock_new(Eina_Spinlock *spinlock) 749_eina_spinlock_macos_take_try(Eina_Spinlock *spinlock)
634{ 750{
635 return _eina_spinlock_new(spinlock); 751 return (os_unfair_lock_trylock(SPINLOCK_GET(spinlock)) == true)
752 ? EINA_LOCK_SUCCEED
753 : EINA_LOCK_FAIL;
636} 754}
637 755
638static inline void 756static inline Eina_Lock_Result
639eina_spinlock_free(Eina_Spinlock *spinlock) 757_eina_spinlock_macos_release(Eina_Spinlock *spinlock)
640{ 758{
641 _eina_spinlock_free(spinlock); 759 os_unfair_lock_unlock(SPINLOCK_GET(spinlock));
760 return EINA_LOCK_SUCCEED;
642} 761}
762#endif /* EINA_HAVE_OSX_SPINLOCK */
643 763
644static inline Eina_Lock_Result 764static inline Eina_Lock_Result
645eina_spinlock_take_try(Eina_Spinlock *spinlock) 765_eina_spinlock_take_try(Eina_Spinlock *spinlock)
646{ 766{
647#if defined(EINA_HAVE_POSIX_SPINLOCK) 767#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
648 int t = pthread_spin_trylock(spinlock); 768 int t = pthread_spin_trylock(spinlock);
649 if (t == 0) return EINA_LOCK_SUCCEED; 769 if (t == 0) return EINA_LOCK_SUCCEED;
650 else if (t == EBUSY) return EINA_LOCK_FAIL; 770 else if (t == EBUSY) return EINA_LOCK_FAIL;
@@ -658,9 +778,9 @@ eina_spinlock_take_try(Eina_Spinlock *spinlock)
658} 778}
659 779
660static inline Eina_Lock_Result 780static inline Eina_Lock_Result
661eina_spinlock_take(Eina_Spinlock *spinlock) 781_eina_spinlock_take(Eina_Spinlock *spinlock)
662{ 782{
663#if defined(EINA_HAVE_POSIX_SPINLOCK) 783#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
664 int t; 784 int t;
665 785
666#ifdef EINA_HAVE_DEBUG_THREADS 786#ifdef EINA_HAVE_DEBUG_THREADS
@@ -683,9 +803,9 @@ eina_spinlock_take(Eina_Spinlock *spinlock)
683} 803}
684 804
685static inline Eina_Lock_Result 805static inline Eina_Lock_Result
686eina_spinlock_release(Eina_Spinlock *spinlock) 806_eina_spinlock_release(Eina_Spinlock *spinlock)
687{ 807{
688#if defined(EINA_HAVE_POSIX_SPINLOCK) 808#if defined(EINA_HAVE_PTHREAD_SPINLOCK)
689 int ok = pthread_spin_unlock(spinlock); 809 int ok = pthread_spin_unlock(spinlock);
690 if (ok == 0) return EINA_LOCK_SUCCEED; 810 if (ok == 0) return EINA_LOCK_SUCCEED;
691 else if (ok == EPERM) return EINA_LOCK_FAIL; 811 else if (ok == EPERM) return EINA_LOCK_FAIL;
@@ -699,19 +819,37 @@ eina_spinlock_release(Eina_Spinlock *spinlock)
699} 819}
700 820
701static inline Eina_Bool 821static inline Eina_Bool
702eina_semaphore_new(Eina_Semaphore *sem, int count_init) 822_eina_semaphore_new(Eina_Semaphore *sem, int count_init)
703{ 823{
704 return _eina_semaphore_new(sem, count_init); 824 if (sem && (count_init >= 0))
825 {
826#if defined(EINA_HAVE_OSX_SEMAPHORE)
827 kern_return_t kr = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, count_init);
828 return (kr == KERN_SUCCESS) ? EINA_TRUE : EINA_FALSE;
829#else
830 return (sem_init(sem, 0, count_init) == 0) ? EINA_TRUE : EINA_FALSE;
831#endif
832 }
833 return EINA_FALSE;
705} 834}
706 835
707static inline Eina_Bool 836static inline Eina_Bool
708eina_semaphore_free(Eina_Semaphore *sem) 837_eina_semaphore_free(Eina_Semaphore *sem)
709{ 838{
710 return _eina_semaphore_free(sem); 839 if (sem)
840 {
841#if defined(EINA_HAVE_OSX_SEMAPHORE)
842 return (semaphore_destroy(mach_task_self(), *sem) == KERN_SUCCESS)
843 ? EINA_TRUE : EINA_FALSE;
844#else
845 return (sem_destroy(sem) == 0) ? EINA_TRUE : EINA_FALSE;
846#endif
847 }
848 return EINA_FALSE;
711} 849}
712 850
713static inline Eina_Bool 851static inline Eina_Bool
714eina_semaphore_lock(Eina_Semaphore *sem) 852_eina_semaphore_lock(Eina_Semaphore *sem)
715{ 853{
716 if (sem) 854 if (sem)
717 { 855 {
@@ -735,7 +873,7 @@ err:
735} 873}
736 874
737static inline Eina_Bool 875static inline Eina_Bool
738eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED) 876_eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
739{ 877{
740 if (sem) 878 if (sem)
741#if defined(EINA_HAVE_OSX_SEMAPHORE) 879#if defined(EINA_HAVE_OSX_SEMAPHORE)
diff --git a/src/lib/eina/eina_inline_lock_win32.x b/src/lib/eina/eina_inline_lock_win32.x
new file mode 100644
index 0000000000..dc5c8659de
--- /dev/null
+++ b/src/lib/eina/eina_inline_lock_win32.x
@@ -0,0 +1,747 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2020 Lucas Cavalcante de Sousa
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef EINA_INLINE_LOCK_WIN32_X_
20#define EINA_INLINE_LOCK_WIN32_X_
21
22#ifndef WIN32_LEAN_AND_MEAN
23# define WIN32_LEAN_AND_MEAN
24#endif
25
26#include <Windows.h>
27#include <synchapi.h>
28#undef WIN32_LEAN_AND_MEAN
29
30#include "unimplemented.h"
31
32#include <errno.h>
33
34#include <sys/time.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38
39#include <sys/types.h>
40#include <unistd.h>
41
42#ifdef EINA_HAVE_DEBUG_THREADS
43#include <assert.h>
44#include <execinfo.h>
45#define EINA_LOCK_DEBUG_BT_NUM 64
46typedef void (*Eina_Lock_Bt_Func) ();
47
48#include "eina_inlist.h"
49#endif
50
51EAPI void _eina_lock_debug_abort(int err, const char *fn, const volatile void *ptr);
52EAPI void _eina_lock_debug_deadlock(const char *fn, const volatile void *ptr);
53
54#define EINA_LOCK_ABORT_DEBUG(err, fn, ptr) \
55 _eina_lock_debug_abort(err, #fn, ptr)
56#define EINA_LOCK_DEADLOCK_DEBUG(fn, ptr) \
57 _eina_lock_debug_deadlock(#fn, ptr)
58
59/* For cond_timedwait */
60#include <time.h>
61#include <sys/time.h>
62
63#include <eina_error.h>
64
65typedef struct _Eina_Lock Eina_Lock;
66typedef struct _Eina_RWLock Eina_RWLock;
67typedef struct _Eina_Condition Eina_Condition;
68typedef struct _Eina_Barrier Eina_Barrier;
69typedef LPDWORD Eina_TLS;
70typedef HANDLE Eina_Semaphore;
71
72#ifdef EINA_HAVE_WIN32_SPINLOCK
73typedef PCRITICAL_SECTION Eina_Spinlock;
74#else
75typedef Eina_Lock Eina_Spinlock;
76#endif
77
78EAPI void eina_lock_debug(const Eina_Lock *mutex);
79
80/** @privatesection @{ */
81typedef HANDLE _Eina_Thread;
82typedef PCRITICAL_SECTION _Eina_Mutex_t;
83typedef CONDITION_VARIABLE _Eina_Condition_t;
84typedef PSRWLOCK _Eina_RWLock_t;
85
86struct _Eina_Lock
87{
88 _Eina_Mutex_t mutex; /**< The mutex that handles the locking */
89#ifdef EINA_HAVE_DEBUG_THREADS
90 EINA_INLIST; /**< Keeps track of the threads waiting for the lock */
91 _Eina_Thread lock_thread_id; /**< The ID of the thread that currently has the lock */
92 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 */
93 int lock_bt_num; /**< Number of addresses in the backtrace */
94 Eina_Bool locked : 1; /**< Indicates locked or not locked */
95 Eina_Bool recursive : 1; /**< Indicates recursive lock */
96#endif /* EINA_HAVE_DEBUG_THREADS */
97};
98
99struct _Eina_Condition
100{
101 Eina_Lock *lock; /**< The lock for this condition */
102 _Eina_Condition_t condition; /**< The condition variable */
103#if defined(__clockid_t_defined)
104 clockid_t clkid; /**< The attached clock for timedwait */
105#endif
106};
107
108enum _Eina_RWLock_Mode {
109 _Eina_RWLock_Mode_Shared,
110 _Eina_RWLock_Mode_Exclusive,
111 _Eina_RWLock_Mode_None
112};
113
114struct _Eina_RWLock
115{
116 _Eina_RWLock_t mutex; /**< The mutex that handles the locking */
117#ifdef EINA_HAVE_DEBUG_THREADS
118 _Eina_Thread lock_thread_wid; /**< The ID of the thread that currently has the lock */
119#endif
120 enum _Eina_RWLock_Mode mode; /**< The mode the SRWLock is (Shared, Exclusive or None)*/
121};
122/** @} privatesection */
123
124EAPI extern Eina_Bool _eina_threads_activated;
125
126#ifdef EINA_HAVE_DEBUG_THREADS
127EAPI extern int _eina_threads_debug;
128EAPI extern _Eina_Thread _eina_main_loop;
129EAPI extern Eina_Lock _eina_tracking_lock;
130EAPI extern Eina_Inlist *_eina_tracking;
131#endif
132
133EAPI Eina_Bool eina_lock_new(Eina_Lock *mutex);
134EAPI void eina_lock_free(Eina_Lock *mutex);
135EAPI Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
136EAPI Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
137EAPI Eina_Lock_Result eina_lock_release(Eina_Lock *mutex);
138EAPI Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
139EAPI void eina_condition_free(Eina_Condition *cond);
140EAPI Eina_Bool eina_condition_wait(Eina_Condition *cond);
141EAPI Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
142
143static inline Eina_Bool
144_eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive)
145{
146 InitializeCriticalSection((mutex->mutex));
147 DWORD ok = GetLastError();
148 if (ok == ERROR_SUCCESS) return EINA_TRUE;
149 return EINA_FALSE;
150}
151
152static inline void
153_eina_lock_free(Eina_Lock *mutex)
154{
155#ifdef EINA_HAVE_DEBUG_THREADS
156 if (mutex->locked)
157 {
158 EnterCriticalSection(_eina_tracking_lock);
159 _eina_tracking = eina_inlist_remove(_eina_tracking,
160 EINA_INLIST_GET(mutex));
161 LeaveCriticalSection(_eina_tracking_lock);
162 }
163#endif
164 DWORD ok;
165
166 DeleteCriticalSection((mutex->mutex));
167 ok = GetLastError();
168 if (ok != ERROR_SUCCESS) EINA_LOCK_ABORT_DEBUG((int)ok, mutex_destroy
169 , mutex);
170}
171
172static inline Eina_Lock_Result
173_eina_lock_take_try(Eina_Lock *mutex)
174{
175 Eina_Lock_Result ret = EINA_LOCK_FAIL;
176
177#ifdef EINA_HAVE_ON_OFF_THREADS
178 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
179#endif
180
181 int ok = TryEnterCriticalSection((mutex->mutex));
182 DWORD err = GetLastError();
183 if (ok != 0) ret = EINA_LOCK_SUCCEED;
184 else if (err == ERROR_POSSIBLE_DEADLOCK)
185 {
186 eina_lock_debug(mutex);
187 ret = EINA_LOCK_DEADLOCK;
188 }
189 else if (err != ERROR_TIMEOUT) EINA_LOCK_ABORT_DEBUG((int)err, trylock, mutex);
190#ifdef EINA_HAVE_DEBUG_THREADS
191 if (ret == EINA_LOCK_SUCCEED)
192 {
193 /* recursive locks can't make use of any of this */
194 if (mutex->recursive) return ret;
195 mutex->locked = 1;
196 mutex->lock_thread_id = GetCurrentThreadId();
197 /* backtrace() can somehow generate EINVAL even though this is not documented anywhere? */
198 int err = errno;
199 mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
200 errno = err;
201
202 EnterCriticalSection(_eina_tracking_lock);
203 _eina_tracking = eina_inlist_append(_eina_tracking,
204 EINA_INLIST_GET(mutex));
205 LeaveCriticalSection(_eina_tracking_lock);
206 }
207#endif
208 return ret;
209}
210
211static inline Eina_Lock_Result
212_eina_lock_take(Eina_Lock *mutex)
213{
214 Eina_Lock_Result ret = EINA_LOCK_FAIL;
215 DWORD ok;
216
217#ifdef EINA_HAVE_ON_OFF_THREADS
218 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
219#endif
220
221#ifdef EINA_HAVE_DEBUG_THREADS
222 if (eina_lock_take_try(mutex) == EINA_LOCK_SUCCEED) return EINA_LOCK_SUCCEED;
223
224 if (_eina_threads_debug >= 100)
225 {
226 struct timeval t0, t1;
227 int dt;
228
229 gettimeofday(&t0, NULL);
230 ok = EnterCriticalSection((mutex->mutex));
231 gettimeofday(&t1, NULL);
232
233 dt = (t1.tv_sec - t0.tv_sec) * 1000000;
234 if (t1.tv_usec > t0.tv_usec) dt += (t1.tv_usec - t0.tv_usec);
235 else dt -= t0.tv_usec - t1.tv_usec;
236 if (dt > _eina_threads_debug) abort();
237 }
238 else
239 {
240#endif
241 EnterCriticalSection((mutex->mutex));
242 ok = GetLastError();
243#ifdef EINA_HAVE_DEBUG_THREADS
244 }
245#endif
246
247 if (ok == ERROR_SUCCESS) ret = EINA_LOCK_SUCCEED;
248 else if (ok == ERROR_POSSIBLE_DEADLOCK)
249 {
250 eina_lock_debug(mutex);
251 ret = EINA_LOCK_DEADLOCK;
252#ifdef EINA_HAVE_DEBUG_THREADS
253 if (_eina_threads_debug) abort();
254#endif
255 }
256 else if (ok != ERROR_TIMEOUT) EINA_LOCK_ABORT_DEBUG((int)ok, lock, mutex);
257
258#ifdef EINA_HAVE_DEBUG_THREADS
259 /* recursive locks can't make use of any of this */
260 if (mutex->recursive) return ret;
261 mutex->locked = 1;
262 mutex->lock_thread_id = GetCurrentThreadId();
263 /* backtrace() can somehow generate EINVAL even though this is not documented anywhere? */
264 int err = errno;
265 mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
266 errno = err;
267
268 EnterCriticalSection(_eina_tracking_lock);
269 _eina_tracking = eina_inlist_append(_eina_tracking,
270 EINA_INLIST_GET(mutex));
271 LeaveCriticalSection(_eina_tracking_lock);
272#endif
273
274 return ret;
275}
276
277static inline Eina_Lock_Result
278_eina_lock_release(Eina_Lock *mutex)
279{
280 Eina_Lock_Result ret = EINA_LOCK_FAIL;
281
282#ifdef EINA_HAVE_ON_OFF_THREADS
283 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
284#endif
285
286#ifdef EINA_HAVE_DEBUG_THREADS
287/* recursive locks can't make use of any of this */
288 if (!mutex->recursive)
289 {
290 mutex->locked = 0;
291 mutex->lock_thread_id = 0;
292 memset(mutex->lock_bt, 0, EINA_LOCK_DEBUG_BT_NUM * sizeof(Eina_Lock_Bt_Func));
293 mutex->lock_bt_num = 0;
294 EnterCriticalSection(_eina_tracking_lock);
295 _eina_tracking = eina_inlist_remove(_eina_tracking,
296 EINA_INLIST_GET(mutex));
297 LeaveCriticalSection(_eina_tracking_lock);
298 }
299#endif
300 LeaveCriticalSection((mutex->mutex));
301 DWORD ok = GetLastError();
302 if (ok == ERROR_SUCCESS) ret = EINA_LOCK_SUCCEED;
303 else if (ok != ERROR_ACCESS_DENIED) ret = EINA_LOCK_FAIL;
304 else EINA_LOCK_ABORT_DEBUG((int)ok, unlock, mutex);
305 return ret;
306}
307
308UNIMPLEMENTED static inline Eina_Bool
309_eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
310{
311 // TODO
312 #warning eina_condition_new is not implemented
313 return EINA_TRUE;
314}
315
316static inline void
317_eina_condition_free(Eina_Condition *cond)
318{
319 return;
320}
321
322static inline Eina_Bool
323_eina_condition_wait(Eina_Condition *cond)
324{
325 Eina_Bool r = EINA_FALSE;
326
327#ifdef EINA_HAVE_DEBUG_THREADS
328 assert(_eina_threads_activated);
329 assert(cond->lock != NULL);
330
331 EnterCriticalSection(_eina_tracking_lock);
332 _eina_tracking = eina_inlist_remove(_eina_tracking,
333 EINA_INLIST_GET(cond->lock));
334 LeaveCriticalSection(_eina_tracking_lock);
335#endif
336
337 int ok = SleepConditionVariableCS(&(cond->condition)
338 , (cond->lock->mutex), INFINITE);
339 DWORD err = GetLastError();
340 if (ok != 0) r = EINA_TRUE;
341 else if (err != ERROR_ACCESS_DENIED) r = EINA_FALSE;
342 else EINA_LOCK_ABORT_DEBUG((int)ok, cond_wait, cond);
343
344#ifdef EINA_HAVE_DEBUG_THREADS
345 EnterCriticalSection(_eina_tracking_lock);
346 _eina_tracking = eina_inlist_append(_eina_tracking
347 , EINA_INLIST_GET(cond->lock));
348 LeaveCriticalSection(_eina_tracking_lock);
349#endif
350
351 return r;
352}
353
354UNIMPLEMENTED static inline Eina_Bool
355_eina_condition_timedwait(Eina_Condition *cond, double t)
356{
357 //** TODO **//
358 #warning eina_condition_timedwait is not implemented
359 return EINA_TRUE;
360}
361
362static inline Eina_Bool
363_eina_condition_broadcast(Eina_Condition *cond)
364{
365#ifdef EINA_HAVE_DEBUG_THREADS
366 assert(cond->lock != NULL);
367#endif
368
369 WakeAllConditionVariable(&(cond->condition));
370 DWORD ok = GetLastError();
371 if (ok == ERROR_SUCCESS) return EINA_TRUE;
372
373 EINA_LOCK_ABORT_DEBUG((int)ok, cond_broadcast, cond);
374 return EINA_FALSE;
375}
376
377static inline Eina_Bool
378_eina_condition_signal(Eina_Condition *cond)
379{
380#ifdef EINA_HAVE_DEBUG_THREADS
381 assert(cond->lock != NULL);
382#endif
383
384 WakeConditionVariable(&(cond->condition));
385 DWORD ok = GetLastError();
386 if (ok == ERROR_SUCCESS) return EINA_TRUE;
387
388 EINA_LOCK_ABORT_DEBUG((int)ok, cond_signal, cond);
389 return EINA_FALSE;
390}
391
392static inline Eina_Bool
393_eina_rwlock_new(Eina_RWLock *mutex)
394{
395 InitializeSRWLock((mutex->mutex));
396 DWORD ok = GetLastError();
397 if (ok == ERROR_SUCCESS) return EINA_TRUE;
398 else if ((ok == ERROR_NOT_ENOUGH_MEMORY) || (ok == ERROR_ACCESS_DENIED)
399 || (ok == ERROR_OUTOFMEMORY))
400 {
401 return EINA_FALSE;
402 }
403 else EINA_LOCK_ABORT_DEBUG(ok, rwlock_init, mutex);
404 return EINA_FALSE;
405}
406
407static inline void
408_eina_rwlock_free(Eina_RWLock *mutex)
409{
410 return;
411}
412
413static inline Eina_Lock_Result
414_eina_rwlock_take_read(Eina_RWLock *mutex)
415{
416#ifdef EINA_HAVE_ON_OFF_THREADS
417 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
418#endif
419
420 AcquireSRWLockShared((mutex->mutex));
421 DWORD ok = GetLastError();
422 if (ok == ERROR_SUCCESS)
423 {
424 mutex->mode = _Eina_RWLock_Mode_Shared;
425 return EINA_LOCK_SUCCEED;
426 }
427 else if (ok == ERROR_NOT_ENOUGH_MEMORY || ok == ERROR_OUTOFMEMORY)
428 {
429 return EINA_LOCK_FAIL;
430 }
431 else if (ok == ERROR_POSSIBLE_DEADLOCK)
432 {
433 EINA_LOCK_DEADLOCK_DEBUG(rwlock_rdlock, mutex);
434 }
435 else EINA_LOCK_ABORT_DEBUG((int)ok, rwlock_rdlock, mutex);
436 return EINA_LOCK_FAIL;
437}
438static inline Eina_Lock_Result
439_eina_rwlock_take_write(Eina_RWLock *mutex)
440{
441#ifdef EINA_HAVE_ON_OFF_THREADS
442 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
443#endif
444
445 AcquireSRWLockExclusive((mutex->mutex));
446 DWORD ok = GetLastError();
447 if (ok == ERROR_SUCCESS)
448 {
449 mutex->mode = _Eina_RWLock_Mode_Exclusive;
450 return EINA_LOCK_SUCCEED;
451 }
452 else if (ok == ERROR_NOT_ENOUGH_MEMORY || ok == ERROR_OUTOFMEMORY)
453 {
454 return EINA_LOCK_FAIL;
455 }
456 else if (ok == ERROR_POSSIBLE_DEADLOCK)
457 {
458 EINA_LOCK_DEADLOCK_DEBUG(rwlock_rdlock, mutex);
459 }
460 else EINA_LOCK_ABORT_DEBUG((int)ok, rwlock_rdlock, mutex);
461 return EINA_LOCK_FAIL;
462}
463
464static inline Eina_Lock_Result
465_eina_rwlock_release(Eina_RWLock *mutex)
466{
467 DWORD ok;
468
469#ifdef EINA_HAVE_ON_OFF_THREADS
470 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
471#endif
472
473 if (mutex->mode == _Eina_RWLock_Mode_Exclusive)
474 {
475 mutex->mode = _Eina_RWLock_Mode_None;
476 ReleaseSRWLockExclusive((mutex->mutex));
477 ok = GetLastError();
478 if (ok == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
479 mutex->mode = _Eina_RWLock_Mode_Exclusive;
480 }
481 else if (mutex->mode == _Eina_RWLock_Mode_Shared)
482 {
483 mutex->mode = _Eina_RWLock_Mode_None;
484 ReleaseSRWLockShared((mutex->mutex));
485 ok = GetLastError();
486 if (ok == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
487 mutex->mode = _Eina_RWLock_Mode_Shared;
488 }
489 if (ok == ERROR_ACCESS_DENIED) return EINA_LOCK_FAIL;
490
491 EINA_LOCK_ABORT_DEBUG((int)ok, rwlock_unlock, mutex);
492 return EINA_LOCK_FAIL;
493}
494
495static inline Eina_Bool
496_eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
497{
498 * key = TlsAlloc();
499 DWORD ok = GetLastError();
500 if (key != TLS_OUT_OF_INDEXES || ok != ERROR_SUCCESS) return EINA_TRUE;
501 else return EINA_FALSE;
502}
503
504static inline void
505_eina_tls_free(Eina_TLS key)
506{
507 TlsFree(key);
508}
509
510static inline void *
511_eina_tls_get(Eina_TLS key)
512{
513 return TlsGetValue(key);
514}
515
516static inline Eina_Bool
517_eina_tls_set(Eina_TLS key, const void *data)
518{
519 int ok = TlsSetValue(key, (void *) data);
520 DWORD err = GetLastError();
521 if (ok != 0 && err == ERROR_SUCCESS) return EINA_TRUE;
522 else return EINA_TRUE;
523}
524
525#ifdef EINA_HAVE_WIN32_BARRIER
526struct _Eina_Barrier
527{
528 LPSYNCHRONIZATION_BARRIER barrier;
529};
530#else
531struct _Eina_Barrier
532{
533 int needed; /**< The number of waiting threads that will cause the barrier to signal and reset. */
534 int called; /**< The number of threads that are waiting on this barrier. */
535 Eina_Lock cond_lock; /**< The lock for the barrier */
536 Eina_Condition cond; /**< The condition variable for the barrier */
537};
538#endif
539
540static inline Eina_Bool
541_eina_barrier_new(Eina_Barrier *barrier, int needed)
542{
543#ifdef EINA_HAVE_WIN32_BARRIER
544 InitializeSynchronizationBarrier(&(barrier->barrier), (LONG) needed, 0);
545 DWORD ok = GetLastError();
546 if (ok == ERROR_SUCCESS) return EINA_TRUE;
547 else if ((ok == ERROR_NOT_ENOUGH_MEMORY) || (ok == ERROR_ACCESS_DENIED)
548 || (ok == ERROR_OUTOFMEMORY))
549 {
550 return EINA_FALSE;
551 }
552 else EINA_LOCK_ABORT_DEBUG(ok, barrier_init, barrier);
553 return EINA_FALSE;
554#else
555 barrier->needed = needed;
556 barrier->called = 0;
557 if (eina_lock_new(&(barrier->cond_lock)))
558 {
559 if (eina_condition_new(&(barrier->cond), &(barrier->cond_lock)))
560 return EINA_TRUE;
561 }
562 return EINA_FALSE;
563#endif
564}
565
566static inline void
567_eina_barrier_free(Eina_Barrier *barrier)
568{
569#ifdef EINA_HAVE_WIN32_BARRIER
570 DeleteSynchronizationBarrier(&(barrier->barrier));
571 DWORD ok = GetLastError();
572 if (ok != ERROR_SUCCESS) EINA_LOCK_ABORT_DEBUG(ok, barrier_destroy, barrier);
573#else
574 eina_condition_free(&(barrier->cond));
575 eina_lock_free(&(barrier->cond_lock));
576 barrier->needed = 0;
577 barrier->called = 0;
578#endif
579}
580
581static inline Eina_Bool
582_eina_barrier_wait(Eina_Barrier *barrier)
583{
584#ifdef EINA_HAVE_WIN32_BARRIER
585 EnterSyncronizationBarrier(&(barrier->barrier)
586 , SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
587 DWORD ok = GetLastError();
588 if (ok == ERROR_SUCCESS) return EINA_TRUE;
589 else EINA_LOCK_ABORT_DEBUG((int)ok, barrier_wait, barrier);
590 return EINA_TRUE;
591#else
592 eina_lock_take(&(barrier->cond_lock));
593 barrier->called++;
594 if (barrier->called == barrier->needed)
595 {
596 barrier->called = 0;
597 eina_condition_broadcast(&(barrier->cond));
598 }
599 else eina_condition_wait(&(barrier->cond));
600 eina_lock_release(&(barrier->cond_lock));
601 return EINA_TRUE;
602#endif
603}
604
605static inline Eina_Bool
606_eina_spinlock_new(Eina_Spinlock *spinlock)
607{
608#ifdef EINA_HAVE_WIN32_SPINLOCK
609 int ok = InitializeCriticalSectionAndSpinCount(spinlock, INFINITE);
610 DWORD err = GetLastError();
611 if (ok != 0) return EINA_TRUE;
612 else if ((err == ERROR_NOT_ENOUGH_MEMORY) || (err == ERROR_ACCESS_DENIED)
613 || (err == ERROR_OUTOFMEMORY))
614 {
615 return EINA_FALSE;
616 }
617 else EINA_LOCK_ABORT_DEBUG((int)err, spin_init, spinlock);
618 return EINA_FALSE;
619#else
620 return eina_lock_new(spinlock);
621#endif
622}
623
624static inline void
625_eina_spinlock_free(Eina_Spinlock *spinlock)
626{
627#ifdef EINA_HAVE_WIN32_SPINLOCK
628 DeleteCriticalSection(spinlock);
629 DWORD ok = GetLastError();
630 if (ok != ERROR_SUCCESS) EINA_LOCK_ABORT_DEBUG(ok, spin_destroy, spinlock);
631#else
632 eina_lock_free(spinlock);
633#endif
634}
635
636static inline Eina_Lock_Result
637_eina_spinlock_take_try(Eina_Spinlock *spinlock)
638{
639#ifdef EINA_HAVE_WIN32_SPINLOCK
640 int ok = TryEnterCriticalSection(spinlock);
641 DWORD err = GetLastError();
642 if (err == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
643 else if (ok == 0 || err == ERROR_TIMEOUT) EINA_LOCK_FAIL;
644 else EINA_LOCK_ABORT_DEBUG((int)err, trylock, mutex);
645 return EINA_LOCK_FAIL
646#else
647 return eina_lock_take_try(spinlock);
648#endif
649}
650
651static inline Eina_Lock_Result
652_eina_spinlock_take(Eina_Spinlock *spinlock)
653{
654#ifdef EINA_HAVE_WIN32_SPINLOCK
655# ifdef EINA_HAVE_DEBUG_THREADS
656 if (eina_spinlock_take_try(spinlock) == EINA_LOCK_SUCCEED)
657 return EINA_LOCK_SUCCEED;
658# endif
659
660 for (;;)
661 {
662 int ok = EnterCriticalSection(spinlock);
663 if (ok != 0) break;
664 else {
665 DWORD err = GetLastError();
666 EINA_LOCK_ABORT_DEBUG((int)err, spin_lock, spinlock);
667 }
668 }
669
670 return EINA_LOCK_SUCCEED;
671#else
672 return eina_lock_take(spinlock);
673#endif
674}
675
676static inline Eina_Lock_Result
677_eina_spinlock_release(Eina_Spinlock *spinlock)
678{
679#if defined(EINA_HAVE_WIN32_SPINLOCK)
680 LeaveCriticalSection(spinlock);
681 DWORD ok = GetLastError();
682 if (ok == ERROR_SUCCESS) return EINA_LOCK_SUCCEED;
683 else if (ok == ERROR_ACCESS_DENIED) return EINA_LOCK_FAIL;
684 else EINA_LOCK_ABORT_DEBUG((int)ok, spin_unlock, spinlock);
685 return EINA_LOCK_FAIL;
686#else
687 return eina_lock_release(spinlock);
688#endif
689}
690
691static inline Eina_Bool
692_eina_semaphore_new(Eina_Semaphore *sem, int count_init)
693{
694 if (sem && (count_init >= 0))
695 {
696 sem = CreateSemaphoreA(NULL, count_init, count_init, NULL);
697 DWORD ok = GetLastError();
698 if (ok == ERROR_SUCCESS) return EINA_TRUE;
699 }
700 return EINA_FALSE;
701}
702
703static inline Eina_Bool
704_eina_semaphore_free(Eina_Semaphore *sem)
705{
706 if (sem)
707 {
708 CloseHandle(sem);
709 DWORD ok = GetLastError();
710 if (ok == ERROR_SUCCESS) return EINA_TRUE;
711 }
712 return EINA_FALSE;
713}
714
715static inline Eina_Bool
716_eina_semaphore_lock(Eina_Semaphore *sem)
717{
718 if (sem)
719 {
720 for (;;)
721 {
722 WaitForSingleObject(sem, INFINITE);
723 DWORD ok = GetLastError();
724 if (ok == ERROR_SUCCESS)
725 return EINA_TRUE;
726 else if (ok == WAIT_OBJECT_0 || ok == WAIT_TIMEOUT)
727 continue;
728 else if (errno == ERROR_POSSIBLE_DEADLOCK)
729 {
730 EINA_LOCK_DEADLOCK_DEBUG(sem_wait, sem);
731 return EINA_FALSE;
732 }
733 }
734 }
735 return EINA_FALSE;
736}
737
738static inline Eina_Bool
739_eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
740{
741 if (sem)
742 return (ReleaseSemaphore(sem, 1, NULL) != 0) ? EINA_TRUE : EINA_FALSE;
743 return EINA_FALSE;
744}
745
746
747#endif
diff --git a/src/lib/eina/eina_lock.c b/src/lib/eina/eina_lock.c
index aa085cd15a..1566ab25c3 100644
--- a/src/lib/eina/eina_lock.c
+++ b/src/lib/eina/eina_lock.c
@@ -7,51 +7,6 @@
7#include "eina_config.h" 7#include "eina_config.h"
8#include "Eina.h" 8#include "Eina.h"
9 9
10#ifdef EINA_HAVE_OSX_SPINLOCK
11
12/*
13 * macOS 10.12 introduced the os_unfair_lock API which
14 * deprecates OSSpinLock, while keeping compatible.
15 *
16 * The Spinlock API is not inlined because it would imply including
17 * stdbool.h, which is not wanted: it would introduce new macros,
18 * and break compilation of existing programs.
19 */
20# if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
21# include <os/lock.h>
22# define SPINLOCK_GET(LCK) ((os_unfair_lock_t)(LCK))
23# else
24# include <libkern/OSAtomic.h>
25# define SPINLOCK_GET(LCK) ((OSSpinLock *)(LCK))
26# define os_unfair_lock_lock(LCK) OSSpinLockLock(LCK)
27# define os_unfair_lock_unlock(LCK) OSSpinLockUnlock(LCK)
28# define os_unfair_lock_trylock(LCK) OSSpinLockTry(LCK)
29# endif
30
31EAPI Eina_Lock_Result
32_eina_spinlock_macos_take(Eina_Spinlock *spinlock)
33{
34 os_unfair_lock_lock(SPINLOCK_GET(spinlock));
35 return EINA_LOCK_SUCCEED;
36}
37
38EAPI Eina_Lock_Result
39_eina_spinlock_macos_take_try(Eina_Spinlock *spinlock)
40{
41 return (os_unfair_lock_trylock(SPINLOCK_GET(spinlock)) == true)
42 ? EINA_LOCK_SUCCEED
43 : EINA_LOCK_FAIL;
44}
45
46EAPI Eina_Lock_Result
47_eina_spinlock_macos_release(Eina_Spinlock *spinlock)
48{
49 os_unfair_lock_unlock(SPINLOCK_GET(spinlock));
50 return EINA_LOCK_SUCCEED;
51}
52#endif /* EINA_HAVE_OSX_SPINLOCK */
53
54
55Eina_Bool fork_resetting; 10Eina_Bool fork_resetting;
56 11
57EAPI void 12EAPI void
@@ -85,198 +40,220 @@ eina_lock_debug(const Eina_Lock *mutex)
85#endif 40#endif
86} 41}
87 42
88EAPI Eina_Bool 43EAPI Eina_Bool eina_lock_new(Eina_Lock *mutex)
89_eina_lock_new(Eina_Lock *mutex, Eina_Bool recursive)
90{ 44{
91 pthread_mutexattr_t attr; 45 Eina_Bool ret = _eina_lock_new(mutex, EINA_FALSE);
92 Eina_Bool ok = EINA_FALSE; 46#ifdef EINA_HAVE_DEBUG_THREADS
47 mutex->recursive = EINA_FALSE;
48 mutex->lock_thread_id = 0;
49 mutex->lock_bt_num = 0;
50 mutex->locked = 0;
51#endif
52 return ret;
53}
93 54
94 if (pthread_mutexattr_init(&attr) != 0) return EINA_FALSE; 55EAPI Eina_Bool
95 if (recursive) 56eina_lock_recursive_new(Eina_Lock *mutex)
96 { 57{
97 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) goto fail_release; 58 Eina_Bool ret = _eina_lock_new(mutex, EINA_TRUE);
98 }
99#ifdef EINA_HAVE_DEBUG_THREADS 59#ifdef EINA_HAVE_DEBUG_THREADS
100 else if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) goto fail_release; 60 mutex->recursive = EINA_TRUE;
61 mutex->lock_thread_id = 0;
62 mutex->lock_bt_num = 0;
63 mutex->locked = 0;
101#endif 64#endif
102 if (pthread_mutex_init(&(mutex->mutex), &attr) != 0) goto fail_release; 65 return ret;
103 ok = EINA_TRUE;
104fail_release:
105 pthread_mutexattr_destroy(&attr);
106 return ok;
107} 66}
108 67
109EAPI void 68EAPI void
110_eina_lock_free(Eina_Lock *mutex) 69eina_lock_free(Eina_Lock *mutex)
111{ 70{
112 int ok; 71 _eina_lock_free(mutex);
72}
113 73
114 ok = pthread_mutex_destroy(&(mutex->mutex)); 74EAPI Eina_Lock_Result
115 if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, mutex_destroy, mutex); 75eina_lock_take_try(Eina_Lock *mutex)
76{
77 return _eina_lock_take_try(mutex);
78}
79
80EAPI Eina_Lock_Result
81eina_lock_take(Eina_Lock *mutex)
82{
83 return _eina_lock_take(mutex);
84}
85
86EAPI Eina_Lock_Result
87eina_lock_release(Eina_Lock *mutex)
88{
89 return _eina_lock_release(mutex);
116} 90}
117 91
118EAPI Eina_Bool 92EAPI Eina_Bool
119_eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex) 93eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
120{ 94{
121 pthread_condattr_t attr; 95 return _eina_condition_new(cond, mutex);
122 int ok; 96}
123 97
124#ifdef EINA_HAVE_DEBUG_THREADS 98EAPI void
125 assert(mutex != NULL); 99eina_condition_free(Eina_Condition *cond)
126#endif 100{
101 _eina_condition_free(cond);
102}
127 103
128 cond->lock = mutex; 104EAPI Eina_Bool
129 pthread_condattr_init(&attr); 105eina_condition_wait(Eina_Condition *cond)
130 106{
131 /* OSX doesn't provide clockid_t or clock_gettime. */ 107 return _eina_condition_wait(cond);
132#if defined(__clockid_t_defined) 108}
133 cond->clkid = (clockid_t) 0;
134 /* We try here to chose the best clock for cond_timedwait */
135# if defined(CLOCK_MONOTONIC_RAW)
136 if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC_RAW))
137 cond->clkid = CLOCK_MONOTONIC_RAW;
138# endif
139# if defined(CLOCK_MONOTONIC)
140 if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
141 cond->clkid = CLOCK_MONOTONIC;
142# endif
143# if defined(CLOCK_REALTIME)
144 if (!cond->clkid && !pthread_condattr_setclock(&attr, CLOCK_REALTIME))
145 cond->clkid = CLOCK_REALTIME;
146# endif
147#endif
148 109
149 ok = pthread_cond_init(&cond->condition, &attr); 110EAPI Eina_Bool
150 if (ok != 0) 111eina_condition_timedwait(Eina_Condition *cond, double t)
151 { 112{
152 pthread_condattr_destroy(&attr); 113 return _eina_condition_timedwait(cond, t);
153#ifdef EINA_HAVE_DEBUG_THREADS 114}
154 if (ok == EBUSY) 115
155 fprintf(stderr, "EINA ERROR: eina_condition_new on already initialized Eina_Condition\n"); 116EAPI Eina_Bool
156#endif 117eina_condition_broadcast(Eina_Condition *cond)
157 return EINA_FALSE; 118{
158 } 119 return _eina_condition_broadcast(cond);
120}
121
122EAPI Eina_Bool
123eina_condition_signal(Eina_Condition *cond)
124{
125 return _eina_condition_signal(cond);
126}
159 127
160 pthread_condattr_destroy(&attr); 128EAPI Eina_Bool
161 return EINA_TRUE; 129eina_rwlock_new(Eina_RWLock *mutex)
130{
131 return _eina_rwlock_new(mutex);
162} 132}
163 133
164EAPI void 134EAPI void
165_eina_condition_free(Eina_Condition *cond) 135eina_rwlock_free(Eina_RWLock *mutex)
136{
137 _eina_rwlock_free(mutex);
138}
139
140EAPI Eina_Lock_Result
141eina_rwlock_take_read(Eina_RWLock *mutex)
142{
143 return _eina_rwlock_take_read(mutex);
144}
145
146EAPI Eina_Lock_Result
147eina_rwlock_take_write(Eina_RWLock *mutex)
166{ 148{
167 pthread_cond_destroy(&(cond->condition)); 149 return _eina_rwlock_take_write(mutex);
150}
151
152EAPI Eina_Lock_Result
153eina_rwlock_release(Eina_RWLock *mutex)
154{
155 return _eina_rwlock_release(mutex);
168} 156}
169 157
170EAPI Eina_Bool 158EAPI Eina_Bool
171_eina_rwlock_new(Eina_RWLock *mutex) 159eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
172{ 160{
173 int ok; 161 return _eina_tls_cb_new(key, delete_cb);
162}
174 163
175 ok = pthread_rwlock_init(&(mutex->mutex), NULL); 164EAPI Eina_Bool
176 if (ok == 0) return EINA_TRUE; 165eina_tls_new(Eina_TLS *key)
177 else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE; 166{
178 else EINA_LOCK_ABORT_DEBUG(ok, rwlock_init, mutex); 167 return _eina_tls_cb_new(key, NULL);
179 return EINA_FALSE;
180} 168}
181 169
182EAPI void 170EAPI void
183_eina_rwlock_free(Eina_RWLock *mutex) 171eina_tls_free(Eina_TLS key)
172{
173 _eina_tls_free(key);
174}
175
176EAPI void *
177eina_tls_get(Eina_TLS key)
184{ 178{
185 pthread_rwlock_destroy(&(mutex->mutex)); 179 return _eina_tls_get(key);
186} 180}
187 181
188EAPI Eina_Bool 182EAPI Eina_Bool
189_eina_barrier_new(Eina_Barrier *barrier, int needed) 183eina_tls_set(Eina_TLS key, const void *data)
190{ 184{
191#ifdef EINA_HAVE_PTHREAD_BARRIER 185 return _eina_tls_set(key, data);
192 int ok = pthread_barrier_init(&(barrier->barrier), NULL, needed); 186}
193 if (ok == 0) return EINA_TRUE; 187
194 else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE; 188EAPI Eina_Bool
195 else EINA_LOCK_ABORT_DEBUG(ok, barrier_init, barrier); 189eina_barrier_new(Eina_Barrier *barrier, int needed)
196 return EINA_FALSE; 190{
197#else 191 return _eina_barrier_new(barrier, needed);
198 barrier->needed = needed;
199 barrier->called = 0;
200 if (eina_lock_new(&(barrier->cond_lock)))
201 {
202 if (eina_condition_new(&(barrier->cond), &(barrier->cond_lock)))
203 return EINA_TRUE;
204 }
205 return EINA_FALSE;
206#endif
207} 192}
208 193
209EAPI void 194EAPI void
210_eina_barrier_free(Eina_Barrier *barrier) 195eina_barrier_free(Eina_Barrier *barrier)
211{ 196{
212#ifdef EINA_HAVE_PTHREAD_BARRIER 197 _eina_barrier_free(barrier);
213 int ok = pthread_barrier_destroy(&(barrier->barrier));
214 if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, barrier_destroy, barrier);
215#else
216 eina_condition_free(&(barrier->cond));
217 eina_lock_free(&(barrier->cond_lock));
218 barrier->needed = 0;
219 barrier->called = 0;
220#endif
221} 198}
222 199
223EAPI Eina_Bool 200EAPI Eina_Bool
224_eina_spinlock_new(Eina_Spinlock *spinlock) 201eina_barrier_wait(Eina_Barrier *barrier)
225{ 202{
226#if defined(EINA_HAVE_POSIX_SPINLOCK) 203 return _eina_barrier_wait(barrier);
227 int ok = pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE); 204}
228 if (ok == 0) return EINA_TRUE; 205
229 else if ((ok == EAGAIN) || (ok == ENOMEM)) return EINA_FALSE; 206EAPI Eina_Bool
230 else EINA_LOCK_ABORT_DEBUG(ok, spin_init, spinlock); 207eina_spinlock_new(Eina_Spinlock *spinlock)
231 return EINA_FALSE; 208{
232#elif defined(EINA_HAVE_OSX_SPINLOCK) 209 return _eina_spinlock_new(spinlock);
233 *spinlock = 0;
234 return EINA_TRUE;
235#else
236 return eina_lock_new(spinlock);
237#endif
238} 210}
239 211
240EAPI void 212EAPI void
241_eina_spinlock_free(Eina_Spinlock *spinlock) 213eina_spinlock_free(Eina_Spinlock *spinlock)
242{ 214{
243#if defined(EINA_HAVE_POSIX_SPINLOCK) 215 _eina_spinlock_free(spinlock);
244 int ok = pthread_spin_destroy(spinlock); 216}
245 if (ok != 0) EINA_LOCK_ABORT_DEBUG(ok, spin_destroy, spinlock); 217
246#elif defined(EINA_HAVE_OSX_SPINLOCK) 218EAPI Eina_Lock_Result
247 /* Not applicable */ 219eina_spinlock_take_try(Eina_Spinlock *spinlock)
248 (void) spinlock; 220{
249#else 221 return _eina_spinlock_take_try(spinlock);
250 eina_lock_free(spinlock); 222}
251#endif 223
224EAPI Eina_Lock_Result
225eina_spinlock_take(Eina_Spinlock *spinlock)
226{
227 return _eina_spinlock_take(spinlock);
228}
229
230EAPI Eina_Lock_Result
231eina_spinlock_release(Eina_Spinlock *spinlock)
232{
233 return _eina_spinlock_release(spinlock);
252} 234}
253 235
254EAPI Eina_Bool 236EAPI Eina_Bool
255_eina_semaphore_new(Eina_Semaphore *sem, int count_init) 237eina_semaphore_new(Eina_Semaphore *sem, int count_init)
256{ 238{
257 if (sem && (count_init >= 0)) 239 return _eina_semaphore_new(sem, count_init);
258 {
259#if defined(EINA_HAVE_OSX_SEMAPHORE)
260 kern_return_t kr = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, count_init);
261 return (kr == KERN_SUCCESS) ? EINA_TRUE : EINA_FALSE;
262#else
263 return (sem_init(sem, 0, count_init) == 0) ? EINA_TRUE : EINA_FALSE;
264#endif
265 }
266 return EINA_FALSE;
267} 240}
268 241
269EAPI Eina_Bool 242EAPI Eina_Bool
270_eina_semaphore_free(Eina_Semaphore *sem) 243eina_semaphore_free(Eina_Semaphore *sem)
271{ 244{
272 if (sem) 245 return _eina_semaphore_free(sem);
273 { 246}
274#if defined(EINA_HAVE_OSX_SEMAPHORE) 247
275 return (semaphore_destroy(mach_task_self(), *sem) == KERN_SUCCESS) 248EAPI Eina_Bool
276 ? EINA_TRUE : EINA_FALSE; 249eina_semaphore_lock(Eina_Semaphore *sem)
277#else 250{
278 return (sem_destroy(sem) == 0) ? EINA_TRUE : EINA_FALSE; 251 return _eina_semaphore_lock(sem);
279#endif
280 }
281 return EINA_FALSE;
282} 252}
253
254EAPI Eina_Bool
255eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
256{
257 return _eina_semaphore_release(sem, count_release);
258}
259
diff --git a/src/lib/eina/eina_lock.h b/src/lib/eina/eina_lock.h
index d173f6be34..a6e438843e 100644
--- a/src/lib/eina/eina_lock.h
+++ b/src/lib/eina/eina_lock.h
@@ -97,7 +97,11 @@ typedef enum
97 */ 97 */
98typedef void (*Eina_TLS_Delete_Cb)(void *ptr); 98typedef void (*Eina_TLS_Delete_Cb)(void *ptr);
99 99
100#include "eina_inline_lock_posix.x" 100#ifdef _WIN32
101# include "eina_inline_lock_win32.x"
102#else
103# include "eina_inline_lock_posix.x"
104#endif
101 105
102/** 106/**
103 * @brief A type definition for warning that a function was called from 107 * @brief A type definition for warning that a function was called from
@@ -117,7 +121,7 @@ EAPI extern Eina_Error EINA_ERROR_NOT_MAIN_LOOP;
117 * 121 *
118 * @see eina_lock_free() 122 * @see eina_lock_free()
119 */ 123 */
120static inline Eina_Bool eina_lock_new(Eina_Lock *mutex); 124EAPI Eina_Bool eina_lock_new(Eina_Lock *mutex);
121 125
122/** 126/**
123 * @brief Initializes a new #Eina_Lock that is recursive. 127 * @brief Initializes a new #Eina_Lock that is recursive.
@@ -133,7 +137,7 @@ static inline Eina_Bool eina_lock_new(Eina_Lock *mutex);
133 * @see eina_lock_free() 137 * @see eina_lock_free()
134 * @since 1.19 138 * @since 1.19
135 */ 139 */
136static inline Eina_Bool eina_lock_recursive_new(Eina_Lock *mutex); 140EAPI Eina_Bool eina_lock_recursive_new(Eina_Lock *mutex);
137 141
138/** 142/**
139 * @brief Deallocates an #Eina_Lock. 143 * @brief Deallocates an #Eina_Lock.
@@ -144,7 +148,7 @@ static inline Eina_Bool eina_lock_recursive_new(Eina_Lock *mutex);
144 * 148 *
145 * @see eina_lock_new() 149 * @see eina_lock_new()
146 */ 150 */
147static inline void eina_lock_free(Eina_Lock *mutex); 151EAPI void eina_lock_free(Eina_Lock *mutex);
148 152
149/** 153/**
150 * @brief Attempts to take a lock. 154 * @brief Attempts to take a lock.
@@ -162,7 +166,7 @@ static inline void eina_lock_free(Eina_Lock *mutex);
162 * @see eina_lock_take_try() 166 * @see eina_lock_take_try()
163 * @see eina_lock_release() 167 * @see eina_lock_release()
164 */ 168 */
165static inline Eina_Lock_Result eina_lock_take(Eina_Lock *mutex); 169EAPI Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
166 170
167/** 171/**
168 * @brief Attempts to take a lock if possible. 172 * @brief Attempts to take a lock if possible.
@@ -178,7 +182,7 @@ static inline Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
178 * @see eina_lock_take() 182 * @see eina_lock_take()
179 * @see eina_lock_release() 183 * @see eina_lock_release()
180 */ 184 */
181static inline Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex); 185EAPI Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
182 186
183/** 187/**
184 * @brief Releases a lock. 188 * @brief Releases a lock.
@@ -194,7 +198,7 @@ static inline Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
194 * @see eina_lock_take() 198 * @see eina_lock_take()
195 * @see eina_lock_take_try() 199 * @see eina_lock_take_try()
196 */ 200 */
197static inline Eina_Lock_Result eina_lock_release(Eina_Lock *mutex); 201EAPI Eina_Lock_Result eina_lock_release(Eina_Lock *mutex);
198 202
199/** 203/**
200 * @brief Prints debug information about a lock. 204 * @brief Prints debug information about a lock.
@@ -226,7 +230,7 @@ EAPI void eina_lock_debug(const Eina_Lock *mutex);
226 * 230 *
227 * @see eina_condition_free() 231 * @see eina_condition_free()
228 */ 232 */
229static inline Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex); 233EAPI Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex);
230 234
231/** 235/**
232 * @brief Deallocates a condition variable. 236 * @brief Deallocates a condition variable.
@@ -237,7 +241,7 @@ static inline Eina_Bool eina_condition_new(Eina_Condition *cond, Eina_Lock *mute
237 * 241 *
238 * @see eina_condition_new() 242 * @see eina_condition_new()
239 */ 243 */
240static inline void eina_condition_free(Eina_Condition *cond); 244EAPI void eina_condition_free(Eina_Condition *cond);
241 245
242/** 246/**
243 * @brief Causes a thread to wait until signaled by the condition. 247 * @brief Causes a thread to wait until signaled by the condition.
@@ -249,7 +253,7 @@ static inline void eina_condition_free(Eina_Condition *cond);
249 * 253 *
250 * @see eina_condition_timedwait() 254 * @see eina_condition_timedwait()
251 */ 255 */
252static inline Eina_Bool eina_condition_wait(Eina_Condition *cond); 256EAPI Eina_Bool eina_condition_wait(Eina_Condition *cond);
253 257
254/** 258/**
255 * @brief Causes a thread to wait until signaled by the condition or a 259 * @brief Causes a thread to wait until signaled by the condition or a
@@ -265,7 +269,7 @@ static inline Eina_Bool eina_condition_wait(Eina_Condition *cond);
265 * 269 *
266 * @see eina_condition_wait() 270 * @see eina_condition_wait()
267 */ 271 */
268static inline Eina_Bool eina_condition_timedwait(Eina_Condition *cond, double t); 272EAPI Eina_Bool eina_condition_timedwait(Eina_Condition *cond, double t);
269 273
270/** 274/**
271 * @brief Signals all threads waiting for a condition. 275 * @brief Signals all threads waiting for a condition.
@@ -279,7 +283,7 @@ static inline Eina_Bool eina_condition_timedwait(Eina_Condition *cond, double t)
279 * 283 *
280 * @see eina_condition_signal() 284 * @see eina_condition_signal()
281 */ 285 */
282static inline Eina_Bool eina_condition_broadcast(Eina_Condition *cond); 286EAPI Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
283 287
284/** 288/**
285 * @brief Signals a thread waiting for a condition. 289 * @brief Signals a thread waiting for a condition.
@@ -296,7 +300,7 @@ static inline Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
296 * 300 *
297 * @see eina_condition_broadcast() 301 * @see eina_condition_broadcast()
298 */ 302 */
299static inline Eina_Bool eina_condition_signal(Eina_Condition *cond); 303EAPI Eina_Bool eina_condition_signal(Eina_Condition *cond);
300 304
301 305
302/** 306/**
@@ -311,7 +315,7 @@ static inline Eina_Bool eina_condition_signal(Eina_Condition *cond);
311 * 315 *
312 * @see eina_rwlock_free() 316 * @see eina_rwlock_free()
313 */ 317 */
314static inline Eina_Bool eina_rwlock_new(Eina_RWLock *mutex); 318EAPI Eina_Bool eina_rwlock_new(Eina_RWLock *mutex);
315 319
316/** 320/**
317 * @brief Deallocates an #Eina_RWLock. 321 * @brief Deallocates an #Eina_RWLock.
@@ -322,7 +326,7 @@ static inline Eina_Bool eina_rwlock_new(Eina_RWLock *mutex);
322 * 326 *
323 * @see eina_rwlock_new() 327 * @see eina_rwlock_new()
324 */ 328 */
325static inline void eina_rwlock_free(Eina_RWLock *mutex); 329EAPI void eina_rwlock_free(Eina_RWLock *mutex);
326 330
327/** 331/**
328 * @brief Attempts to take a read lock. 332 * @brief Attempts to take a read lock.
@@ -338,7 +342,7 @@ static inline void eina_rwlock_free(Eina_RWLock *mutex);
338 * 342 *
339 * @see eina_rwlock_release() 343 * @see eina_rwlock_release()
340 */ 344 */
341static inline Eina_Lock_Result eina_rwlock_take_read(Eina_RWLock *mutex); 345EAPI Eina_Lock_Result eina_rwlock_take_read(Eina_RWLock *mutex);
342 346
343/** 347/**
344 * @brief Attempts to take a write lock. 348 * @brief Attempts to take a write lock.
@@ -354,7 +358,7 @@ static inline Eina_Lock_Result eina_rwlock_take_read(Eina_RWLock *mutex);
354 * 358 *
355 * @see eina_rwlock_release() 359 * @see eina_rwlock_release()
356 */ 360 */
357static inline Eina_Lock_Result eina_rwlock_take_write(Eina_RWLock *mutex); 361EAPI Eina_Lock_Result eina_rwlock_take_write(Eina_RWLock *mutex);
358 362
359/** 363/**
360 * @brief Releases a lock. 364 * @brief Releases a lock.
@@ -368,7 +372,7 @@ static inline Eina_Lock_Result eina_rwlock_take_write(Eina_RWLock *mutex);
368 * @see eina_rwlock_take_read() 372 * @see eina_rwlock_take_read()
369 * @see eina_rwlock_take_write() 373 * @see eina_rwlock_take_write()
370 */ 374 */
371static inline Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex); 375EAPI Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
372 376
373/** 377/**
374 * @brief Initializes a new #Eina_TLS, or thread level storage, to store thread 378 * @brief Initializes a new #Eina_TLS, or thread level storage, to store thread
@@ -386,7 +390,7 @@ static inline Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
386 * @see eina_tls_cb_new() 390 * @see eina_tls_cb_new()
387 * @see eina_tls_free() 391 * @see eina_tls_free()
388 */ 392 */
389static inline Eina_Bool eina_tls_new(Eina_TLS *key); 393EAPI Eina_Bool eina_tls_new(Eina_TLS *key);
390 394
391/** 395/**
392 * @brief Initializes a new #Eina_TLS, or thread level storage, to store thread 396 * @brief Initializes a new #Eina_TLS, or thread level storage, to store thread
@@ -403,7 +407,7 @@ static inline Eina_Bool eina_tls_new(Eina_TLS *key);
403 * @see eina_tls_new() 407 * @see eina_tls_new()
404 * @see eina_tls_free() 408 * @see eina_tls_free()
405 */ 409 */
406static inline Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb); 410EAPI Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb);
407 411
408/** 412/**
409 * @brief Frees an allocated #Eina_TLS. 413 * @brief Frees an allocated #Eina_TLS.
@@ -415,7 +419,7 @@ static inline Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete
415 * @see eina_tls_new() 419 * @see eina_tls_new()
416 * @see eina_tls_cb_new() 420 * @see eina_tls_cb_new()
417 */ 421 */
418static inline void eina_tls_free(Eina_TLS key); 422EAPI void eina_tls_free(Eina_TLS key);
419 423
420/** 424/**
421 * @brief Gets the value in #Eina_TLS for this thread. 425 * @brief Gets the value in #Eina_TLS for this thread.
@@ -428,7 +432,7 @@ static inline void eina_tls_free(Eina_TLS key);
428 * 432 *
429 * @see eina_tls_set() 433 * @see eina_tls_set()
430 */ 434 */
431static inline void *eina_tls_get(Eina_TLS key); 435EAPI void *eina_tls_get(Eina_TLS key);
432 436
433/** 437/**
434 * @brief Sets the value in Eina_TLS for this thread. 438 * @brief Sets the value in Eina_TLS for this thread.
@@ -442,7 +446,7 @@ static inline void *eina_tls_get(Eina_TLS key);
442 * 446 *
443 * @see eina_tls_get() 447 * @see eina_tls_get()
444 */ 448 */
445static inline Eina_Bool eina_tls_set(Eina_TLS key, const void *data); 449EAPI Eina_Bool eina_tls_set(Eina_TLS key, const void *data);
446 450
447/** 451/**
448 * @brief Initializes a new #Eina_Semaphore. 452 * @brief Initializes a new #Eina_Semaphore.
@@ -456,7 +460,7 @@ static inline Eina_Bool eina_tls_set(Eina_TLS key, const void *data);
456 * 460 *
457 * @see eina_semaphore_free() 461 * @see eina_semaphore_free()
458 */ 462 */
459static inline Eina_Bool eina_semaphore_new(Eina_Semaphore *sem, int count_init); 463EAPI Eina_Bool eina_semaphore_new(Eina_Semaphore *sem, int count_init);
460 464
461/** 465/**
462 * @brief Frees an allocated #Eina_Semaphore. 466 * @brief Frees an allocated #Eina_Semaphore.
@@ -469,7 +473,7 @@ static inline Eina_Bool eina_semaphore_new(Eina_Semaphore *sem, int count_init);
469 * 473 *
470 * @see eina_semaphore_new() 474 * @see eina_semaphore_new()
471 */ 475 */
472static inline Eina_Bool eina_semaphore_free(Eina_Semaphore *sem); 476EAPI Eina_Bool eina_semaphore_free(Eina_Semaphore *sem);
473 477
474/** 478/**
475 * @brief Gets a lock on an #Eina_Semaphore. 479 * @brief Gets a lock on an #Eina_Semaphore.
@@ -482,7 +486,7 @@ static inline Eina_Bool eina_semaphore_free(Eina_Semaphore *sem);
482 * 486 *
483 * @see eina_semaphore_release() 487 * @see eina_semaphore_release()
484 */ 488 */
485static inline Eina_Bool eina_semaphore_lock(Eina_Semaphore *sem); 489EAPI Eina_Bool eina_semaphore_lock(Eina_Semaphore *sem);
486 490
487/** 491/**
488 * @brief Releases a lock on an #Eina_Semaphore. 492 * @brief Releases a lock on an #Eina_Semaphore.
@@ -496,7 +500,7 @@ static inline Eina_Bool eina_semaphore_lock(Eina_Semaphore *sem);
496 * 500 *
497 * @see eina_semaphore_lock() 501 * @see eina_semaphore_lock()
498 */ 502 */
499static inline Eina_Bool eina_semaphore_release(Eina_Semaphore *sem, int count_release); 503EAPI Eina_Bool eina_semaphore_release(Eina_Semaphore *sem, int count_release);
500 504
501/** 505/**
502 * @brief Initializes a new #Eina_Barrier. 506 * @brief Initializes a new #Eina_Barrier.
@@ -511,7 +515,7 @@ static inline Eina_Bool eina_semaphore_release(Eina_Semaphore *sem, int count_re
511 * 515 *
512 * @see eina_barrier_free() 516 * @see eina_barrier_free()
513 */ 517 */
514static inline Eina_Bool eina_barrier_new(Eina_Barrier *barrier, int needed); 518EAPI Eina_Bool eina_barrier_new(Eina_Barrier *barrier, int needed);
515 519
516/** 520/**
517 * @brief Frees an allocated #Eina_Barrier. 521 * @brief Frees an allocated #Eina_Barrier.
@@ -521,7 +525,7 @@ static inline Eina_Bool eina_barrier_new(Eina_Barrier *barrier, int needed);
521 * 525 *
522 * @see eina_barrier_new() 526 * @see eina_barrier_new()
523 */ 527 */
524static inline void eina_barrier_free(Eina_Barrier *barrier); 528EAPI void eina_barrier_free(Eina_Barrier *barrier);
525 529
526/** 530/**
527 * @brief Increments the count of threads that are waiting on @p barrier. 531 * @brief Increments the count of threads that are waiting on @p barrier.
@@ -532,7 +536,7 @@ static inline void eina_barrier_free(Eina_Barrier *barrier);
532 * @return #EINA_TRUE on success, else #EINA_FALSE otherwise. 536 * @return #EINA_TRUE on success, else #EINA_FALSE otherwise.
533 * 537 *
534 */ 538 */
535static inline Eina_Bool eina_barrier_wait(Eina_Barrier *barrier); 539EAPI Eina_Bool eina_barrier_wait(Eina_Barrier *barrier);
536 540
537 541
538/** 542/**
@@ -549,7 +553,7 @@ static inline Eina_Bool eina_barrier_wait(Eina_Barrier *barrier);
549 * 553 *
550 * @see eina_spinlock_free() 554 * @see eina_spinlock_free()
551 */ 555 */
552static inline Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock); 556EAPI Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock);
553 557
554/** 558/**
555 * @brief Attempts to take a spinlock. 559 * @brief Attempts to take a spinlock.
@@ -567,7 +571,7 @@ static inline Eina_Bool eina_spinlock_new(Eina_Spinlock *spinlock);
567 * @see eina_spinlock_take_try() 571 * @see eina_spinlock_take_try()
568 * @see eina_spinlock_release() 572 * @see eina_spinlock_release()
569 */ 573 */
570static inline Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock); 574EAPI Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock);
571 575
572/** 576/**
573 * @brief Attempts to take a spinlock if possible. 577 * @brief Attempts to take a spinlock if possible.
@@ -583,7 +587,7 @@ static inline Eina_Lock_Result eina_spinlock_take(Eina_Spinlock *spinlock);
583 * @see eina_spinlock_take_try() 587 * @see eina_spinlock_take_try()
584 * @see eina_spinlock_release() 588 * @see eina_spinlock_release()
585 */ 589 */
586static inline Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock); 590EAPI Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock);
587 591
588/** 592/**
589 * @brief Releases a spinlock. 593 * @brief Releases a spinlock.
@@ -599,7 +603,7 @@ static inline Eina_Lock_Result eina_spinlock_take_try(Eina_Spinlock *spinlock);
599 * @see eina_spinlock_take_try() 603 * @see eina_spinlock_take_try()
600 604
601 */ 605 */
602static inline Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock); 606EAPI Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock);
603 607
604/** 608/**
605 * @brief Deallocates an #Eina_Spinlock. 609 * @brief Deallocates an #Eina_Spinlock.
@@ -609,7 +613,7 @@ static inline Eina_Lock_Result eina_spinlock_release(Eina_Spinlock *spinlock);
609 * @param[in] spinlock The #Eina_Spinlock to be deallocated. 613 * @param[in] spinlock The #Eina_Spinlock to be deallocated.
610 * 614 *
611 */ 615 */
612static inline void eina_spinlock_free(Eina_Spinlock *spinlock); 616EAPI void eina_spinlock_free(Eina_Spinlock *spinlock);
613 617
614#ifdef EINA_HAVE_DEBUG_THREADS 618#ifdef EINA_HAVE_DEBUG_THREADS
615# define EINA_MAIN_LOOP_CHECK_RETURN_VAL(val) \ 619# define EINA_MAIN_LOOP_CHECK_RETURN_VAL(val) \
diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c
index 61c21b01c3..54af2cfa00 100644
--- a/src/lib/eina/eina_main.c
+++ b/src/lib/eina/eina_main.c
@@ -41,6 +41,7 @@
41#endif 41#endif
42 42
43#include "eina_lock.h" 43#include "eina_lock.h"
44#include "eina_thread.h"
44#include "eina_config.h" 45#include "eina_config.h"
45#include "eina_private.h" 46#include "eina_private.h"
46#include "eina_types.h" 47#include "eina_types.h"
@@ -99,7 +100,7 @@ EAPI Eina_Error EINA_ERROR_NOT_IMPLEMENTED = 0;
99EAPI unsigned int eina_seed = 0; 100EAPI unsigned int eina_seed = 0;
100 101
101#ifdef EFL_HAVE_THREADS 102#ifdef EFL_HAVE_THREADS
102EAPI Eina_Thread _eina_main_loop; 103EAPI Eina_Thread _eina_main_loop;
103#endif 104#endif
104 105
105#ifdef MT 106#ifdef MT
@@ -108,7 +109,7 @@ static int _mt_enabled = 0;
108 109
109#ifdef EFL_HAVE_THREADS 110#ifdef EFL_HAVE_THREADS
110EAPI int _eina_threads_debug = 0; 111EAPI int _eina_threads_debug = 0;
111EAPI pthread_mutex_t _eina_tracking_lock; 112EAPI Eina_Lock _eina_tracking_lock;
112EAPI Eina_Inlist *_eina_tracking = NULL; 113EAPI Eina_Inlist *_eina_tracking = NULL;
113extern Eina_Lock _sysmon_lock; 114extern Eina_Lock _sysmon_lock;
114#endif 115#endif
@@ -230,7 +231,7 @@ _eina_threads_do_shutdown(void)
230#ifdef EINA_HAVE_DEBUG_THREADS 231#ifdef EINA_HAVE_DEBUG_THREADS
231 const Eina_Lock *lk; 232 const Eina_Lock *lk;
232 233
233 pthread_mutex_lock(&_eina_tracking_lock); 234 eina_lock_take(&_eina_tracking_lock);
234 if (_eina_tracking) 235 if (_eina_tracking)
235 { 236 {
236 if (((Eina_Lock*)_eina_tracking != (&_sysmon_lock)) || (_eina_tracking->next)) 237 if (((Eina_Lock*)_eina_tracking != (&_sysmon_lock)) || (_eina_tracking->next))
@@ -248,7 +249,7 @@ _eina_threads_do_shutdown(void)
248 abort(); 249 abort();
249 } 250 }
250 } 251 }
251 pthread_mutex_unlock(&_eina_tracking_lock); 252 eina_lock_release(&_eina_tracking_lock);
252#endif 253#endif
253 254
254 eina_share_common_threads_shutdown(); 255 eina_share_common_threads_shutdown();
@@ -317,7 +318,7 @@ eina_init(void)
317 } 318 }
318 319
319#ifdef EINA_HAVE_DEBUG_THREADS 320#ifdef EINA_HAVE_DEBUG_THREADS
320 pthread_mutex_init(&_eina_tracking_lock, NULL); 321 eina_lock_take(&_eina_tracking_lock, NULL);
321 322
322 if (getenv("EINA_DEBUG_THREADS")) 323 if (getenv("EINA_DEBUG_THREADS"))
323 _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS")); 324 _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS"));
@@ -367,7 +368,7 @@ eina_shutdown(void)
367 if (_eina_threads_activated && (!_eina_main_thread_count)) 368 if (_eina_threads_activated && (!_eina_main_thread_count))
368 _eina_threads_do_shutdown(); 369 _eina_threads_do_shutdown();
369#ifdef EINA_HAVE_DEBUG_THREADS 370#ifdef EINA_HAVE_DEBUG_THREADS
370 pthread_mutex_destroy(&_eina_tracking_lock); 371 eina_lock_free(&_eina_tracking_lock);
371#endif 372#endif
372 eina_freeq_free(eina_freeq_main_get()); 373 eina_freeq_free(eina_freeq_main_get());
373#ifdef MT 374#ifdef MT
@@ -388,7 +389,7 @@ eina_threads_init(void)
388{ 389{
389#ifdef EFL_HAVE_THREADS 390#ifdef EFL_HAVE_THREADS
390 int ret; 391 int ret;
391# ifdef EINA_HAVE_DEBUG_THREADS 392# ifdef EINA_HAVE_DEBUG_THREADS
392 assert(eina_thread_equal(_eina_main_loop, eina_thread_self())); 393 assert(eina_thread_equal(_eina_main_loop, eina_thread_self()));
393# endif 394# endif
394 395
@@ -438,7 +439,7 @@ eina_main_loop_is(void)
438#ifdef EFL_HAVE_THREADS 439#ifdef EFL_HAVE_THREADS
439# ifdef __GNUC__ 440# ifdef __GNUC__
440 /* pthread_self() can't be optimized, it's a single asm "movl" */ 441 /* pthread_self() can't be optimized, it's a single asm "movl" */
441 if (__builtin_types_compatible_p(pthread_t, unsigned long int)) 442 if (__builtin_types_compatible_p(Eina_Thread, unsigned long int))
442 return (eina_thread_self() == _eina_main_loop); 443 return (eina_thread_self() == _eina_main_loop);
443 else 444 else
444# endif 445# endif
diff --git a/src/lib/eina/meson.build b/src/lib/eina/meson.build
index 5d52682d58..e2220f96df 100644
--- a/src/lib/eina/meson.build
+++ b/src/lib/eina/meson.build
@@ -85,8 +85,6 @@ public_sub_headers = [
85'eina_inline_value.x', 85'eina_inline_value.x',
86'eina_value_util.h', 86'eina_value_util.h',
87'eina_inline_value_util.x', 87'eina_inline_value_util.x',
88'eina_inline_lock_barrier.x',
89'eina_inline_lock_posix.x',
90'eina_tmpstr.h', 88'eina_tmpstr.h',
91'eina_alloca.h', 89'eina_alloca.h',
92'eina_cow.h', 90'eina_cow.h',
@@ -197,15 +195,17 @@ sources = [
197] 195]
198 196
199if sys_windows == true 197if sys_windows == true
200 public_sub_headers += 'eina_thread_win32.h' 198 public_sub_headers += 'eina_thread_win32.h'
201 public_sub_headers += 'eina_inline_thread_win32.x' 199 public_sub_headers += 'eina_inline_thread_win32.x'
202 sources += 'eina_file_win32.c' 200 sources += 'eina_file_win32.c'
203 sources += 'eina_sched_win32.c' 201 sources += 'eina_sched_win32.c'
202 public_sub_headers += 'eina_inline_lock_win32.x'
204else 203else
205 public_sub_headers += 'eina_thread_posix.h' 204 public_sub_headers += 'eina_thread_posix.h'
206 public_sub_headers += 'eina_inline_thread_posix.x' 205 public_sub_headers += 'eina_inline_thread_posix.x'
207 sources += 'eina_file.c' 206 sources += 'eina_file.c'
208 sources += 'eina_sched_posix.c' 207 sources += 'eina_sched_posix.c'
208 public_sub_headers += 'eina_inline_lock_posix.x'
209endif 209endif
210 210
211eina_config = configuration_data() 211eina_config = configuration_data()
@@ -347,7 +347,7 @@ if cc.has_header('byteswap.h')
347endif 347endif
348 348
349if cc.has_header_symbol('pthread.h', 'pthread_spin_init') 349if cc.has_header_symbol('pthread.h', 'pthread_spin_init')
350 eina_config.set('EINA_HAVE_POSIX_SPINLOCK', '1') 350 eina_config.set('EINA_HAVE_PTHREAD_SPINLOCK', '1')
351endif 351endif
352 352
353if sys_osx == true 353if sys_osx == true
@@ -359,6 +359,15 @@ if sys_osx == true
359 endif 359 endif
360endif 360endif
361 361
362if sys_windows == true
363 if cc.has_header_symbol('synchapi.h', 'SetCriticalSectionSpinCount')
364 eina_config.set('EINA_HAVE_WIN32_SPINLOCK', '1')
365 endif
366 if cc.has_header_symbol('synchapi.h', 'InitializeSynchronizationBarrier')
367 eina_config.set('EINA_HAVE_WIN32_BARRIER', '1')
368 endif
369endif
370
362if host_machine.endian() == 'big' 371if host_machine.endian() == 'big'
363 eina_config.set('EINA_HAVE_WORDS_BIGENDIAN', '1') 372 eina_config.set('EINA_HAVE_WORDS_BIGENDIAN', '1')
364endif 373endif
@@ -423,4 +432,4 @@ pkgconfig.generate(eina_lib,
423 version : version_major + '.' + version_minor + '.' + version_micro, 432 version : version_major + '.' + version_minor + '.' + version_micro,
424 libraries : eina_pub_deps, 433 libraries : eina_pub_deps,
425) 434)
426endif \ No newline at end of file 435endif
diff --git a/src/lib/evil/unposix/meson.build b/src/lib/evil/unposix/meson.build
index 6fba6e87c2..53d82022fa 100644
--- a/src/lib/evil/unposix/meson.build
+++ b/src/lib/evil/unposix/meson.build
@@ -10,7 +10,6 @@ if sys_windows
10 'locale.h', 10 'locale.h',
11 'math.h', 11 'math.h',
12 'pthread.h', 12 'pthread.h',
13 'semaphore.h',
14 'stdlib.h', 13 'stdlib.h',
15 'string.h', 14 'string.h',
16 'strings.h', 15 'strings.h',
diff --git a/src/lib/evil/unposix/pthread.h b/src/lib/evil/unposix/pthread.h
index 7790821c8d..98491dcb49 100644
--- a/src/lib/evil/unposix/pthread.h
+++ b/src/lib/evil/unposix/pthread.h
@@ -5,24 +5,15 @@
5 5
6UNIMPLEMENTED typedef unsigned long long pthread_t; 6UNIMPLEMENTED typedef unsigned long long pthread_t;
7 7
8UNIMPLEMENTED_STRUCT_T(pthread_mutexattr)
9UNIMPLEMENTED_STRUCT_T(pthread_condattr)
10UNIMPLEMENTED_STRUCT_T(pthread_attr) 8UNIMPLEMENTED_STRUCT_T(pthread_attr)
11UNIMPLEMENTED_STRUCT_T(pthread_rwlock)
12UNIMPLEMENTED_STRUCT_T(pthread_cond)
13UNIMPLEMENTED_STRUCT_T(pthread_mutex)
14UNIMPLEMENTED_STRUCT_T(sem)
15 9
16UNIMPLEMENTED struct sched_param { 10UNIMPLEMENTED struct sched_param {
17 int sched_priority; 11 int sched_priority;
18}; 12};
19 13
20UNIMPLEMENTED typedef int pthread_key_t;
21
22#define SCHED_RR 5 14#define SCHED_RR 5
23#define SCHED_FIFO 6 15#define SCHED_FIFO 6
24 16
25#define PTHREAD_BARRIER_SERIAL_THREAD 1
26#define PTHREAD_CANCEL_ASYNCHRONOUS 2 17#define PTHREAD_CANCEL_ASYNCHRONOUS 2
27#define PTHREAD_CANCEL_ENABLE 3 18#define PTHREAD_CANCEL_ENABLE 3
28#define PTHREAD_CANCEL_DEFERRED 4 19#define PTHREAD_CANCEL_DEFERRED 4
@@ -32,12 +23,6 @@ UNIMPLEMENTED typedef int pthread_key_t;
32#define PTHREAD_CREATE_JOINABLE 8 23#define PTHREAD_CREATE_JOINABLE 8
33#define PTHREAD_EXPLICIT_SCHED 9 24#define PTHREAD_EXPLICIT_SCHED 9
34#define PTHREAD_INHERIT_SCHED 10 25#define PTHREAD_INHERIT_SCHED 10
35#define PTHREAD_MUTEX_DEFAULT 11
36#define PTHREAD_MUTEX_ERRORCHECK 12
37#define PTHREAD_MUTEX_NORMAL 13
38#define PTHREAD_MUTEX_RECURSIVE 14
39#define PTHREAD_MUTEX_ROBUST 15
40#define PTHREAD_MUTEX_STALLED 16
41#define PTHREAD_ONCE_INIT 17 26#define PTHREAD_ONCE_INIT 17
42#define PTHREAD_PRIO_INHERIT 18 27#define PTHREAD_PRIO_INHERIT 18
43#define PTHREAD_PRIO_NONE 19 28#define PTHREAD_PRIO_NONE 19
@@ -47,202 +32,4 @@ UNIMPLEMENTED typedef int pthread_key_t;
47#define PTHREAD_SCOPE_PROCESS 23 32#define PTHREAD_SCOPE_PROCESS 23
48#define PTHREAD_SCOPE_SYSTEM 24 33#define PTHREAD_SCOPE_SYSTEM 24
49 34
50UNIMPLEMENTED inline int pthread_mutex_trylock(void* m)
51{
52 #warning pthread_mutex_trylock is not implemented.
53 return 0;
54}
55
56UNIMPLEMENTED inline int pthread_mutex_lock(void* m)
57{
58 #warning pthread_mutex_lock is not implemented.
59 return 0;
60}
61
62UNIMPLEMENTED inline int pthread_mutex_unlock(void* m)
63{
64 #warning pthread_mutex_unlock is not implemented.
65 return 0;
66}
67
68UNIMPLEMENTED inline int pthread_cond_wait(void* c, void* m)
69{
70 #warning pthread_cond_wait is not implemented.
71 return 0;
72}
73
74UNIMPLEMENTED inline int pthread_cond_timedwait(void* c, void* m, int t)
75{
76 #warning pthread_cond_timedwait is not implemented.
77 return 0;
78}
79
80UNIMPLEMENTED inline int pthread_cond_broadcast(void* c)
81{
82 #warning pthread_cond_broadcast is not implemented.
83 return 0;
84}
85
86UNIMPLEMENTED inline int pthread_cond_signal(void* c)
87{
88 #warning pthread_cond_signal is not implemented.
89 return 0;
90}
91
92UNIMPLEMENTED inline int pthread_rwlock_init(void* a, ...)
93{
94 #warning pthread_rwlock_init is not implemented.
95 return 0;
96}
97
98UNIMPLEMENTED inline int pthread_mutexattr_settype(void* a, ...)
99{
100 #warning pthread_mutexattr_settype is not implemented.
101 return 0;
102}
103
104UNIMPLEMENTED inline int pthread_mutex_init(void* a, ...)
105{
106 #warning pthread_mutex_init is not implemented.
107 return 0;
108}
109
110UNIMPLEMENTED inline int pthread_mutex_destroy(void* a, ...)
111{
112 #warning pthread_mutex_destroy is not implemented.
113 return 0;
114}
115
116UNIMPLEMENTED inline int pthread_condattr_init(void* a, ...)
117{
118 #warning pthread_condattr_init is not implemented.
119 return 0;
120}
121
122UNIMPLEMENTED inline int pthread_cond_init(void* a, ...)
123{
124 #warning pthread_cond_init is not implemented.
125 return 0;
126}
127
128UNIMPLEMENTED inline int pthread_condattr_destroy(void* a, ...)
129{
130 #warning pthread_condattr_destroy is not implemented.
131 return 0;
132}
133
134UNIMPLEMENTED inline int pthread_cond_destroy(void* a, ...)
135{
136 #warning pthread_cond_destroy is not implemented.
137 return 0;
138}
139
140UNIMPLEMENTED inline int pthread_rwlock_destroy(void* a, ...)
141{
142 #warning pthread_rwlock_destroy is not implemented.
143 return 0;
144}
145
146UNIMPLEMENTED inline int pthread_rwlock_rdlock(void* c)
147{
148 #warning pthread_rwlock_rdlock is not implemented.
149 return 0;
150}
151
152UNIMPLEMENTED inline int pthread_rwlock_wrlock(void* c)
153{
154 #warning pthread_rwlock_wrlock is not implemented.
155 return 0;
156}
157
158UNIMPLEMENTED inline int pthread_rwlock_unlock(void* c)
159{
160 #warning pthread_rwlock_unlock is not implemented.
161 return 0;
162}
163
164UNIMPLEMENTED inline int pthread_key_create(void* c, void * d)
165{
166 #warning pthread_key_create is not implemented.
167 return 0;
168}
169
170UNIMPLEMENTED inline int pthread_key_delete(void* c)
171{
172 #warning pthread_key_delete is not implemented.
173 return 0;
174}
175
176UNIMPLEMENTED inline int pthread_getspecific(void* c)
177{
178 #warning pthread_getspecific is not implemented.
179 return 0;
180}
181
182UNIMPLEMENTED inline int pthread_setspecific(void* c, const void* d)
183{
184 #warning pthread_setspecific is not implemented.
185 return 0;
186}
187
188UNIMPLEMENTED inline int pthread_mutexattr_init(void* c, ...)
189{
190 #warning pthread_mutexattr_init is not implemented.
191 return 0;
192}
193
194UNIMPLEMENTED inline int pthread_getschedparam(void* a, ...)
195{
196 #warning pthread_getschedparam is not implemented.
197 return 0;
198}
199
200UNIMPLEMENTED inline int pthread_setschedparam(void* c, void* d, void* e)
201{
202 #warning pthread_ is not implemented.
203 return 0;
204}
205
206UNIMPLEMENTED inline int pthread_setcancelstate(void* a, ...)
207{
208 #warning pthread_setcancelstate is not implemented.
209 return 0;
210}
211
212UNIMPLEMENTED inline int pthread_testcancel()
213{
214 #warning pthread_testcancel is not implemented.
215 return 0;
216}
217
218UNIMPLEMENTED inline int pthread_cleanup_pop(void* a, ...)
219{
220 #warning pthread_cleanup_pop is not implemented.
221 return 0;
222}
223
224UNIMPLEMENTED inline int pthread_cleanup_push(void* a, ...)
225{
226 #warning pthread_cleanup_push is not implemented.
227 return 0;
228}
229
230UNIMPLEMENTED inline int pthread_attr_init(void* a, ...)
231{
232 #warning pthread_attr_init is not implemented.
233 return 0;
234}
235
236UNIMPLEMENTED inline int pthread_setcanceltype(void* a, ...)
237{
238 #warning pthread_setcanceltype is not implemented.
239 return 0;
240}
241
242UNIMPLEMENTED inline int pthread_mutexattr_destroy(void* a, ...)
243{
244 #warning pthread_mutexattr_destroy is not implemented.
245 return 0;
246}
247
248#endif 35#endif
diff --git a/src/lib/evil/unposix/semaphore.h b/src/lib/evil/unposix/semaphore.h
deleted file mode 100644
index 0e1f46f5bb..0000000000
--- a/src/lib/evil/unposix/semaphore.h
+++ /dev/null
@@ -1,59 +0,0 @@
1#ifndef SEMAPHORE_H
2#define SEMAPHORE_H
3
4#include "unimplemented.h"
5
6UNIMPLEMENTED_STRUCT_T(sem)
7
8UNIMPLEMENTED inline int sem_close(sem_t* sem)
9{
10 #warning sem_close is not implemented
11 return 0;
12}
13UNIMPLEMENTED inline int sem_destroy(sem_t* sem)
14{
15 #warning sem_destroy is not implemented
16 return 0;
17}
18UNIMPLEMENTED inline int sem_getvalue(sem_t* restrict sem, int* restrict x)
19{
20 #warning sem_getvalue is not implemented
21 return 0;
22}
23UNIMPLEMENTED inline int sem_init(sem_t* sem, int x, unsigned y)
24{
25 #warning sem_init is not implemented
26 return 0;
27}
28UNIMPLEMENTED inline sem_t* sem_open(const char* name, int x, ...)
29{
30 #warning sem_open is not implemented
31 return 0;
32}
33UNIMPLEMENTED inline int sem_post(sem_t* sem)
34{
35 #warning sem_post is not implemented
36 return 0;
37}
38UNIMPLEMENTED inline int sem_timedwait(sem_t* restrict sem, const struct timespec* restrict timeout)
39{
40 #warning sem_timedwait is not implemented
41 return 0;
42}
43UNIMPLEMENTED inline int sem_trywait(sem_t* sem)
44{
45 #warning sem_trywait is not implemented
46 return 0;
47}
48UNIMPLEMENTED inline int sem_unlink(const char* name)
49{
50 #warning sem_unlink is not implemented
51 return 0;
52}
53UNIMPLEMENTED inline int sem_wait(sem_t* sem)
54{
55 #warning sem_wait is not implemented
56 return 0;
57}
58
59#endif