summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Nader <adrien@notk.org>2015-02-11 12:15:43 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-02-11 16:38:10 +0100
commit2cb0c1cadc46e1d89fea4e27399b36ce9f1526ff (patch)
tree1a0f4235fb31992073ad2f42369e1b2daea3cd69
parentc0683bc2dd361612a8e285f4966e715aed690b85 (diff)
eina: remove Windows specific thread implementation and rely on posix compliant library instead.
-rw-r--r--m4/efl_threads.m412
-rw-r--r--src/lib/eina/eina_cpu.c4
-rw-r--r--src/lib/eina/eina_inline_lock_win32.x610
-rw-r--r--src/lib/eina/eina_lock.h4
-rw-r--r--src/lib/eina/eina_main.c31
-rw-r--r--src/lib/eina/eina_sched.c22
-rw-r--r--src/lib/eina/eina_thread.c231
7 files changed, 9 insertions, 905 deletions
diff --git a/m4/efl_threads.m4 b/m4/efl_threads.m4
index 9596908c96..88317af8db 100644
--- a/m4/efl_threads.m4
+++ b/m4/efl_threads.m4
@@ -25,17 +25,7 @@ gl_LOCK
25 25
26AC_DEFINE([EFL_HAVE_THREADS], [1], [Define to mention that POSIX or Win32 threads are supported]) 26AC_DEFINE([EFL_HAVE_THREADS], [1], [Define to mention that POSIX or Win32 threads are supported])
27 27
28case "$host_os" in 28_efl_have_posix_threads="${gl_use_threads}"
29 mingw*)
30 _efl_have_win32_threads="yes"
31 efl_have_setaffinity="yes"
32 AC_DEFINE([EFL_HAVE_WIN32_THREADS], [1], [Define to mention that Win32 threads are supported])
33 ;;
34 *)
35 _efl_have_posix_threads="${gl_use_threads}"
36 AC_DEFINE([EFL_HAVE_POSIX_THREADS], [1], [Define to mention that POSIX threads are supported])
37 ;;
38esac
39 29
40dnl System specific CFLAGS 30dnl System specific CFLAGS
41if test "x${_efl_have_posix_threads}" = "xyes"; then 31if test "x${_efl_have_posix_threads}" = "xyes"; then
diff --git a/src/lib/eina/eina_cpu.c b/src/lib/eina/eina_cpu.c
index 82c0f047d4..08b0860fbb 100644
--- a/src/lib/eina/eina_cpu.c
+++ b/src/lib/eina/eina_cpu.c
@@ -35,9 +35,7 @@
35# elif defined (__linux__) || defined(__GLIBC__) 35# elif defined (__linux__) || defined(__GLIBC__)
36# include <sched.h> 36# include <sched.h>
37# endif 37# endif
38# ifdef EFL_HAVE_POSIX_THREADS 38# include <pthread.h>
39# include <pthread.h>
40# endif
41 39
42# define TH_MAX 8 40# define TH_MAX 8
43#endif 41#endif
diff --git a/src/lib/eina/eina_inline_lock_win32.x b/src/lib/eina/eina_inline_lock_win32.x
index b3e8fbcf7d..e69de29bb2 100644
--- a/src/lib/eina/eina_inline_lock_win32.x
+++ b/src/lib/eina/eina_inline_lock_win32.x
@@ -1,610 +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_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#include <windows.h>
26#undef WIN32_LEAN_AND_MEAN
27
28/** @privatesection @{ */
29typedef CRITICAL_SECTION Eina_Lock;
30typedef struct _Eina_Condition Eina_Condition;
31typedef struct _Eina_RWLock Eina_RWLock;
32typedef DWORD Eina_TLS;
33typedef HANDLE Eina_Semaphore;
34typedef Eina_Lock Eina_Spinlock;
35
36#if _WIN32_WINNT >= 0x0600
37struct _Eina_Condition
38{
39 CRITICAL_SECTION *mutex; /**< The locking mechanism for this condition variable */
40 CONDITION_VARIABLE condition; /**< The condition variable */
41};
42
43struct _Eina_RWLock
44{
45 SRWLOCK mutex; /**< The locking mechanism */
46
47 Eina_Bool is_read_mode : 1; /**< Indicates if the lock is a read lock */
48};
49#else
50struct _Eina_Condition
51{
52 int waiters_count; /**< The count of threads that are waiting on this condition */
53 CRITICAL_SECTION waiters_count_lock; /**< The locking mechanism for the waiters_count member */
54 CRITICAL_SECTION *mutex; /**< The locking mechanism for the condition */
55 HANDLE semaphore; /**< Semaphore used to coordinate waiters */
56 HANDLE waiters_done; /**< Event to trigger when all the waiters are done */
57 Eina_Bool was_broadcast; /**< Indicates whether this condition has signalled its waiters */
58};
59
60struct _Eina_RWLock
61{
62 LONG readers_count; /**< The number of readers waiting for locks */
63 LONG writers_count; /**< The number of writers waiting for locks */
64 int readers; /**< The number of readers that have locks */
65 int writers; /**< The number of writers that have locks */
66
67 Eina_Lock mutex; /**< The locking mechanism */
68 Eina_Condition cond_read; /**< The condition for readers */
69 Eina_Condition cond_write; /**< The condition for writers */
70};
71#endif
72/** @} privatesection */
73
74EAPI extern Eina_Bool _eina_threads_activated;
75EAPI extern Eina_Bool _eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb);
76EAPI extern Eina_Bool _eina_thread_tls_cb_unregister(Eina_TLS key);
77EAPI extern Eina_Bool _eina_thread_tls_key_add(Eina_TLS key);
78
79
80static inline Eina_Bool
81eina_lock_new(Eina_Lock *mutex)
82{
83 InitializeCriticalSection(mutex);
84
85 return EINA_TRUE;
86}
87
88static inline void
89eina_lock_free(Eina_Lock *mutex)
90{
91 DeleteCriticalSection(mutex);
92}
93
94static inline Eina_Lock_Result
95eina_lock_take(Eina_Lock *mutex)
96{
97#ifdef EINA_HAVE_ON_OFF_THREADS
98 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
99#endif
100
101 EnterCriticalSection(mutex);
102
103 return EINA_LOCK_SUCCEED;
104}
105
106static inline Eina_Lock_Result
107eina_lock_take_try(Eina_Lock *mutex)
108{
109#ifdef EINA_HAVE_ON_OFF_THREADS
110 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
111#endif
112
113 return TryEnterCriticalSection(mutex) == 0 ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
114}
115
116static inline Eina_Lock_Result
117eina_lock_release(Eina_Lock *mutex)
118{
119#ifdef EINA_HAVE_ON_OFF_THREADS
120 if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
121#endif
122
123 LeaveCriticalSection(mutex);
124
125 return EINA_LOCK_SUCCEED;
126}
127
128static inline void
129eina_lock_debug(const Eina_Lock *mutex)
130{
131 (void)mutex;
132}
133
134static inline Eina_Bool
135eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
136{
137 cond->mutex = mutex;
138#if _WIN32_WINNT >= 0x0600
139 InitializeConditionVariable(&cond->condition);
140#else
141 cond->waiters_count = 0;
142 cond->was_broadcast = EINA_FALSE;
143 cond->semaphore = CreateSemaphore(NULL, // no security
144 0, // initially 0
145 0x7fffffff, // max count
146 NULL); // unnamed
147 if (!cond->semaphore)
148 return EINA_FALSE;
149
150 InitializeCriticalSection(&cond->waiters_count_lock);
151
152 cond->waiters_done = CreateEvent(NULL, // no security
153 FALSE, // auto-reset
154 FALSE, // non-signaled initially
155 NULL); // unnamed
156 if (!cond->waiters_done)
157 {
158 CloseHandle(cond->semaphore);
159 return EINA_FALSE;
160 }
161#endif
162
163 return EINA_TRUE;
164}
165
166static inline void
167eina_condition_free(Eina_Condition *cond)
168{
169#if _WIN32_WINNT >= 0x0600
170 /* Nothing to do */
171 (void)cond;
172#else
173 CloseHandle(cond->waiters_done);
174 DeleteCriticalSection(&cond->waiters_count_lock);
175 CloseHandle(cond->semaphore);
176#endif
177}
178
179static inline Eina_Bool
180_eina_condition_internal_timedwait(Eina_Condition *cond, DWORD t)
181{
182#if _WIN32_WINNT >= 0x0600
183 SleepConditionVariableCS(&cond->condition, cond->mutex, t);
184#else
185 DWORD ret;
186 Eina_Bool last_waiter;
187
188 /* Avoid race conditions. */
189 EnterCriticalSection(&cond->waiters_count_lock);
190 cond->waiters_count++;
191 LeaveCriticalSection(&cond->waiters_count_lock);
192
193 /*
194 * This call atomically releases the mutex and waits on the
195 * semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
196 * are called by another thread.
197 */
198 ret = SignalObjectAndWait(cond->mutex, cond->semaphore, t, FALSE);
199 if (ret == WAIT_FAILED)
200 return EINA_FALSE;
201
202 /* Reacquire lock to avoid race conditions. */
203 EnterCriticalSection(&cond->waiters_count_lock);
204
205 /* We're no longer waiting... */
206 cond->waiters_count--;
207
208 /* Check to see if we're the last waiter after <pthread_cond_broadcast>. */
209 last_waiter = (cond->was_broadcast) && (cond->waiters_count == 0);
210
211 LeaveCriticalSection(&cond->waiters_count_lock);
212
213 /*
214 * If we're the last waiter thread during this particular broadcast
215 * then let all the other threads proceed.
216 */
217 if (last_waiter)
218 {
219 /*
220 * This call atomically signals the <waiters_done_> event and waits until
221 * it can acquire the <external_mutex>. This is required to ensure fairness.
222 */
223 ret = SignalObjectAndWait(cond->waiters_done, cond->mutex, t, FALSE);
224 if (ret == WAIT_FAILED)
225 return EINA_FALSE;
226 }
227 else
228 {
229 /*
230 * Always regain the external mutex since that's the guarantee we
231 * give to our callers.
232 */
233 ret = WaitForSingleObject(cond->mutex, t);
234 if (ret == WAIT_FAILED)
235 return EINA_FALSE;
236 }
237#endif
238
239 return EINA_TRUE;
240}
241
242static inline Eina_Bool
243eina_condition_timedwait(Eina_Condition *cond, double val)
244{
245 return _eina_condition_internal_timedwait(cond, (DWORD)(val * 1000));
246}
247
248static inline Eina_Bool
249eina_condition_wait(Eina_Condition *cond)
250{
251 return _eina_condition_internal_timedwait(cond, INFINITE);
252}
253
254static inline Eina_Bool
255eina_condition_broadcast(Eina_Condition *cond)
256{
257#if _WIN32_WINNT >= 0x0600
258 WakeAllConditionVariable(&cond->condition);
259 return EINA_TRUE;
260#else
261 Eina_Bool have_waiters;
262
263 /*
264 * This is needed to ensure that <waiters_count_> and <was_broadcast_> are
265 * consistent relative to each other.
266 */
267 EnterCriticalSection(&cond->waiters_count_lock);
268 have_waiters = EINA_FALSE;
269
270 if (cond->waiters_count > 0)
271 {
272 /*
273 * We are broadcasting, even if there is just one waiter...
274 * Record that we are broadcasting, which helps optimize
275 * <pthread_cond_wait> for the non-broadcast case.
276 */
277 cond->was_broadcast = EINA_TRUE;
278 have_waiters = EINA_TRUE;
279 }
280
281 if (have_waiters)
282 {
283 DWORD ret;
284
285 /* Wake up all the waiters atomically. */
286 ret = ReleaseSemaphore(cond->semaphore, cond->waiters_count, 0);
287 LeaveCriticalSection(&cond->waiters_count_lock);
288 if (!ret) return EINA_FALSE;
289
290 /*
291 * Wait for all the awakened threads to acquire the counting
292 * semaphore.
293 */
294 ret = WaitForSingleObject(cond->waiters_done, INFINITE);
295 if (ret == WAIT_FAILED)
296 return EINA_FALSE;
297 /*
298 * This assignment is okay, even without the <waiters_count_lock_> held
299 * because no other waiter threads can wake up to access it.
300 */
301 cond->was_broadcast = EINA_FALSE;
302 }
303 else
304 LeaveCriticalSection(&cond->waiters_count_lock);
305
306 return EINA_TRUE;
307#endif
308}
309
310static inline Eina_Bool
311eina_condition_signal(Eina_Condition *cond)
312{
313#if _WIN32_WINNT >= 0x0600
314 WakeConditionVariable(&cond->condition);
315#else
316 Eina_Bool have_waiters;
317
318 EnterCriticalSection(&cond->waiters_count_lock);
319 have_waiters = (cond->waiters_count > 0);
320 LeaveCriticalSection(&cond->waiters_count_lock);
321
322 /* If there aren't any waiters, then this is a no-op. */
323 if (have_waiters)
324 {
325 if (!ReleaseSemaphore(cond->semaphore, 1, 0))
326 return EINA_FALSE;
327 }
328#endif
329
330 return EINA_TRUE;
331}
332
333static inline Eina_Bool
334eina_rwlock_new(Eina_RWLock *mutex)
335{
336#if _WIN32_WINNT >= 0x0600
337 InitializeSRWLock(&mutex->mutex);
338 return EINA_TRUE;
339#else
340 if (!eina_lock_new(&(mutex->mutex))) return EINA_FALSE;
341 if (!eina_condition_new(&(mutex->cond_read), &(mutex->mutex)))
342 goto on_error1;
343 if (!eina_condition_new(&(mutex->cond_write), &(mutex->mutex)))
344 goto on_error2;
345
346 mutex->readers_count = 0;
347 mutex->writers_count = 0;
348 mutex->readers = 0;
349 mutex->writers = 0;
350
351 return EINA_TRUE;
352
353 on_error2:
354 eina_condition_free(&(mutex->cond_read));
355 on_error1:
356 eina_lock_free(&(mutex->mutex));
357 return EINA_FALSE;
358#endif
359}
360
361static inline void
362eina_rwlock_free(Eina_RWLock *mutex)
363{
364#if _WIN32_WINNT >= 0x0600
365 (void)mutex;
366#else
367 eina_condition_free(&(mutex->cond_read));
368 eina_condition_free(&(mutex->cond_write));
369 eina_lock_free(&(mutex->mutex));
370#endif
371}
372
373static inline Eina_Lock_Result
374eina_rwlock_take_read(Eina_RWLock *mutex)
375{
376#if _WIN32_WINNT >= 0x0600
377 AcquireSRWLockShared(&mutex->mutex);
378 mutex->is_read_mode = EINA_TRUE;
379#else
380 DWORD res = 0;
381
382 if (eina_lock_take(&(mutex->mutex)) == EINA_LOCK_FAIL)
383 return EINA_LOCK_FAIL;
384
385 if (mutex->writers)
386 {
387 mutex->readers_count++;
388 while (mutex->writers)
389 {
390 EnterCriticalSection(&mutex->cond_write.waiters_count_lock);
391 mutex->cond_read.waiters_count++;
392 LeaveCriticalSection(&mutex->cond_write.waiters_count_lock);
393 res = WaitForSingleObject(mutex->cond_write.semaphore, INFINITE);
394 if (res != WAIT_OBJECT_0) break;
395 }
396 mutex->readers_count--;
397 }
398 if (res == 0)
399 mutex->readers++;
400 eina_lock_release(&(mutex->mutex));
401#endif
402
403 return EINA_LOCK_SUCCEED;
404}
405
406static inline Eina_Lock_Result
407eina_rwlock_take_write(Eina_RWLock *mutex)
408{
409#if _WIN32_WINNT >= 0x0600
410 AcquireSRWLockExclusive(&mutex->mutex);
411 mutex->is_read_mode = EINA_FALSE;
412#else
413 DWORD res = 0;
414
415 if (eina_lock_take(&(mutex->mutex)) == EINA_LOCK_FAIL)
416 return EINA_LOCK_FAIL;
417
418 if (mutex->writers || mutex->readers > 0)
419 {
420 mutex->writers_count++;
421 while (mutex->writers || mutex->readers > 0)
422 {
423 EnterCriticalSection(&mutex->cond_write.waiters_count_lock);
424 mutex->cond_read.waiters_count++;
425 LeaveCriticalSection(&mutex->cond_write.waiters_count_lock);
426 res = WaitForSingleObject(mutex->cond_write.semaphore, INFINITE);
427 if (res != WAIT_OBJECT_0) break;
428 }
429 mutex->writers_count--;
430 }
431 if (res == 0) mutex->writers = 1;
432 eina_lock_release(&(mutex->mutex));
433#endif
434
435 return EINA_LOCK_SUCCEED;
436}
437
438static inline Eina_Lock_Result
439eina_rwlock_release(Eina_RWLock *mutex)
440{
441#if _WIN32_WINNT >= 0x0600
442 if (mutex->is_read_mode)
443 ReleaseSRWLockShared(&mutex->mutex);
444 else
445 ReleaseSRWLockExclusive(&mutex->mutex);
446#else
447 if (eina_lock_take(&(mutex->mutex)) == EINA_LOCK_FAIL)
448 return EINA_LOCK_FAIL;
449
450 if (mutex->writers)
451 {
452 mutex->writers = 0;
453 if (mutex->readers_count == 1)
454 {
455 EnterCriticalSection(&mutex->cond_read.waiters_count_lock);
456 if (mutex->cond_read.waiters_count > 0)
457 ReleaseSemaphore(mutex->cond_read.semaphore, 1, 0);
458 LeaveCriticalSection(&mutex->cond_read.waiters_count_lock);
459 }
460 else if (mutex->readers_count > 0)
461 eina_condition_broadcast(&(mutex->cond_read));
462 else if (mutex->writers_count > 0)
463 {
464 EnterCriticalSection (&mutex->cond_write.waiters_count_lock);
465 if (mutex->cond_write.waiters_count > 0)
466 ReleaseSemaphore(mutex->cond_write.semaphore, 1, 0);
467 LeaveCriticalSection (&mutex->cond_write.waiters_count_lock);
468 }
469 }
470 else if (mutex->readers > 0)
471 {
472 mutex->readers--;
473 if (mutex->readers == 0 && mutex->writers_count > 0)
474 {
475 EnterCriticalSection (&mutex->cond_write.waiters_count_lock);
476 if (mutex->cond_write.waiters_count > 0)
477 ReleaseSemaphore(mutex->cond_write.semaphore, 1, 0);
478 LeaveCriticalSection (&mutex->cond_write.waiters_count_lock);
479 }
480 }
481 eina_lock_release(&(mutex->mutex));
482#endif
483
484 return EINA_LOCK_SUCCEED;
485}
486
487static inline Eina_Bool
488eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
489{
490 if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
491 return EINA_FALSE;
492 if (delete_cb)
493 {
494 if (!_eina_thread_tls_cb_register(*key, delete_cb))
495 {
496 TlsFree(*key);
497 return EINA_FALSE;
498 }
499 }
500 return EINA_TRUE;
501}
502
503static inline Eina_Bool
504eina_tls_new(Eina_TLS *key)
505{
506 return eina_tls_cb_new(key, NULL);
507}
508
509static inline void
510eina_tls_free(Eina_TLS key)
511{
512 _eina_thread_tls_cb_unregister(key);
513 TlsFree(key);
514}
515
516static inline void *
517eina_tls_get(Eina_TLS key)
518{
519 return (void*)TlsGetValue(key);
520}
521
522static inline Eina_Bool
523eina_tls_set(Eina_TLS key, const void *data)
524{
525 if (TlsSetValue(key, (LPVOID)data) == 0)
526 return EINA_FALSE;
527 _eina_thread_tls_key_add(key);
528 return EINA_TRUE;
529}
530
531static inline Eina_Bool
532eina_semaphore_new(Eina_Semaphore *sem, int count_init)
533{
534 if (!sem || (count_init <= 0))
535 return EINA_FALSE;
536
537 *sem = CreateSemaphore(NULL, count_init, 32767, NULL);
538 if (!*sem)
539 return EINA_FALSE;
540 return EINA_TRUE;
541}
542
543static inline Eina_Bool
544eina_semaphore_free(Eina_Semaphore *sem)
545{
546 if (!sem)
547 return EINA_FALSE;
548
549 CloseHandle(*sem);
550 return EINA_TRUE;
551}
552
553static inline Eina_Bool
554eina_semaphore_lock(Eina_Semaphore *sem)
555{
556 DWORD res;
557
558 if (!sem)
559 return EINA_FALSE;
560
561 res = WaitForSingleObject(*sem, 0L);
562 if (res == WAIT_OBJECT_0)
563 return EINA_TRUE;
564
565 return EINA_FALSE;
566}
567
568static inline Eina_Bool
569eina_semaphore_release(Eina_Semaphore *sem, int count_release)
570{
571 if (!sem)
572 return EINA_FALSE;
573
574 return ReleaseSemaphore(*sem, count_release, NULL) ? EINA_TRUE : EINA_FALSE;
575}
576
577// FIXME: Implement proper spinlock = http://www.codeproject.com/Articles/184046/Spin-Lock-in-C
578static inline Eina_Bool
579eina_spinlock_new(Eina_Spinlock *spinlock)
580{
581 return eina_lock_new(spinlock);
582}
583
584static inline Eina_Lock_Result
585eina_spinlock_take(Eina_Spinlock *spinlock)
586{
587 return eina_lock_take(spinlock);
588}
589
590static inline Eina_Lock_Result
591eina_spinlock_take_try(Eina_Spinlock *spinlock)
592{
593 return eina_lock_take_try(spinlock);
594}
595
596static inline Eina_Lock_Result
597eina_spinlock_release(Eina_Spinlock *spinlock)
598{
599 return eina_lock_release(spinlock);
600}
601
602static inline void
603eina_spinlock_free(Eina_Spinlock *spinlock)
604{
605 eina_lock_free(spinlock);
606}
607
608#include "eina_inline_lock_barrier.x"
609
610#endif
diff --git a/src/lib/eina/eina_lock.h b/src/lib/eina/eina_lock.h
index 7598869193..93e2e68e78 100644
--- a/src/lib/eina/eina_lock.h
+++ b/src/lib/eina/eina_lock.h
@@ -97,11 +97,7 @@ typedef enum
97 */ 97 */
98typedef void (*Eina_TLS_Delete_Cb)(void *ptr); 98typedef void (*Eina_TLS_Delete_Cb)(void *ptr);
99 99
100#ifdef _WIN32
101# include "eina_inline_lock_win32.x"
102#else
103# include "eina_inline_lock_posix.x" 100# include "eina_inline_lock_posix.x"
104#endif
105 101
106/** 102/**
107 * @brief A type definition for warning that a function was called from 103 * @brief A type definition for warning that a function was called from
diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c
index d4edb24558..7a9ec9fb74 100644
--- a/src/lib/eina/eina_main.c
+++ b/src/lib/eina/eina_main.c
@@ -103,11 +103,7 @@ EAPI Eina_Error EINA_ERROR_NOT_MAIN_LOOP = 0;
103EAPI unsigned int eina_seed = 0; 103EAPI unsigned int eina_seed = 0;
104 104
105#ifdef EFL_HAVE_THREADS 105#ifdef EFL_HAVE_THREADS
106# ifdef _WIN32
107EAPI DWORD _eina_main_loop;
108# else
109EAPI pthread_t _eina_main_loop; 106EAPI pthread_t _eina_main_loop;
110# endif
111static pid_t _eina_pid; 107static pid_t _eina_pid;
112#endif 108#endif
113 109
@@ -117,10 +113,8 @@ static int _mt_enabled = 0;
117 113
118#ifdef EFL_HAVE_THREADS 114#ifdef EFL_HAVE_THREADS
119EAPI int _eina_threads_debug = 0; 115EAPI int _eina_threads_debug = 0;
120# if !defined(_WIN32)
121EAPI pthread_mutex_t _eina_tracking_lock; 116EAPI pthread_mutex_t _eina_tracking_lock;
122EAPI Eina_Inlist *_eina_tracking = NULL; 117EAPI Eina_Inlist *_eina_tracking = NULL;
123# endif
124#endif 118#endif
125 119
126/* place module init/shutdown functions here to avoid other modules 120/* place module init/shutdown functions here to avoid other modules
@@ -280,11 +274,7 @@ eina_init(void)
280 } 274 }
281 275
282#ifdef EFL_HAVE_THREADS 276#ifdef EFL_HAVE_THREADS
283# ifdef _WIN32
284 _eina_main_loop = GetCurrentThreadId();
285# else
286 _eina_main_loop = pthread_self(); 277 _eina_main_loop = pthread_self();
287# endif
288 _eina_pid = getpid(); 278 _eina_pid = getpid();
289#endif 279#endif
290 280
@@ -426,24 +416,10 @@ eina_main_loop_is(void)
426{ 416{
427#ifdef EFL_HAVE_THREADS 417#ifdef EFL_HAVE_THREADS
428 pid_t pid; 418 pid_t pid;
429 419 if (pthread_equal(_eina_main_loop, pthread_self()))
430# ifdef _WIN32
431 if (_eina_main_loop == GetCurrentThreadId())
432 return EINA_TRUE; 420 return EINA_TRUE;
433# else
434 if (pthread_equal(_eina_main_loop, pthread_self()))
435 return EINA_TRUE;
436# endif
437 421
438 pid = getpid(); 422 pid = getpid();
439# ifdef _WIN32
440 if (pid != _eina_pid)
441 {
442 _eina_pid = pid;
443 _eina_main_loop = GetCurrentThreadId();
444 return EINA_TRUE;
445 }
446#else
447 if (pid != _eina_pid) 423 if (pid != _eina_pid)
448 { 424 {
449 /* This is in case of a fork, but don't like the solution */ 425 /* This is in case of a fork, but don't like the solution */
@@ -452,7 +428,6 @@ eina_main_loop_is(void)
452 return EINA_TRUE; 428 return EINA_TRUE;
453 } 429 }
454#endif 430#endif
455#endif
456 431
457 return EINA_FALSE; 432 return EINA_FALSE;
458} 433}
@@ -463,11 +438,7 @@ eina_main_loop_define(void)
463{ 438{
464#ifdef EFL_HAVE_THREADS 439#ifdef EFL_HAVE_THREADS
465 _eina_pid = getpid(); 440 _eina_pid = getpid();
466# ifdef _WIN32
467 _eina_main_loop = GetCurrentThreadId();
468# else
469 _eina_main_loop = pthread_self(); 441 _eina_main_loop = pthread_self();
470# endif
471#endif 442#endif
472} 443}
473 444
diff --git a/src/lib/eina/eina_sched.c b/src/lib/eina/eina_sched.c
index 71a08f5961..006f23fa4e 100644
--- a/src/lib/eina/eina_sched.c
+++ b/src/lib/eina/eina_sched.c
@@ -20,14 +20,12 @@
20# include "config.h" 20# include "config.h"
21#endif 21#endif
22 22
23#ifdef EFL_HAVE_POSIX_THREADS 23#include <pthread.h>
24# include <pthread.h> 24#ifdef __linux__
25# ifdef __linux__ 25# include <sched.h>
26# include <sched.h> 26# include <sys/time.h>
27# include <sys/time.h> 27# include <sys/resource.h>
28# include <sys/resource.h> 28# include <errno.h>
29# include <errno.h>
30# endif
31#endif 29#endif
32 30
33#ifdef EFL_HAVE_WIN32_THREADS 31#ifdef EFL_HAVE_WIN32_THREADS
@@ -47,7 +45,6 @@
47EAPI void 45EAPI void
48eina_sched_prio_drop(void) 46eina_sched_prio_drop(void)
49{ 47{
50#ifdef EFL_HAVE_POSIX_THREADS
51 struct sched_param param; 48 struct sched_param param;
52 int pol, ret; 49 int pol, ret;
53 pthread_t pthread_id; 50 pthread_t pthread_id;
@@ -92,11 +89,4 @@ eina_sched_prio_drop(void)
92 } 89 }
93 } 90 }
94# endif 91# endif
95#elif defined EFL_HAVE_WIN32_THREADS
96 if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL))
97 EINA_LOG_ERR("Can not set thread priority");
98#else
99 EINA_LOG_ERR("Eina does not have support for threads enabled"
100 "or it doesn't support setting scheduler priorities");
101#endif
102} 92}
diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c
index cd7d48e510..2924fc7360 100644
--- a/src/lib/eina/eina_thread.c
+++ b/src/lib/eina/eina_thread.c
@@ -25,238 +25,10 @@
25#include "eina_config.h" 25#include "eina_config.h"
26#include "eina_thread.h" 26#include "eina_thread.h"
27#include "eina_sched.h" 27#include "eina_sched.h"
28#ifdef _WIN32
29# include "eina_list.h"
30# include "eina_lock.h"
31#endif
32 28
33/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ 29/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
34#include "eina_safety_checks.h" 30#include "eina_safety_checks.h"
35 31
36#ifdef _WIN32
37# define WIN32_LEAN_AND_MEAN
38# include <windows.h>
39# undef WIN32_LEAN_AND_MEAN
40
41#include <process.h>
42
43typedef struct _Eina_TLS_Cbs_Win32 Eina_TLS_Cbs_Win32;
44struct _Eina_TLS_Cbs_Win32
45{
46 Eina_TLS key;
47 Eina_TLS_Delete_Cb cb;
48};
49typedef struct _Eina_Thread_Win32 Eina_Thread_Win32;
50struct _Eina_Thread_Win32
51{
52 HANDLE thread;
53 void *(*func)(void *data);
54 void *data;
55 void *ret;
56 Eina_List *tls_keys;
57
58 Eina_Thread index;
59};
60
61/* FIXME: For the moment Eina_Thread is considered not
62 thread safe, wondering if it's worth it */
63static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */
64static Eina_List *_thread_pool = NULL;
65static Eina_List *_thread_running = NULL;
66static Eina_List *_tls_keys_cbs = NULL;
67
68static inline Eina_TLS_Cbs_Win32 *
69_eina_thread_tls_cb_find(Eina_TLS key)
70{
71 Eina_TLS_Cbs_Win32 *cb;
72 Eina_List *l;
73
74 EINA_LIST_FOREACH(_tls_keys_cbs, l, cb)
75 if (cb->key == key)
76 return cb;
77
78 return NULL;
79}
80
81static inline void
82_eina_thread_tls_keys_clean(Eina_Thread_Win32 *tw)
83{
84 void *data;
85 Eina_TLS_Cbs_Win32 *cb;
86
87 EINA_LIST_FREE(tw->tls_keys, data)
88 {
89 Eina_TLS key = (Eina_TLS)(uintptr_t)data;
90 cb = _eina_thread_tls_cb_find(key);
91 if (cb)
92 cb->cb(eina_tls_get(key));
93 }
94 tw->tls_keys = NULL;
95}
96
97EAPI Eina_Bool
98_eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb)
99{
100 Eina_TLS_Cbs_Win32 *tls_cb;
101
102 if (!cb) return EINA_FALSE;
103
104 tls_cb = malloc(sizeof(Eina_TLS_Cbs_Win32));
105 if (!tls_cb) return EINA_FALSE;
106
107 tls_cb->key = key;
108 tls_cb->cb = cb;
109 _tls_keys_cbs = eina_list_append(_tls_keys_cbs, tls_cb);
110
111 return EINA_TRUE;
112}
113
114EAPI Eina_Bool
115_eina_thread_tls_cb_unregister(Eina_TLS key)
116{
117 Eina_TLS_Cbs_Win32 *cb = _eina_thread_tls_cb_find(key);
118 if (!cb) return EINA_FALSE;
119
120 _tls_keys_cbs = eina_list_remove(_tls_keys_cbs, cb);
121 free(cb);
122
123 return EINA_TRUE;
124}
125
126EAPI Eina_Bool
127_eina_thread_tls_key_add(Eina_TLS key)
128{
129 HANDLE t;
130 Eina_Thread_Win32 *tw;
131 Eina_List *l;
132
133 t = GetCurrentThread();
134 EINA_LIST_FOREACH(_thread_running, l, tw)
135 if (tw->thread == t)
136 {
137 void *data = (void *)(uintptr_t)key;
138 if (!eina_list_data_find(tw->tls_keys, data))
139 tw->tls_keys = eina_list_append(tw->tls_keys, data);
140 return EINA_TRUE;
141 }
142
143 return EINA_FALSE;
144}
145
146static Eina_Thread_Win32 *
147_eina_thread_win32_find(Eina_Thread index)
148{
149 Eina_Thread_Win32 *tw;
150 Eina_List *l;
151
152 EINA_LIST_FOREACH(_thread_running, l, tw)
153 if (tw->index == index)
154 return tw;
155 return NULL;
156}
157
158static inline Eina_Thread
159_eina_thread_self(void)
160{
161 HANDLE t;
162 Eina_Thread_Win32 *tw;
163 Eina_List *l;
164
165 t = GetCurrentThread();
166 EINA_LIST_FOREACH(_thread_running, l, tw)
167 if (tw->thread == t)
168 return tw->index;
169
170 /* We assume main loop == 0 on Windows */
171 return 0;
172}
173
174static inline Eina_Bool
175_eina_thread_equal(Eina_Thread t1, Eina_Thread t2)
176{
177 if (t1 == t2) return EINA_TRUE;
178 return EINA_FALSE;
179}
180
181static unsigned int WINAPI
182_eina_thread_win32_cb(LPVOID lpParam)
183{
184 Eina_Thread_Win32 *tw = lpParam;
185
186 tw->ret = tw->func(tw->data);
187
188 return 0;
189}
190
191static inline Eina_Bool
192_eina_thread_create(Eina_Thread *t,
193 int affinity,
194 void *(*func)(void *data),
195 const void *data)
196{
197 Eina_Thread_Win32 *tw;
198
199 tw = eina_list_data_get(_thread_pool);
200 _thread_pool = eina_list_remove_list(_thread_pool, _thread_pool);
201
202 if (!tw)
203 {
204 tw = malloc(sizeof (Eina_Thread_Win32));
205 if (!tw) goto on_error;
206
207 do {
208 tw->index = _current_index++;
209 } while (tw->index == 0); /* prevent having a "false" main loop */
210 }
211
212 tw->func = func;
213 tw->data = (void *)data;
214 tw->tls_keys = NULL;
215
216 tw->thread = (HANDLE)_beginthreadex(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
217 if (!tw->thread) goto on_error;
218
219 /* affinity is an hint, if we fail, we continue without */
220 if (affinity >= 0)
221 SetThreadAffinityMask(tw->thread, 1 << affinity);
222
223 _thread_running = eina_list_append(_thread_running, tw);
224
225 *t = tw->index;
226 return EINA_TRUE;
227
228 on_error:
229 _thread_pool = eina_list_append(_thread_pool, tw);
230 return EINA_FALSE;
231}
232
233static inline void *
234_eina_thread_join(Eina_Thread t)
235{
236 Eina_Thread_Win32 *tw;
237 void *ret;
238
239 tw = _eina_thread_win32_find(t);
240 if (!tw) return NULL;
241
242 WaitForSingleObject(tw->thread, INFINITE);
243 CloseHandle(tw->thread);
244
245 ret = tw->ret;
246
247 tw->ret = NULL;
248 tw->thread = NULL;
249 tw->func = NULL;
250 tw->data = NULL;
251 _eina_thread_tls_keys_clean(tw);
252
253 _thread_running = eina_list_remove(_thread_running, tw);
254 _thread_pool = eina_list_append(_thread_pool, _thread_pool);
255
256 return ret;
257}
258
259#elif defined(EFL_HAVE_POSIX_THREADS)
260# include <pthread.h> 32# include <pthread.h>
261# include <errno.h> 33# include <errno.h>
262 34
@@ -312,9 +84,6 @@ _eina_thread_self(void)
312 return (Eina_Thread)pthread_self(); 84 return (Eina_Thread)pthread_self();
313} 85}
314 86
315#else
316# error "Not supported any more"
317#endif
318 87
319typedef struct _Eina_Thread_Call Eina_Thread_Call; 88typedef struct _Eina_Thread_Call Eina_Thread_Call;
320struct _Eina_Thread_Call 89struct _Eina_Thread_Call