aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src/include/eina_inline_lock_posix.x
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eina/src/include/eina_inline_lock_posix.x')
-rw-r--r--libraries/eina/src/include/eina_inline_lock_posix.x556
1 files changed, 0 insertions, 556 deletions
diff --git a/libraries/eina/src/include/eina_inline_lock_posix.x b/libraries/eina/src/include/eina_inline_lock_posix.x
deleted file mode 100644
index 64e049a..0000000
--- a/libraries/eina/src/include/eina_inline_lock_posix.x
+++ /dev/null
@@ -1,556 +0,0 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2011 Vincent Torri
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_POSIX_X_
20#define EINA_INLINE_LOCK_POSIX_X_
21
22#ifdef EINA_UNUSED
23# undef EINA_UNUSED
24#endif
25#ifdef __GNUC__
26# define EINA_UNUSED __attribute__((unused))
27#else
28# define EINA_UNUSED
29#endif
30
31#include <errno.h>
32#ifndef __USE_UNIX98
33# define __USE_UNIX98
34# include <pthread.h>
35# undef __USE_UNIX98
36#else
37# include <pthread.h>
38#endif
39
40#include <semaphore.h>
41
42#include <sys/time.h>
43#include <stdio.h>
44
45#ifdef EINA_HAVE_DEBUG_THREADS
46#include <stdlib.h>
47#include <string.h>
48#include <assert.h>
49#include <execinfo.h>
50#define EINA_LOCK_DEBUG_BT_NUM 64
51typedef void (*Eina_Lock_Bt_Func) ();
52
53#include "eina_inlist.h"
54#endif
55
56typedef struct _Eina_Lock Eina_Lock;
57typedef struct _Eina_RWLock Eina_RWLock;
58typedef struct _Eina_Condition Eina_Condition;
59typedef pthread_key_t Eina_TLS;
60typedef sem_t Eina_Semaphore;
61
62struct _Eina_Lock
63{
64#ifdef EINA_HAVE_DEBUG_THREADS
65 EINA_INLIST;
66#endif
67 pthread_mutex_t mutex;
68#ifdef EINA_HAVE_DEBUG_THREADS
69 pthread_t lock_thread_id;
70 Eina_Lock_Bt_Func lock_bt[EINA_LOCK_DEBUG_BT_NUM];
71 int lock_bt_num;
72 Eina_Bool locked : 1;
73#endif
74};
75
76struct _Eina_Condition
77{
78 Eina_Lock *lock;
79 pthread_cond_t condition;
80};
81
82struct _Eina_RWLock
83{
84 pthread_rwlock_t mutex;
85#ifdef EINA_HAVE_DEBUG_THREADS
86 pthread_t lock_thread_wid;
87#endif
88};
89
90EAPI extern Eina_Bool _eina_threads_activated;
91
92#ifdef EINA_HAVE_DEBUG_THREADS
93EAPI extern int _eina_threads_debug;
94EAPI extern pthread_t _eina_main_loop;
95EAPI extern pthread_mutex_t _eina_tracking_lock;
96EAPI extern Eina_Inlist *_eina_tracking;
97#endif
98
99static inline void
100eina_lock_debug(const Eina_Lock *mutex)
101{
102#ifdef EINA_HAVE_DEBUG_THREADS
103 printf("lock %p, locked: %i, by %i\n",
104 mutex, (int)mutex->locked, (int)mutex->lock_thread_id);
105 backtrace_symbols_fd((void **)mutex->lock_bt, mutex->lock_bt_num, 1);
106#else
107 (void) mutex;
108#endif
109}
110
111static inline Eina_Bool
112eina_lock_new(Eina_Lock *mutex)
113{
114 pthread_mutexattr_t attr;
115
116#ifdef EINA_HAVE_DEBUG_THREADS
117 if (!_eina_threads_activated)
118 assert(pthread_equal(_eina_main_loop, pthread_self()));
119#endif
120
121 if (pthread_mutexattr_init(&attr) != 0)
122 return EINA_FALSE;
123 /* NOTE: PTHREAD_MUTEX_RECURSIVE is not allowed at all, you will break on/off
124 feature for sure with that change. */
125#ifdef EINA_HAVE_DEBUG_THREADS
126 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
127 return EINA_FALSE;
128 memset(mutex, 0, sizeof(Eina_Lock));
129#endif
130 if (pthread_mutex_init(&(mutex->mutex), &attr) != 0)
131 return EINA_FALSE;
132
133 pthread_mutexattr_destroy(&attr);
134
135 return EINA_TRUE;
136}
137
138static inline void
139eina_lock_free(Eina_Lock *mutex)
140{
141#ifdef EINA_HAVE_DEBUG_THREADS
142 if (!_eina_threads_activated)
143 assert(pthread_equal(_eina_main_loop, pthread_self()));
144#endif
145
146 pthread_mutex_destroy(&(mutex->mutex));
147#ifdef EINA_HAVE_DEBUG_THREADS
148 memset(mutex, 0, sizeof(Eina_Lock));
149#endif
150}
151
152static inline Eina_Lock_Result
153eina_lock_take(Eina_Lock *mutex)
154{
155 Eina_Lock_Result ret = EINA_LOCK_FAIL;
156 int ok;
157
158#ifdef EINA_HAVE_ON_OFF_THREADS
159 if (!_eina_threads_activated)
160 {
161#ifdef EINA_HAVE_DEBUG_THREADS
162 assert(pthread_equal(_eina_main_loop, pthread_self()));
163#endif
164 return EINA_LOCK_SUCCEED;
165 }
166#endif
167
168#ifdef EINA_HAVE_DEBUG_THREADS
169 if (_eina_threads_debug)
170 {
171 struct timeval t0, t1;
172 int dt;
173
174 gettimeofday(&t0, NULL);
175 ok = pthread_mutex_lock(&(mutex->mutex));
176 gettimeofday(&t1, NULL);
177
178 dt = (t1.tv_sec - t0.tv_sec) * 1000000;
179 if (t1.tv_usec > t0.tv_usec)
180 dt += (t1.tv_usec - t0.tv_usec);
181 else
182 dt -= t0.tv_usec - t1.tv_usec;
183 dt /= 1000;
184
185 if (dt > _eina_threads_debug) abort();
186 }
187 else
188 {
189#endif
190 ok = pthread_mutex_lock(&(mutex->mutex));
191#ifdef EINA_HAVE_DEBUG_THREADS
192 }
193#endif
194
195 if (ok == 0) ret = EINA_LOCK_SUCCEED;
196 else if (ok == EDEADLK)
197 {
198 printf("ERROR ERROR: DEADLOCK on lock %p\n", mutex);
199 eina_lock_debug(mutex);
200 ret = EINA_LOCK_DEADLOCK; // magic
201#ifdef EINA_HAVE_DEBUG_THREADS
202 if (_eina_threads_debug) abort();
203#endif
204 }
205
206#ifdef EINA_HAVE_DEBUG_THREADS
207 mutex->locked = 1;
208 mutex->lock_thread_id = pthread_self();
209 mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
210
211 pthread_mutex_lock(&_eina_tracking_lock);
212 _eina_tracking = eina_inlist_append(_eina_tracking,
213 EINA_INLIST_GET(mutex));
214 pthread_mutex_unlock(&_eina_tracking_lock);
215#endif
216
217 return ret;
218}
219
220static inline Eina_Lock_Result
221eina_lock_take_try(Eina_Lock *mutex)
222{
223 Eina_Lock_Result ret = EINA_LOCK_FAIL;
224 int ok;
225
226#ifdef EINA_HAVE_ON_OFF_THREADS
227 if (!_eina_threads_activated)
228 {
229#ifdef EINA_HAVE_DEBUG_THREADS
230 assert(pthread_equal(_eina_main_loop, pthread_self()));
231#endif
232 return EINA_LOCK_SUCCEED;
233 }
234#endif
235
236#ifdef EINA_HAVE_DEBUG_THREADS
237 if (!_eina_threads_activated)
238 assert(pthread_equal(_eina_main_loop, pthread_self()));
239#endif
240
241 ok = pthread_mutex_trylock(&(mutex->mutex));
242 if (ok == 0) ret = EINA_LOCK_SUCCEED;
243 else if (ok == EDEADLK)
244 {
245 printf("ERROR ERROR: DEADLOCK on trylock %p\n", mutex);
246 ret = EINA_LOCK_DEADLOCK; // magic
247 }
248#ifdef EINA_HAVE_DEBUG_THREADS
249 if (ret == EINA_LOCK_SUCCEED)
250 {
251 mutex->locked = 1;
252 mutex->lock_thread_id = pthread_self();
253 mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
254
255 pthread_mutex_lock(&_eina_tracking_lock);
256 _eina_tracking = eina_inlist_append(_eina_tracking,
257 EINA_INLIST_GET(mutex));
258 pthread_mutex_unlock(&_eina_tracking_lock);
259 }
260#endif
261 return ret;
262}
263
264static inline Eina_Lock_Result
265eina_lock_release(Eina_Lock *mutex)
266{
267 Eina_Lock_Result ret;
268
269#ifdef EINA_HAVE_ON_OFF_THREADS
270 if (!_eina_threads_activated)
271 {
272#ifdef EINA_HAVE_DEBUG_THREADS
273 assert(pthread_equal(_eina_main_loop, pthread_self()));
274#endif
275 return EINA_LOCK_SUCCEED;
276 }
277#endif
278
279#ifdef EINA_HAVE_DEBUG_THREADS
280 pthread_mutex_lock(&_eina_tracking_lock);
281 _eina_tracking = eina_inlist_remove(_eina_tracking,
282 EINA_INLIST_GET(mutex));
283 pthread_mutex_unlock(&_eina_tracking_lock);
284
285 mutex->locked = 0;
286 mutex->lock_thread_id = 0;
287 memset(mutex->lock_bt, 0, EINA_LOCK_DEBUG_BT_NUM * sizeof(Eina_Lock_Bt_Func));
288 mutex->lock_bt_num = 0;
289#endif
290 ret = (pthread_mutex_unlock(&(mutex->mutex)) == 0) ?
291 EINA_LOCK_SUCCEED : EINA_LOCK_FAIL;
292 return ret;
293}
294
295static inline Eina_Bool
296eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
297{
298#ifdef EINA_HAVE_DEBUG_THREADS
299 assert(mutex != NULL);
300 if (!_eina_threads_activated)
301 assert(pthread_equal(_eina_main_loop, pthread_self()));
302 memset(cond, 0, sizeof (Eina_Condition));
303#endif
304
305 cond->lock = mutex;
306 if (pthread_cond_init(&cond->condition, NULL) != 0)
307 {
308#ifdef EINA_HAVE_DEBUG_THREADS
309 if (errno == EBUSY)
310 printf("eina_condition_new on already initialized Eina_Condition\n");
311#endif
312 return EINA_FALSE;
313 }
314
315 return EINA_TRUE;
316}
317
318static inline void
319eina_condition_free(Eina_Condition *cond)
320{
321#ifdef EINA_HAVE_DEBUG_THREADS
322 if (!_eina_threads_activated)
323 assert(pthread_equal(_eina_main_loop, pthread_self()));
324#endif
325
326 pthread_cond_destroy(&(cond->condition));
327#ifdef EINA_HAVE_DEBUG_THREADS
328 memset(cond, 0, sizeof (Eina_Condition));
329#endif
330}
331
332static inline Eina_Bool
333eina_condition_wait(Eina_Condition *cond)
334{
335 Eina_Bool r;
336
337#ifdef EINA_HAVE_DEBUG_THREADS
338 assert(_eina_threads_activated);
339 assert(cond->lock != NULL);
340
341 pthread_mutex_lock(&_eina_tracking_lock);
342 _eina_tracking = eina_inlist_remove(_eina_tracking,
343 EINA_INLIST_GET(cond->lock));
344 pthread_mutex_unlock(&_eina_tracking_lock);
345#endif
346
347 r = pthread_cond_wait(&(cond->condition),
348 &(cond->lock->mutex)) == 0 ? EINA_TRUE : EINA_FALSE;
349
350#ifdef EINA_HAVE_DEBUG_THREADS
351 pthread_mutex_lock(&_eina_tracking_lock);
352 _eina_tracking = eina_inlist_append(_eina_tracking,
353 EINA_INLIST_GET(cond->lock));
354 pthread_mutex_unlock(&_eina_tracking_lock);
355#endif
356
357 return r;
358}
359
360static inline Eina_Bool
361eina_condition_timedwait(Eina_Condition *cond, double t)
362{
363 struct timespec tv;
364 Eina_Bool r;
365
366#ifdef EINA_HAVE_DEBUG_THREADS
367 assert(_eina_threads_activated);
368 assert(cond->lock != NULL);
369
370 pthread_mutex_lock(&_eina_tracking_lock);
371 _eina_tracking = eina_inlist_remove(_eina_tracking,
372 EINA_INLIST_GET(cond->lock));
373 pthread_mutex_unlock(&_eina_tracking_lock);
374#endif
375
376 tv.tv_sec = t;
377 tv.tv_nsec = (t - (double) tv.tv_sec) * 1000000000;
378
379 r = pthread_cond_timedwait(&(cond->condition),
380 &(cond->lock->mutex),
381 &tv) == 0 ?
382 EINA_TRUE : EINA_FALSE;
383
384#ifdef EINA_HAVE_DEBUG_THREADS
385 pthread_mutex_lock(&_eina_tracking_lock);
386 _eina_tracking = eina_inlist_append(_eina_tracking,
387 EINA_INLIST_GET(cond->lock));
388 pthread_mutex_unlock(&_eina_tracking_lock);
389#endif
390
391 return r;
392}
393
394static inline Eina_Bool
395eina_condition_broadcast(Eina_Condition *cond)
396{
397#ifdef EINA_HAVE_DEBUG_THREADS
398 assert(cond->lock != NULL);
399#endif
400
401 return pthread_cond_broadcast(&(cond->condition)) == 0 ? EINA_TRUE : EINA_FALSE;
402}
403
404static inline Eina_Bool
405eina_condition_signal(Eina_Condition *cond)
406{
407#ifdef EINA_HAVE_DEBUG_THREADS
408 assert(cond->lock != NULL);
409#endif
410
411 return pthread_cond_signal(&(cond->condition)) == 0 ? EINA_TRUE : EINA_FALSE;
412}
413
414static inline Eina_Bool
415eina_rwlock_new(Eina_RWLock *mutex)
416{
417#ifdef EINA_HAVE_DEBUG_THREADS
418 if (!_eina_threads_activated)
419 assert(pthread_equal(_eina_main_loop, pthread_self()));
420#endif
421
422 if (pthread_rwlock_init(&(mutex->mutex), NULL) != 0)
423 return EINA_FALSE;
424 return EINA_TRUE;
425}
426
427static inline void
428eina_rwlock_free(Eina_RWLock *mutex)
429{
430#ifdef EINA_HAVE_DEBUG_THREADS
431 if (!_eina_threads_activated)
432 assert(pthread_equal(_eina_main_loop, pthread_self()));
433#endif
434
435 pthread_rwlock_destroy(&(mutex->mutex));
436}
437
438static inline Eina_Lock_Result
439eina_rwlock_take_read(Eina_RWLock *mutex)
440{
441#ifdef EINA_HAVE_ON_OFF_THREADS
442 if (!_eina_threads_activated)
443 {
444#ifdef EINA_HAVE_DEBUG_THREADS
445 assert(pthread_equal(_eina_main_loop, pthread_self()));
446#endif
447 return EINA_LOCK_SUCCEED;
448 }
449#endif
450
451 if (pthread_rwlock_rdlock(&(mutex->mutex)) != 0)
452 return EINA_LOCK_FAIL;
453 return EINA_LOCK_SUCCEED;
454}
455
456static inline Eina_Lock_Result
457eina_rwlock_take_write(Eina_RWLock *mutex)
458{
459#ifdef EINA_HAVE_ON_OFF_THREADS
460 if (!_eina_threads_activated)
461 {
462#ifdef EINA_HAVE_DEBUG_THREADS
463 assert(pthread_equal(_eina_main_loop, pthread_self()));
464#endif
465 return EINA_LOCK_SUCCEED;
466 }
467#endif
468
469 if (pthread_rwlock_wrlock(&(mutex->mutex)) != 0)
470 return EINA_LOCK_FAIL;
471 return EINA_LOCK_SUCCEED;
472}
473
474static inline Eina_Lock_Result
475eina_rwlock_release(Eina_RWLock *mutex)
476{
477#ifdef EINA_HAVE_ON_OFF_THREADS
478 if (!_eina_threads_activated)
479 {
480#ifdef EINA_HAVE_DEBUG_THREADS
481 assert(pthread_equal(_eina_main_loop, pthread_self()));
482#endif
483 return EINA_LOCK_SUCCEED;
484 }
485#endif
486
487 if (pthread_rwlock_unlock(&(mutex->mutex)) != 0)
488 return EINA_LOCK_FAIL;
489 return EINA_LOCK_SUCCEED;
490}
491
492static inline Eina_Bool
493eina_tls_new(Eina_TLS *key)
494{
495 if (pthread_key_create(key, NULL) != 0)
496 return EINA_FALSE;
497 return EINA_TRUE;
498}
499
500static inline void
501eina_tls_free(Eina_TLS key)
502{
503 pthread_key_delete(key);
504}
505
506static inline void *
507eina_tls_get(Eina_TLS key)
508{
509 return pthread_getspecific(key);
510}
511
512static inline Eina_Bool
513eina_tls_set(Eina_TLS key, const void *data)
514{
515 if (pthread_setspecific(key, data) != 0)
516 return EINA_FALSE;
517 return EINA_TRUE;
518}
519
520static inline Eina_Bool
521eina_semaphore_new(Eina_Semaphore *sem, int count_init)
522{
523 if (!sem || (count_init <= 0))
524 return EINA_FALSE;
525
526 return (sem_init(sem, count_init, 1) == 0) ? EINA_TRUE : EINA_FALSE;
527}
528
529static inline Eina_Bool
530eina_semaphore_free(Eina_Semaphore *sem)
531{
532 if (!sem)
533 return EINA_FALSE;
534
535 return (sem_destroy(sem) == 0) ? EINA_TRUE : EINA_FALSE;
536}
537
538static inline Eina_Bool
539eina_semaphore_lock(Eina_Semaphore *sem)
540{
541 if (!sem)
542 return EINA_FALSE;
543
544 return (sem_wait(sem) == 0) ? EINA_TRUE : EINA_FALSE;
545}
546
547static inline Eina_Bool
548eina_semaphore_release(Eina_Semaphore *sem, int count_release EINA_UNUSED)
549{
550 if (!sem)
551 return EINA_FALSE;
552
553 return (sem_post(sem) == 0) ? EINA_TRUE : EINA_FALSE;
554}
555
556#endif