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