1 /* threads.c: Thread Abstraction Functions
2 *
3 * Copyright (C) 2014 Michael Smith <msmith@icecast.org>,
4 * Brendan Cully <brendan@xiph.org>,
5 * Karl Heyes <karl@xiph.org>,
6 * Jack Moffitt <jack@icecast.org>,
7 * Ed "oddsock" Zaleski <oddsock@xiph.org>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <sys/types.h>
36
37 #include <pthread.h>
38
39 #ifndef _WIN32
40 #include <unistd.h>
41 #include <sys/time.h>
42 #else
43 #include <windows.h>
44 #include <winbase.h>
45 #endif
46
47 #include <signal.h>
48
49 #include <thread/thread.h>
50 #include <avl/avl.h>
51 #ifdef THREAD_DEBUG
52 #include <log/log.h>
53 #endif
54
55 #ifdef _WIN32
56 #define __FUNCTION__ __FILE__
57 #endif
58
59 #ifdef THREAD_DEBUG
60 #define CATMODULE "thread"
61 #define LOG_ERROR(y) log_write(_logid, 1, CATMODULE "/", __FUNCTION__, y)
62 #define LOG_ERROR3(y, z1, z2, z3) log_write(_logid, 1, CATMODULE "/", __FUNCTION__, y, z1, z2, z3)
63 #define LOG_ERROR7(y, z1, z2, z3, z4, z5, z6, z7) log_write(_logid, 1, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5, z6, z7)
64
65 #define LOG_WARN(y) log_write(_logid, 2, CATMODULE "/", __FUNCTION__, y)
66 #define LOG_WARN3(y, z1, z2, z3) log_write(_logid, 2, CATMODULE "/", __FUNCTION__, y, z1, z2, z3)
67 #define LOG_WARN5(y, z1, z2, z3, z4, z5) log_write(_logid, 2, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5)
68 #define LOG_WARN7(y, z1, z2, z3, z4, z5, z6, z7) log_write(_logid, 2, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5, z6, z7)
69
70 #define LOG_INFO(y) log_write(_logid, 3, CATMODULE "/", __FUNCTION__, y)
71 #define LOG_INFO4(y, z1, z2, z3, z4) log_write(_logid, 3, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4)
72 #define LOG_INFO5(y, z1, z2, z3, z4, z5) log_write(_logid, 3, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5)
73
74 #define LOG_DEBUG(y) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y)
75 #define LOG_DEBUG2(y, z1, z2) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1, z2)
76 #define LOG_DEBUG5(y, z1, z2, z3, z4, z5) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5)
77 #endif
78
79 /* thread starting structure */
80 typedef struct thread_start_tag {
81 /* the real start routine and arg */
82 void *(*start_routine)(void *);
83 void *arg;
84
85 /* the other stuff we need to make sure this thread is inserted into
86 ** the thread tree
87 */
88 thread_type *thread;
89 pthread_t sys_thread;
90 } thread_start_t;
91
92 static long _next_thread_id = 0;
93 static int _initialized = 0;
94 static avl_tree *_threadtree = NULL;
95
96 #ifdef DEBUG_MUTEXES
97 static mutex_t _threadtree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1,
98 PTHREAD_MUTEX_INITIALIZER};
99 #else
100 static mutex_t _threadtree_mutex = { PTHREAD_MUTEX_INITIALIZER };
101 #endif
102
103
104
105 #ifdef DEBUG_MUTEXES
106 static int _logid = -1;
107 static long _next_mutex_id = 0;
108
109 static avl_tree *_mutextree = NULL;
110 static mutex_t _mutextree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1,
111 PTHREAD_MUTEX_INITIALIZER};
112 #endif
113
114 #ifdef DEBUG_MUTEXES
115 static mutex_t _library_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1,
116 PTHREAD_MUTEX_INITIALIZER};
117 #else
118 static mutex_t _library_mutex = { PTHREAD_MUTEX_INITIALIZER };
119 #endif
120
121 /* INTERNAL FUNCTIONS */
122
123 /* avl tree functions */
124 #ifdef DEBUG_MUTEXES
125 static int _compare_mutexes(void *compare_arg, void *a, void *b);
126 static int _free_mutex(void *key);
127 #endif
128
129 static int _compare_threads(void *compare_arg, void *a, void *b);
130 static int _free_thread(void *key);
131
132 /* mutex fuctions */
133 static void _mutex_create(mutex_t *mutex);
134 static void _mutex_lock(mutex_t *mutex);
135 static void _mutex_unlock(mutex_t *mutex);
136
137 /* misc thread stuff */
138 static void *_start_routine(void *arg);
139 static void _catch_signals(void);
140 static void _block_signals(void);
141
142 /* LIBRARY INITIALIZATION */
143
thread_initialize(void)144 void thread_initialize(void)
145 {
146 thread_type *thread;
147
148 /* set up logging */
149
150 #ifdef THREAD_DEBUG
151 log_initialize();
152 _logid = log_open("thread.log");
153 log_set_level(_logid, THREAD_DEBUG);
154 #endif
155
156 #ifdef DEBUG_MUTEXES
157 /* create all the internal mutexes, and initialize the mutex tree */
158
159 _mutextree = avl_tree_new(_compare_mutexes, NULL);
160
161 /* we have to create this one by hand, because there's no
162 ** mutextree_mutex to lock yet!
163 */
164 _mutex_create(&_mutextree_mutex);
165
166 _mutextree_mutex.mutex_id = _next_mutex_id++;
167 avl_insert(_mutextree, (void *)&_mutextree_mutex);
168 #endif
169
170 thread_mutex_create(&_threadtree_mutex);
171 thread_mutex_create(&_library_mutex);
172
173 /* initialize the thread tree and insert the main thread */
174
175 _threadtree = avl_tree_new(_compare_threads, NULL);
176
177 thread = (thread_type *)malloc(sizeof(thread_type));
178
179 thread->thread_id = _next_thread_id++;
180 thread->line = 0;
181 thread->file = strdup("main.c");
182 thread->sys_thread = pthread_self();
183 thread->create_time = time(NULL);
184 thread->name = strdup("Main Thread");
185
186 avl_insert(_threadtree, (void *)thread);
187
188 _catch_signals();
189
190 _initialized = 1;
191 }
192
thread_shutdown(void)193 void thread_shutdown(void)
194 {
195 if (_initialized == 1) {
196 thread_mutex_destroy(&_library_mutex);
197 thread_mutex_destroy(&_threadtree_mutex);
198 #ifdef THREAD_DEBUG
199 thread_mutex_destroy(&_mutextree_mutex);
200
201 avl_tree_free(_mutextree, _free_mutex);
202 #endif
203 avl_tree_free(_threadtree, _free_thread);
204 _threadtree = NULL;
205 }
206
207 #ifdef THREAD_DEBUG
208 log_close(_logid);
209 log_shutdown();
210 #endif
211
212 }
213
214 /*
215 * Signals should be handled by the main thread, nowhere else.
216 * I'm using POSIX signal interface here, until someone tells me
217 * that I should use signal/sigset instead
218 *
219 * This function only valid for non-Win32
220 */
_block_signals(void)221 static void _block_signals(void)
222 {
223 #if !defined(_WIN32) && !defined(__ANDROID__)
224 sigset_t ss;
225
226 sigfillset(&ss);
227
228 /* These ones we want */
229 sigdelset(&ss, SIGKILL);
230 sigdelset(&ss, SIGSTOP);
231 sigdelset(&ss, SIGSEGV);
232 sigdelset(&ss, SIGCHLD);
233 sigdelset(&ss, SIGBUS);
234 if (pthread_sigmask(SIG_BLOCK, &ss, NULL) != 0) {
235 #ifdef THREAD_DEBUG
236 LOG_ERROR("Pthread_sigmask() failed for blocking signals");
237 #endif
238 }
239 #endif
240 }
241
242 /*
243 * Let the calling thread catch all the relevant signals
244 *
245 * This function only valid for non-Win32
246 */
_catch_signals(void)247 static void _catch_signals(void)
248 {
249 #if !defined(_WIN32) && !defined(__ANDROID__)
250 sigset_t ss;
251
252 sigemptyset(&ss);
253
254 /* These ones should only be accepted by the signal handling thread (main thread) */
255 sigaddset(&ss, SIGHUP);
256 sigaddset(&ss, SIGCHLD);
257 sigaddset(&ss, SIGINT);
258 sigaddset(&ss, SIGPIPE);
259 sigaddset(&ss, SIGTERM);
260
261 if (pthread_sigmask(SIG_UNBLOCK, &ss, NULL) != 0) {
262 #ifdef THREAD_DEBUG
263 LOG_ERROR("pthread_sigmask() failed for catching signals!");
264 #endif
265 }
266 #endif
267 }
268
269
thread_create_c(char * name,void * (* start_routine)(void *),void * arg,int detached,int line,char * file)270 thread_type *thread_create_c(char *name, void *(*start_routine)(void *),
271 void *arg, int detached, int line, char *file)
272 {
273 thread_type *thread = NULL;
274 thread_start_t *start = NULL;
275 pthread_attr_t attr;
276
277 thread = (thread_type *)calloc(1, sizeof(thread_type));
278 do {
279 if (thread == NULL)
280 break;
281 start = (thread_start_t *)calloc(1, sizeof(thread_start_t));
282 if (start == NULL)
283 break;
284 if (pthread_attr_init (&attr) < 0)
285 break;
286
287 thread->line = line;
288 thread->file = strdup(file);
289
290 _mutex_lock (&_threadtree_mutex);
291 thread->thread_id = _next_thread_id++;
292 _mutex_unlock (&_threadtree_mutex);
293
294 thread->name = strdup(name);
295 thread->create_time = time(NULL);
296
297 start->start_routine = start_routine;
298 start->arg = arg;
299 start->thread = thread;
300
301 pthread_attr_setstacksize (&attr, 512*1024);
302
303 #ifndef __ANDROID__
304 pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED);
305 #endif
306
307 if (detached)
308 {
309 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
310 thread->detached = 1;
311 }
312
313 if (pthread_create (&thread->sys_thread, &attr, _start_routine, start) == 0)
314 {
315 pthread_attr_destroy (&attr);
316 return thread;
317 }
318 else
319 pthread_attr_destroy (&attr);
320 }
321 while (0);
322
323 #ifdef THREAD_DEBUG
324 LOG_ERROR("Could not create new thread %s", name);
325 #endif
326 if (start) free (start);
327 if (thread) free (thread);
328 return NULL;
329 }
330
331 /* _mutex_create
332 **
333 ** creates a mutex
334 */
_mutex_create(mutex_t * mutex)335 static void _mutex_create(mutex_t *mutex)
336 {
337 #ifdef DEBUG_MUTEXES
338 mutex->thread_id = MUTEX_STATE_NEVERLOCKED;
339 mutex->line = -1;
340 #endif
341
342 pthread_mutex_init(&mutex->sys_mutex, NULL);
343 }
344
thread_mutex_create_c(mutex_t * mutex,int line,char * file)345 void thread_mutex_create_c(mutex_t *mutex, int line, char *file)
346 {
347 _mutex_create(mutex);
348
349 #ifdef DEBUG_MUTEXES
350 _mutex_lock(&_mutextree_mutex);
351 mutex->mutex_id = _next_mutex_id++;
352 avl_insert(_mutextree, (void *)mutex);
353 _mutex_unlock(&_mutextree_mutex);
354 #endif
355 }
356
thread_mutex_destroy(mutex_t * mutex)357 void thread_mutex_destroy (mutex_t *mutex)
358 {
359 pthread_mutex_destroy(&mutex->sys_mutex);
360
361 #ifdef DEBUG_MUTEXES
362 _mutex_lock(&_mutextree_mutex);
363 avl_delete(_mutextree, mutex, _free_mutex);
364 _mutex_unlock(&_mutextree_mutex);
365 #endif
366 }
367
thread_mutex_lock_c(mutex_t * mutex,int line,char * file)368 void thread_mutex_lock_c(mutex_t *mutex, int line, char *file)
369 {
370 #ifdef DEBUG_MUTEXES
371 thread_type *th = thread_self();
372
373 if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line);
374
375 LOG_DEBUG5("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1);
376
377 # ifdef CHECK_MUTEXES
378 /* Just a little sanity checking to make sure that we're locking
379 ** mutexes correctly
380 */
381
382 if (th) {
383 int locks = 0;
384 avl_node *node;
385 mutex_t *tmutex;
386
387 _mutex_lock(&_mutextree_mutex);
388
389 node = avl_get_first (_mutextree);
390
391 while (node) {
392 tmutex = (mutex_t *)node->key;
393
394 if (tmutex->mutex_id == mutex->mutex_id) {
395 if (tmutex->thread_id == th->thread_id) {
396 /* Deadlock, same thread can't lock the same mutex twice */
397 LOG_ERROR7("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]",
398 tmutex->thread_id, th->thread_id, mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name);
399
400 _mutex_unlock(&_mutextree_mutex);
401 return;
402 }
403 } else if (tmutex->thread_id == th->thread_id) {
404 /* Mutex locked by this thread (not this mutex) */
405 locks++;
406 }
407
408 node = avl_get_next(node);
409 }
410
411 if (locks > 0) {
412 /* Has already got a mutex locked */
413 if (_multi_mutex.thread_id != th->thread_id) {
414 /* Tries to lock two mutexes, but has not got the double mutex, norty boy! */
415 LOG_WARN("(%d != %d) Thread %d [%s] tries to lock a second mutex [%s] in file %s line %d, without locking double mutex!",
416 _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line);
417 }
418 }
419
420 _mutex_unlock(&_mutextree_mutex);
421 }
422 # endif /* CHECK_MUTEXES */
423
424 _mutex_lock(mutex);
425
426 _mutex_lock(&_mutextree_mutex);
427
428 LOG_DEBUG2("Locked %p by thread %d", mutex, th ? th->thread_id : -1);
429 mutex->line = line;
430 if (th) {
431 mutex->thread_id = th->thread_id;
432 }
433
434 _mutex_unlock(&_mutextree_mutex);
435 #else
436 _mutex_lock(mutex);
437 #endif /* DEBUG_MUTEXES */
438 }
439
thread_mutex_unlock_c(mutex_t * mutex,int line,char * file)440 void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file)
441 {
442 #ifdef DEBUG_MUTEXES
443 thread_type *th = thread_self();
444
445 if (!th) {
446 LOG_ERROR3("No record for %u in unlock [%s:%d]", thread_self(), file, line);
447 }
448
449 LOG_DEBUG5("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1);
450
451 mutex->line = line;
452
453 # ifdef CHECK_MUTEXES
454 if (th) {
455 int locks = 0;
456 avl_node *node;
457 mutex_t *tmutex;
458
459 _mutex_lock(&_mutextree_mutex);
460
461 while (node) {
462 tmutex = (mutex_t *)node->key;
463
464 if (tmutex->mutex_id == mutex->mutex_id) {
465 if (tmutex->thread_id != th->thread_id) {
466 LOG_ERROR7("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id,
467 mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name);
468 _mutex_unlock(&_mutextree_mutex);
469 return;
470 }
471 } else if (tmutex->thread_id == th->thread_id) {
472 locks++;
473 }
474
475 node = avl_get_next (node);
476 }
477
478 if ((locks > 0) && (_multi_mutex.thread_id != th->thread_id)) {
479 /* Don't have double mutex, has more than this mutex left */
480
481 LOG_WARN("(%d != %d) Thread %d [%s] tries to unlock a mutex [%s] in file %s line %d, without owning double mutex!",
482 _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line);
483 }
484
485 _mutex_unlock(&_mutextree_mutex);
486 }
487 # endif /* CHECK_MUTEXES */
488
489 _mutex_unlock(mutex);
490
491 _mutex_lock(&_mutextree_mutex);
492
493 LOG_DEBUG2("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1);
494 mutex->line = -1;
495 if (mutex->thread_id == th->thread_id) {
496 mutex->thread_id = MUTEX_STATE_NOTLOCKED;
497 }
498
499 _mutex_unlock(&_mutextree_mutex);
500 #else
501 _mutex_unlock(mutex);
502 #endif /* DEBUG_MUTEXES */
503 }
504
thread_cond_create_c(cond_t * cond,int line,char * file)505 void thread_cond_create_c(cond_t *cond, int line, char *file)
506 {
507 pthread_cond_init(&cond->sys_cond, NULL);
508 pthread_mutex_init(&cond->cond_mutex, NULL);
509 }
510
thread_cond_destroy(cond_t * cond)511 void thread_cond_destroy(cond_t *cond)
512 {
513 pthread_mutex_destroy(&cond->cond_mutex);
514 pthread_cond_destroy(&cond->sys_cond);
515 }
516
thread_cond_signal_c(cond_t * cond,int line,char * file)517 void thread_cond_signal_c(cond_t *cond, int line, char *file)
518 {
519 pthread_cond_signal(&cond->sys_cond);
520 }
521
thread_cond_broadcast_c(cond_t * cond,int line,char * file)522 void thread_cond_broadcast_c(cond_t *cond, int line, char *file)
523 {
524 pthread_cond_broadcast(&cond->sys_cond);
525 }
526
thread_cond_timedwait_c(cond_t * cond,int millis,int line,char * file)527 void thread_cond_timedwait_c(cond_t *cond, int millis, int line, char *file)
528 {
529 struct timespec time;
530
531 time.tv_sec = millis/1000;
532 time.tv_nsec = (millis - time.tv_sec*1000)*1000000;
533
534 pthread_mutex_lock(&cond->cond_mutex);
535 pthread_cond_timedwait(&cond->sys_cond, &cond->cond_mutex, &time);
536 pthread_mutex_unlock(&cond->cond_mutex);
537 }
538
thread_cond_wait_c(cond_t * cond,int line,char * file)539 void thread_cond_wait_c(cond_t *cond, int line, char *file)
540 {
541 pthread_mutex_lock(&cond->cond_mutex);
542 pthread_cond_wait(&cond->sys_cond, &cond->cond_mutex);
543 pthread_mutex_unlock(&cond->cond_mutex);
544 }
545
thread_rwlock_create_c(rwlock_t * rwlock,int line,char * file)546 void thread_rwlock_create_c(rwlock_t *rwlock, int line, char *file)
547 {
548 pthread_rwlock_init(&rwlock->sys_rwlock, NULL);
549 }
550
thread_rwlock_destroy(rwlock_t * rwlock)551 void thread_rwlock_destroy(rwlock_t *rwlock)
552 {
553 pthread_rwlock_destroy(&rwlock->sys_rwlock);
554 }
555
thread_rwlock_rlock_c(rwlock_t * rwlock,int line,char * file)556 void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file)
557 {
558 pthread_rwlock_rdlock(&rwlock->sys_rwlock);
559 }
560
thread_rwlock_wlock_c(rwlock_t * rwlock,int line,char * file)561 void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file)
562 {
563 pthread_rwlock_wrlock(&rwlock->sys_rwlock);
564 }
565
thread_rwlock_unlock_c(rwlock_t * rwlock,int line,char * file)566 void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file)
567 {
568 pthread_rwlock_unlock(&rwlock->sys_rwlock);
569 }
570
thread_exit_c(long val,int line,char * file)571 void thread_exit_c(long val, int line, char *file)
572 {
573 thread_type *th = thread_self();
574
575 #if defined(DEBUG_MUTEXES) && defined(CHECK_MUTEXES)
576 if (th) {
577 avl_node *node;
578 mutex_t *tmutex;
579 char name[40];
580
581 _mutex_lock(&_mutextree_mutex);
582
583 while (node) {
584 tmutex = (mutex_t *)node->key;
585
586 if (tmutex->thread_id == th->thread_id) {
587 LOG_WARN("Thread %d [%s] exiting in file %s line %d, without unlocking mutex [%s]",
588 th->thread_id, th->name, file, line, mutex_to_string(tmutex, name));
589 }
590
591 node = avl_get_next (node);
592 }
593
594 _mutex_unlock(&_mutextree_mutex);
595 }
596 #endif
597
598 if (th && th->detached)
599 {
600 #ifdef THREAD_DEBUG
601 LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line);
602 #endif
603
604 _mutex_lock(&_threadtree_mutex);
605 avl_delete(_threadtree, th, _free_thread);
606 _mutex_unlock(&_threadtree_mutex);
607 }
608
609 pthread_exit ((void*)val);
610 }
611
612 /* sleep for a number of microseconds */
thread_sleep(unsigned long len)613 void thread_sleep(unsigned long len)
614 {
615 #ifdef _WIN32
616 Sleep(len / 1000);
617 #else
618 # ifdef HAVE_NANOSLEEP
619 struct timespec time_sleep;
620 struct timespec time_remaining;
621 int ret;
622
623 time_sleep.tv_sec = len / 1000000;
624 time_sleep.tv_nsec = (len % 1000000) * 1000;
625
626 ret = nanosleep(&time_sleep, &time_remaining);
627 while (ret != 0 && errno == EINTR) {
628 time_sleep.tv_sec = time_remaining.tv_sec;
629 time_sleep.tv_nsec = time_remaining.tv_nsec;
630
631 ret = nanosleep(&time_sleep, &time_remaining);
632 }
633 # else
634 struct timeval tv;
635
636 tv.tv_sec = len / 1000000;
637 tv.tv_usec = (len % 1000000);
638
639 select(0, NULL, NULL, NULL, &tv);
640 # endif
641 #endif
642 }
643
_start_routine(void * arg)644 static void *_start_routine(void *arg)
645 {
646 thread_start_t *start = (thread_start_t *)arg;
647 void *(*start_routine)(void *) = start->start_routine;
648 void *real_arg = start->arg;
649 thread_type *thread = start->thread;
650
651 _block_signals();
652
653 /* insert thread into thread tree here */
654 _mutex_lock(&_threadtree_mutex);
655 thread->sys_thread = pthread_self();
656 avl_insert(_threadtree, (void *)thread);
657 _mutex_unlock(&_threadtree_mutex);
658
659 #ifdef THREAD_DEBUG
660 LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line);
661 #endif
662
663 #ifndef __ANDROID__
664 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
665 #endif
666
667 free (start);
668
669 (start_routine)(real_arg);
670
671 if (thread->detached)
672 {
673 _mutex_lock (&_threadtree_mutex);
674 avl_delete (_threadtree, thread, _free_thread);
675 _mutex_unlock (&_threadtree_mutex);
676 }
677
678 return NULL;
679 }
680
thread_self(void)681 thread_type *thread_self(void)
682 {
683 avl_node *node;
684 thread_type *th;
685 pthread_t sys_thread = pthread_self();
686
687 _mutex_lock(&_threadtree_mutex);
688
689 if (_threadtree == NULL) {
690 #ifdef THREAD_DEBUG
691 LOG_WARN("Thread tree is empty, this must be wrong!");
692 #endif
693 _mutex_unlock(&_threadtree_mutex);
694 return NULL;
695 }
696
697 node = avl_get_first(_threadtree);
698
699 while (node) {
700 th = (thread_type *)node->key;
701
702 if (th && pthread_equal(sys_thread, th->sys_thread)) {
703 _mutex_unlock(&_threadtree_mutex);
704 return th;
705 }
706
707 node = avl_get_next(node);
708 }
709 _mutex_unlock(&_threadtree_mutex);
710
711
712 #ifdef THREAD_DEBUG
713 LOG_ERROR("Nonexistant thread alive...");
714 #endif
715
716 return NULL;
717 }
718
thread_rename(const char * name)719 void thread_rename(const char *name)
720 {
721 thread_type *th;
722
723 th = thread_self();
724 if (th->name) free(th->name);
725
726 th->name = strdup(name);
727 }
728
_mutex_lock(mutex_t * mutex)729 static void _mutex_lock(mutex_t *mutex)
730 {
731 pthread_mutex_lock(&mutex->sys_mutex);
732 }
733
_mutex_unlock(mutex_t * mutex)734 static void _mutex_unlock(mutex_t *mutex)
735 {
736 pthread_mutex_unlock(&mutex->sys_mutex);
737 }
738
739
thread_library_lock(void)740 void thread_library_lock(void)
741 {
742 _mutex_lock(&_library_mutex);
743 }
744
thread_library_unlock(void)745 void thread_library_unlock(void)
746 {
747 _mutex_unlock(&_library_mutex);
748 }
749
thread_join(thread_type * thread)750 void thread_join(thread_type *thread)
751 {
752 void *ret;
753
754 (void) pthread_join(thread->sys_thread, &ret);
755 _mutex_lock(&_threadtree_mutex);
756 avl_delete(_threadtree, thread, _free_thread);
757 _mutex_unlock(&_threadtree_mutex);
758 }
759
760 /* AVL tree functions */
761
762 #ifdef DEBUG_MUTEXES
_compare_mutexes(void * compare_arg,void * a,void * b)763 static int _compare_mutexes(void *compare_arg, void *a, void *b)
764 {
765 mutex_t *m1, *m2;
766
767 m1 = (mutex_t *)a;
768 m2 = (mutex_t *)b;
769
770 if (m1->mutex_id > m2->mutex_id)
771 return 1;
772 if (m1->mutex_id < m2->mutex_id)
773 return -1;
774 return 0;
775 }
776 #endif
777
_compare_threads(void * compare_arg,void * a,void * b)778 static int _compare_threads(void *compare_arg, void *a, void *b)
779 {
780 thread_type *t1, *t2;
781
782 t1 = (thread_type *)a;
783 t2 = (thread_type *)b;
784
785 if (t1->thread_id > t2->thread_id)
786 return 1;
787 if (t1->thread_id < t2->thread_id)
788 return -1;
789 return 0;
790 }
791
792 #ifdef DEBUG_MUTEXES
_free_mutex(void * key)793 static int _free_mutex(void *key)
794 {
795 mutex_t *m;
796
797 m = (mutex_t *)key;
798
799 if (m && m->file) {
800 free(m->file);
801 m->file = NULL;
802 }
803
804 /* all mutexes are static. don't need to free them */
805
806 return 1;
807 }
808 #endif
809
_free_thread(void * key)810 static int _free_thread(void *key)
811 {
812 thread_type *t;
813
814 t = (thread_type *)key;
815
816 if (t->file)
817 free(t->file);
818 if (t->name)
819 free(t->name);
820
821 free(t);
822
823 return 1;
824 }
825
826
827 #ifdef HAVE_PTHREAD_SPIN_LOCK
thread_spin_create(spin_t * spin)828 void thread_spin_create (spin_t *spin)
829 {
830 int x = pthread_spin_init (&spin->lock, PTHREAD_PROCESS_PRIVATE);
831 if (x)
832 abort();
833 }
834
thread_spin_destroy(spin_t * spin)835 void thread_spin_destroy (spin_t *spin)
836 {
837 pthread_spin_destroy (&spin->lock);
838 }
839
thread_spin_lock(spin_t * spin)840 void thread_spin_lock (spin_t *spin)
841 {
842 int x = pthread_spin_lock (&spin->lock);
843 if (x != 0)
844 abort();
845 }
846
thread_spin_unlock(spin_t * spin)847 void thread_spin_unlock (spin_t *spin)
848 {
849 pthread_spin_unlock (&spin->lock);
850 }
851 #endif
852
853