diff options
author | Adrien Nader <adrien@notk.org> | 2015-02-11 12:15:43 +0100 |
---|---|---|
committer | Cedric BAIL <cedric@osg.samsung.com> | 2015-02-11 16:38:10 +0100 |
commit | 2cb0c1cadc46e1d89fea4e27399b36ce9f1526ff (patch) | |
tree | 1a0f4235fb31992073ad2f42369e1b2daea3cd69 /src | |
parent | c0683bc2dd361612a8e285f4966e715aed690b85 (diff) |
eina: remove Windows specific thread implementation and rely on posix compliant library instead.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/eina/eina_cpu.c | 4 | ||||
-rw-r--r-- | src/lib/eina/eina_inline_lock_win32.x | 610 | ||||
-rw-r--r-- | src/lib/eina/eina_lock.h | 4 | ||||
-rw-r--r-- | src/lib/eina/eina_main.c | 31 | ||||
-rw-r--r-- | src/lib/eina/eina_sched.c | 22 | ||||
-rw-r--r-- | src/lib/eina/eina_thread.c | 231 |
6 files changed, 8 insertions, 894 deletions
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 @{ */ | ||
29 | typedef CRITICAL_SECTION Eina_Lock; | ||
30 | typedef struct _Eina_Condition Eina_Condition; | ||
31 | typedef struct _Eina_RWLock Eina_RWLock; | ||
32 | typedef DWORD Eina_TLS; | ||
33 | typedef HANDLE Eina_Semaphore; | ||
34 | typedef Eina_Lock Eina_Spinlock; | ||
35 | |||
36 | #if _WIN32_WINNT >= 0x0600 | ||
37 | struct _Eina_Condition | ||
38 | { | ||
39 | CRITICAL_SECTION *mutex; /**< The locking mechanism for this condition variable */ | ||
40 | CONDITION_VARIABLE condition; /**< The condition variable */ | ||
41 | }; | ||
42 | |||
43 | struct _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 | ||
50 | struct _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 | |||
60 | struct _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 | |||
74 | EAPI extern Eina_Bool _eina_threads_activated; | ||
75 | EAPI extern Eina_Bool _eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb); | ||
76 | EAPI extern Eina_Bool _eina_thread_tls_cb_unregister(Eina_TLS key); | ||
77 | EAPI extern Eina_Bool _eina_thread_tls_key_add(Eina_TLS key); | ||
78 | |||
79 | |||
80 | static inline Eina_Bool | ||
81 | eina_lock_new(Eina_Lock *mutex) | ||
82 | { | ||
83 | InitializeCriticalSection(mutex); | ||
84 | |||
85 | return EINA_TRUE; | ||
86 | } | ||
87 | |||
88 | static inline void | ||
89 | eina_lock_free(Eina_Lock *mutex) | ||
90 | { | ||
91 | DeleteCriticalSection(mutex); | ||
92 | } | ||
93 | |||
94 | static inline Eina_Lock_Result | ||
95 | eina_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 | |||
106 | static inline Eina_Lock_Result | ||
107 | eina_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 | |||
116 | static inline Eina_Lock_Result | ||
117 | eina_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 | |||
128 | static inline void | ||
129 | eina_lock_debug(const Eina_Lock *mutex) | ||
130 | { | ||
131 | (void)mutex; | ||
132 | } | ||
133 | |||
134 | static inline Eina_Bool | ||
135 | eina_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 | |||
166 | static inline void | ||
167 | eina_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 | |||
179 | static 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 | |||
242 | static inline Eina_Bool | ||
243 | eina_condition_timedwait(Eina_Condition *cond, double val) | ||
244 | { | ||
245 | return _eina_condition_internal_timedwait(cond, (DWORD)(val * 1000)); | ||
246 | } | ||
247 | |||
248 | static inline Eina_Bool | ||
249 | eina_condition_wait(Eina_Condition *cond) | ||
250 | { | ||
251 | return _eina_condition_internal_timedwait(cond, INFINITE); | ||
252 | } | ||
253 | |||
254 | static inline Eina_Bool | ||
255 | eina_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 | |||
310 | static inline Eina_Bool | ||
311 | eina_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 | |||
333 | static inline Eina_Bool | ||
334 | eina_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 | |||
361 | static inline void | ||
362 | eina_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 | |||
373 | static inline Eina_Lock_Result | ||
374 | eina_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 | |||
406 | static inline Eina_Lock_Result | ||
407 | eina_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 | |||
438 | static inline Eina_Lock_Result | ||
439 | eina_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 | |||
487 | static inline Eina_Bool | ||
488 | eina_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 | |||
503 | static inline Eina_Bool | ||
504 | eina_tls_new(Eina_TLS *key) | ||
505 | { | ||
506 | return eina_tls_cb_new(key, NULL); | ||
507 | } | ||
508 | |||
509 | static inline void | ||
510 | eina_tls_free(Eina_TLS key) | ||
511 | { | ||
512 | _eina_thread_tls_cb_unregister(key); | ||
513 | TlsFree(key); | ||
514 | } | ||
515 | |||
516 | static inline void * | ||
517 | eina_tls_get(Eina_TLS key) | ||
518 | { | ||
519 | return (void*)TlsGetValue(key); | ||
520 | } | ||
521 | |||
522 | static inline Eina_Bool | ||
523 | eina_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 | |||
531 | static inline Eina_Bool | ||
532 | eina_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 | |||
543 | static inline Eina_Bool | ||
544 | eina_semaphore_free(Eina_Semaphore *sem) | ||
545 | { | ||
546 | if (!sem) | ||
547 | return EINA_FALSE; | ||
548 | |||
549 | CloseHandle(*sem); | ||
550 | return EINA_TRUE; | ||
551 | } | ||
552 | |||
553 | static inline Eina_Bool | ||
554 | eina_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 | |||
568 | static inline Eina_Bool | ||
569 | eina_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 | ||
578 | static inline Eina_Bool | ||
579 | eina_spinlock_new(Eina_Spinlock *spinlock) | ||
580 | { | ||
581 | return eina_lock_new(spinlock); | ||
582 | } | ||
583 | |||
584 | static inline Eina_Lock_Result | ||
585 | eina_spinlock_take(Eina_Spinlock *spinlock) | ||
586 | { | ||
587 | return eina_lock_take(spinlock); | ||
588 | } | ||
589 | |||
590 | static inline Eina_Lock_Result | ||
591 | eina_spinlock_take_try(Eina_Spinlock *spinlock) | ||
592 | { | ||
593 | return eina_lock_take_try(spinlock); | ||
594 | } | ||
595 | |||
596 | static inline Eina_Lock_Result | ||
597 | eina_spinlock_release(Eina_Spinlock *spinlock) | ||
598 | { | ||
599 | return eina_lock_release(spinlock); | ||
600 | } | ||
601 | |||
602 | static inline void | ||
603 | eina_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 | */ |
98 | typedef void (*Eina_TLS_Delete_Cb)(void *ptr); | 98 | typedef 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; | |||
103 | EAPI unsigned int eina_seed = 0; | 103 | EAPI unsigned int eina_seed = 0; |
104 | 104 | ||
105 | #ifdef EFL_HAVE_THREADS | 105 | #ifdef EFL_HAVE_THREADS |
106 | # ifdef _WIN32 | ||
107 | EAPI DWORD _eina_main_loop; | ||
108 | # else | ||
109 | EAPI pthread_t _eina_main_loop; | 106 | EAPI pthread_t _eina_main_loop; |
110 | # endif | ||
111 | static pid_t _eina_pid; | 107 | static 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 |
119 | EAPI int _eina_threads_debug = 0; | 115 | EAPI int _eina_threads_debug = 0; |
120 | # if !defined(_WIN32) | ||
121 | EAPI pthread_mutex_t _eina_tracking_lock; | 116 | EAPI pthread_mutex_t _eina_tracking_lock; |
122 | EAPI Eina_Inlist *_eina_tracking = NULL; | 117 | EAPI 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 @@ | |||
47 | EAPI void | 45 | EAPI void |
48 | eina_sched_prio_drop(void) | 46 | eina_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 | |||
43 | typedef struct _Eina_TLS_Cbs_Win32 Eina_TLS_Cbs_Win32; | ||
44 | struct _Eina_TLS_Cbs_Win32 | ||
45 | { | ||
46 | Eina_TLS key; | ||
47 | Eina_TLS_Delete_Cb cb; | ||
48 | }; | ||
49 | typedef struct _Eina_Thread_Win32 Eina_Thread_Win32; | ||
50 | struct _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 */ | ||
63 | static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */ | ||
64 | static Eina_List *_thread_pool = NULL; | ||
65 | static Eina_List *_thread_running = NULL; | ||
66 | static Eina_List *_tls_keys_cbs = NULL; | ||
67 | |||
68 | static 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 | |||
81 | static 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 | |||
97 | EAPI 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 | |||
114 | EAPI 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 | |||
126 | EAPI 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 | |||
146 | static 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 | |||
158 | static 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 | |||
174 | static 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 | |||
181 | static 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 | |||
191 | static 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 | |||
233 | static 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 | ||
319 | typedef struct _Eina_Thread_Call Eina_Thread_Call; | 88 | typedef struct _Eina_Thread_Call Eina_Thread_Call; |
320 | struct _Eina_Thread_Call | 89 | struct _Eina_Thread_Call |