thread.c 19.1 KB
Newer Older
Jack Moffitt's avatar
Jack Moffitt committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* threads.c
** - Thread Abstraction Functions
**
** Copyright (c) 1999, 2000 the icecast team
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any latfer version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

21
22
23
24
#ifdef HAVE_CONFIG_H
 #include <config.h>
#endif

Jack Moffitt's avatar
Jack Moffitt committed
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>

Jack Moffitt's avatar
Jack Moffitt committed
32
33
#include <pthread.h>

Jack Moffitt's avatar
Jack Moffitt committed
34
35
#ifndef _WIN32
#include <unistd.h>
36
#include <sys/time.h>
37
38
39
#else
#include <windows.h>
#include <winbase.h>
Jack Moffitt's avatar
Jack Moffitt committed
40
#include <implement.h>
Jack Moffitt's avatar
Jack Moffitt committed
41
42
43
44
#endif

#include <signal.h>

45
46
#include <thread/thread.h>
#include <avl/avl.h>
47
#ifdef THREAD_DEBUG
48
#include <log/log.h>
49
#endif
Jack Moffitt's avatar
Jack Moffitt committed
50

51
#ifdef _WIN32
Jack Moffitt's avatar
Jack Moffitt committed
52
#define __FUNCTION__ __FILE__
53
54
#endif

55
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
56
#define CATMODULE "thread"
57
58
59
#define LOG_ERROR(y) log_write(_logid, 1, CATMODULE "/", __FUNCTION__, y)
#define LOG_ERROR3(y, z1, z2, z3) log_write(_logid, 1, CATMODULE "/", __FUNCTION__, y, z1, z2, z3)
#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)
60

61
62
63
64
#define LOG_WARN(y) log_write(_logid, 2, CATMODULE "/", __FUNCTION__, y)
#define LOG_WARN3(y, z1, z2, z3) log_write(_logid, 2, CATMODULE "/", __FUNCTION__, y, z1, z2, z3)
#define LOG_WARN5(y, z1, z2, z3, z4, z5) log_write(_logid, 2, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5)
#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)
65

66
67
68
#define LOG_INFO(y) log_write(_logid, 3, CATMODULE "/", __FUNCTION__, y)
#define LOG_INFO4(y, z1, z2, z3, z4) log_write(_logid, 3, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4)
#define LOG_INFO5(y, z1, z2, z3, z4, z5) log_write(_logid, 3, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5)
69

70
71
72
#define LOG_DEBUG(y) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y)
#define LOG_DEBUG2(y, z1, z2) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1, z2)
#define LOG_DEBUG5(y, z1, z2, z3, z4, z5) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4, z5)
73
#endif
Jack Moffitt's avatar
Jack Moffitt committed
74
75
76
77
78
79
80
81
82
83
84
85
86

/* thread starting structure */
typedef struct thread_start_tag {
	/* the real start routine and arg */
	void *(*start_routine)(void *);
	void *arg;

	/* whether to create the threaded in detached state */
	int detached;

	/* the other stuff we need to make sure this thread is inserted into
	** the thread tree
	*/
87
	thread_type *thread;
Jack Moffitt's avatar
Jack Moffitt committed
88
89
90
91
92
93
	pthread_t sys_thread;
} thread_start_t;

static long _next_thread_id = 0;
static int _initialized = 0;
static avl_tree *_threadtree = NULL;
94
95

#ifdef DEBUG_MUTEXES
Michael Smith's avatar
Michael Smith committed
96
97
static mutex_t _threadtree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1, 
    PTHREAD_MUTEX_INITIALIZER};
98
99
100
101
#else
static mutex_t _threadtree_mutex = { PTHREAD_MUTEX_INITIALIZER };
#endif

Jack Moffitt's avatar
Jack Moffitt committed
102

103
104
105

#ifdef DEBUG_MUTEXES
static int _logid = -1;
Jack Moffitt's avatar
Jack Moffitt committed
106
static long _next_mutex_id = 0;
107

Jack Moffitt's avatar
Jack Moffitt committed
108
static avl_tree *_mutextree = NULL;
Michael Smith's avatar
Michael Smith committed
109
110
static mutex_t _mutextree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1,
    PTHREAD_MUTEX_INITIALIZER};
111
112
113
#endif

#ifdef DEBUG_MUTEXES
Michael Smith's avatar
Michael Smith committed
114
115
static mutex_t _library_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1,
    PTHREAD_MUTEX_INITIALIZER};
116
117
118
#else
static mutex_t _library_mutex = { PTHREAD_MUTEX_INITIALIZER };
#endif
Jack Moffitt's avatar
Jack Moffitt committed
119
120
121
122

/* INTERNAL FUNCTIONS */

/* avl tree functions */
123
#ifdef DEBUG_MUTEXES
Jack Moffitt's avatar
Jack Moffitt committed
124
125
static int _compare_mutexes(void *compare_arg, void *a, void *b);
static int _free_mutex(void *key);
126
127
128
#endif

static int _compare_threads(void *compare_arg, void *a, void *b);
Jack Moffitt's avatar
Jack Moffitt committed
129
static int _free_thread(void *key);
130
static int _free_thread_if_detached(void *key);
Jack Moffitt's avatar
Jack Moffitt committed
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

/* mutex fuctions */
static void _mutex_create(mutex_t *mutex);
static void _mutex_lock(mutex_t *mutex);
static void _mutex_unlock(mutex_t *mutex);

/* misc thread stuff */
static void *_start_routine(void *arg);
static void _catch_signals(void);
static void _block_signals(void);

/* LIBRARY INITIALIZATION */

void thread_initialize(void)
{
146
	thread_type *thread;
Jack Moffitt's avatar
Jack Moffitt committed
147
148
149
150

	/* set up logging */

#ifdef THREAD_DEBUG
151
	log_initialize();
Jack Moffitt's avatar
Jack Moffitt committed
152
153
154
155
	_logid = log_open("thread.log");
	log_set_level(_logid, THREAD_DEBUG);
#endif

156
#ifdef DEBUG_MUTEXES
157
	/* create all the internal mutexes, and initialize the mutex tree */
Jack Moffitt's avatar
Jack Moffitt committed
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

	_mutextree = avl_tree_new(_compare_mutexes, NULL);

	/* we have to create this one by hand, because there's no
	** mutextree_mutex to lock yet! 
	*/
	_mutex_create(&_mutextree_mutex);

	_mutextree_mutex.mutex_id = _next_mutex_id++;
	avl_insert(_mutextree, (void *)&_mutextree_mutex);
#endif

	thread_mutex_create(&_threadtree_mutex);
	thread_mutex_create(&_library_mutex);	

	/* initialize the thread tree and insert the main thread */

	_threadtree = avl_tree_new(_compare_threads, NULL);

177
	thread = (thread_type *)malloc(sizeof(thread_type));
Jack Moffitt's avatar
Jack Moffitt committed
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

	thread->thread_id = _next_thread_id++;
	thread->line = 0;
	thread->file = strdup("main.c");
	thread->sys_thread = pthread_self();
	thread->create_time = time(NULL);
	thread->name = strdup("Main Thread");

	avl_insert(_threadtree, (void *)thread);

	_catch_signals();

	_initialized = 1;
}

void thread_shutdown(void)
{
	if (_initialized == 1) {
		thread_mutex_destroy(&_library_mutex);
		thread_mutex_destroy(&_threadtree_mutex);
198
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
199
200
201
		thread_mutex_destroy(&_mutextree_mutex);
		
		avl_tree_free(_mutextree, _free_mutex);
202
#endif
Jack Moffitt's avatar
Jack Moffitt committed
203
204
205
206
207
		avl_tree_free(_threadtree, _free_thread);
	}

#ifdef THREAD_DEBUG
	log_close(_logid);
208
	log_shutdown();
Jack Moffitt's avatar
Jack Moffitt committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#endif

}

/*
 * Signals should be handled by the main thread, nowhere else.
 * I'm using POSIX signal interface here, until someone tells me
 * that I should use signal/sigset instead
 *
 * This function only valid for non-Win32
 */
static void _block_signals(void)
{
#ifndef _WIN32
        sigset_t ss;

        sigfillset(&ss);

        /* These ones we want */
        sigdelset(&ss, SIGKILL);
        sigdelset(&ss, SIGSTOP);
        sigdelset(&ss, SIGTERM);
        sigdelset(&ss, SIGSEGV);
        sigdelset(&ss, SIGBUS);
233
234
        if (pthread_sigmask(SIG_BLOCK, &ss, NULL) != 0) {
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
235
                LOG_ERROR("Pthread_sigmask() failed for blocking signals");
236
237
#endif
        }
Jack Moffitt's avatar
Jack Moffitt committed
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#endif
}

/*
 * Let the calling thread catch all the relevant signals
 *
 * This function only valid for non-Win32
 */
static void _catch_signals(void)
{
#ifndef _WIN32
        sigset_t ss;

        sigemptyset(&ss);

        /* These ones should only be accepted by the signal handling thread (main thread) */
        sigaddset(&ss, SIGHUP);
        sigaddset(&ss, SIGCHLD);
        sigaddset(&ss, SIGINT);
        sigaddset(&ss, SIGPIPE);

259
260
        if (pthread_sigmask(SIG_UNBLOCK, &ss, NULL) != 0) {
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
261
                LOG_ERROR("pthread_sigmask() failed for catching signals!");
262
263
#endif
        }
Jack Moffitt's avatar
Jack Moffitt committed
264
265
266
267
#endif
}


268
269
thread_type *thread_create_c(char *name, void *(*start_routine)(void *), 
        void *arg, int detached, int line, char *file)
Jack Moffitt's avatar
Jack Moffitt committed
270
271
{
	int created;
272
	thread_type *thread;
Jack Moffitt's avatar
Jack Moffitt committed
273
274
	thread_start_t *start;

275
	thread = (thread_type *)malloc(sizeof(thread_type));	
Jack Moffitt's avatar
Jack Moffitt committed
276
277
278
279
280
281
282
283
284
285
	start = (thread_start_t *)malloc(sizeof(thread_start_t));
	thread->line = line;
	thread->file = strdup(file);

	_mutex_lock(&_threadtree_mutex);	
	thread->thread_id = _next_thread_id++;
	_mutex_unlock(&_threadtree_mutex);

	thread->name = strdup(name);
	thread->create_time = time(NULL);
286
    thread->detached = 0;
Jack Moffitt's avatar
Jack Moffitt committed
287
288
289
290
291
292
293

	start->start_routine = start_routine;
	start->arg = arg;
	start->thread = thread;
	start->detached = detached;

	created = 0;
294
	if (pthread_create(&thread->sys_thread, NULL, _start_routine, start) == 0)
Jack Moffitt's avatar
Jack Moffitt committed
295
		created = 1;
296
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
297
298
	else
		LOG_ERROR("Could not create new thread");
299
#endif
Jack Moffitt's avatar
Jack Moffitt committed
300
301

	if (created == 0) {
302
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
303
		LOG_ERROR("System won't let me create more threads, giving up");
304
#endif
Michael Smith's avatar
Michael Smith committed
305
		return NULL;
Jack Moffitt's avatar
Jack Moffitt committed
306
307
	}

Michael Smith's avatar
Michael Smith committed
308
	return thread;
Jack Moffitt's avatar
Jack Moffitt committed
309
310
311
312
313
314
315
316
}

/* _mutex_create
** 
** creates a mutex
*/
static void _mutex_create(mutex_t *mutex)
{
317
#ifdef DEBUG_MUTEXES
Jack Moffitt's avatar
Jack Moffitt committed
318
319
	mutex->thread_id = MUTEX_STATE_NEVERLOCKED;
	mutex->line = -1;
320
#endif
Jack Moffitt's avatar
Jack Moffitt committed
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

	pthread_mutex_init(&mutex->sys_mutex, NULL);
}

void thread_mutex_create_c(mutex_t *mutex, int line, char *file)
{
	_mutex_create(mutex);

#ifdef DEBUG_MUTEXES
	_mutex_lock(&_mutextree_mutex);
	mutex->mutex_id = _next_mutex_id++;
	avl_insert(_mutextree, (void *)mutex);
	_mutex_unlock(&_mutextree_mutex);
#endif
}

void thread_mutex_destroy (mutex_t *mutex)
{
	pthread_mutex_destroy(&mutex->sys_mutex);

#ifdef DEBUG_MUTEXES
	_mutex_lock(&_mutextree_mutex);
	avl_delete(_mutextree, mutex, _free_mutex);
	_mutex_unlock(&_mutextree_mutex);
#endif
}

void thread_mutex_lock_c(mutex_t *mutex, int line, char *file)
{
#ifdef DEBUG_MUTEXES
351
	thread_type *th = thread_self();
Jack Moffitt's avatar
Jack Moffitt committed
352
353
354

	if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line);

355
	LOG_DEBUG5("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1);
Jack Moffitt's avatar
Jack Moffitt committed
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

# ifdef CHECK_MUTEXES
	/* Just a little sanity checking to make sure that we're locking
	** mutexes correctly
	*/

	if (th) {
		int locks = 0;
		avl_node *node;
		mutex_t *tmutex;

		_mutex_lock(&_mutextree_mutex);

		node = avl_get_first (_mutextree);
		
		while (node) {
			tmutex = (mutex_t *)node->key;

			if (tmutex->mutex_id == mutex->mutex_id) {
				if (tmutex->thread_id == th->thread_id) { 
					/* Deadlock, same thread can't lock the same mutex twice */
377
					LOG_ERROR7("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]", 
Jack Moffitt's avatar
Jack Moffitt committed
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
					     tmutex->thread_id, th->thread_id, mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name);

					_mutex_unlock(&_mutextree_mutex);
					return;
				}
			} else if (tmutex->thread_id == th->thread_id) { 
				/* Mutex locked by this thread (not this mutex) */
				locks++;
			}

			node = avl_get_next(node);
		}

		if (locks > 0) { 
			/* Has already got a mutex locked */
			if (_multi_mutex.thread_id != th->thread_id) {
				/* Tries to lock two mutexes, but has not got the double mutex, norty boy! */
				LOG_WARN("(%d != %d) Thread %d [%s] tries to lock a second mutex [%s] in file %s line %d, without locking double mutex!",
				     _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line);
			}
		}
		
		_mutex_unlock(&_mutextree_mutex);
	}
# endif /* CHECK_MUTEXES */
	
	_mutex_lock(mutex);
	
	_mutex_lock(&_mutextree_mutex);

408
	LOG_DEBUG2("Locked %p by thread %d", mutex, th ? th->thread_id : -1);
Jack Moffitt's avatar
Jack Moffitt committed
409
410
411
412
413
414
415
416
417
418
419
420
421
422
	mutex->line = line;
	if (th) {
		mutex->thread_id = th->thread_id;
	}

	_mutex_unlock(&_mutextree_mutex);
#else
	_mutex_lock(mutex);
#endif /* DEBUG_MUTEXES */
}

void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file)
{
#ifdef DEBUG_MUTEXES
423
	thread_type *th = thread_self();
Jack Moffitt's avatar
Jack Moffitt committed
424
425

	if (!th) {
426
		LOG_ERROR3("No record for %u in unlock [%s:%d]", thread_self(), file, line);
Jack Moffitt's avatar
Jack Moffitt committed
427
428
	}

429
	LOG_DEBUG5("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1);
Jack Moffitt's avatar
Jack Moffitt committed
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445

	mutex->line = line;

# ifdef CHECK_MUTEXES
	if (th) {
		int locks = 0;
		avl_node *node;
		mutex_t *tmutex;

		_mutex_lock(&_mutextree_mutex);

		while (node) {
			tmutex = (mutex_t *)node->key;

			if (tmutex->mutex_id == mutex->mutex_id) {
				if (tmutex->thread_id != th->thread_id) {
446
					LOG_ERROR7("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id, 
Jack Moffitt's avatar
Jack Moffitt committed
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
					     mutex->name ? mutex->name : "undefined", file, line, th->thread_id, th->name);
					_mutex_unlock(&_mutextree_mutex);
					return;
				}
			} else if (tmutex->thread_id == th->thread_id) {
				locks++;
			}

			node = avl_get_next (node);
		}

		if ((locks > 0) && (_multi_mutex.thread_id != th->thread_id)) {
			/* Don't have double mutex, has more than this mutex left */
		
			LOG_WARN("(%d != %d) Thread %d [%s] tries to unlock a mutex [%s] in file %s line %d, without owning double mutex!",
			     _multi_mutex.thread_id, th->thread_id, th->thread_id, th->name, mutex->name ? mutex->name : "undefined", file, line);
		}

		_mutex_unlock(&_mutextree_mutex);
	}
# endif  /* CHECK_MUTEXES */

	_mutex_unlock(mutex);

	_mutex_lock(&_mutextree_mutex);

473
	LOG_DEBUG2("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1);
Jack Moffitt's avatar
Jack Moffitt committed
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
	mutex->line = -1;
	if (mutex->thread_id == th->thread_id) {
		mutex->thread_id = MUTEX_STATE_NOTLOCKED;
	}

	_mutex_unlock(&_mutextree_mutex);
#else
	_mutex_unlock(mutex);
#endif /* DEBUG_MUTEXES */
}

void thread_cond_create_c(cond_t *cond, int line, char *file)
{
	pthread_cond_init(&cond->sys_cond, NULL);
	pthread_mutex_init(&cond->cond_mutex, NULL);
}

void thread_cond_destroy(cond_t *cond)
{
	pthread_mutex_destroy(&cond->cond_mutex);
	pthread_cond_destroy(&cond->sys_cond);
}

void thread_cond_signal_c(cond_t *cond, int line, char *file)
{
	pthread_cond_signal(&cond->sys_cond);
}

void thread_cond_broadcast_c(cond_t *cond, int line, char *file)
{
	pthread_cond_broadcast(&cond->sys_cond);
}

507
508
509
510
511
512
513
514
515
516
517
518
void thread_cond_timedwait_c(cond_t *cond, int millis, int line, char *file)
{
    struct timespec time;

    time.tv_sec = millis/1000;
    time.tv_nsec = (millis - time.tv_sec*1000)*1000000;

    pthread_mutex_lock(&cond->cond_mutex);
    pthread_cond_timedwait(&cond->sys_cond, &cond->cond_mutex, &time);
    pthread_mutex_unlock(&cond->cond_mutex);
}

Jack Moffitt's avatar
Jack Moffitt committed
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
void thread_cond_wait_c(cond_t *cond, int line, char *file)
{
	pthread_mutex_lock(&cond->cond_mutex);
	pthread_cond_wait(&cond->sys_cond, &cond->cond_mutex);
	pthread_mutex_unlock(&cond->cond_mutex);
}

void thread_rwlock_create_c(rwlock_t *rwlock, int line, char *file)
{
	pthread_rwlock_init(&rwlock->sys_rwlock, NULL);
}

void thread_rwlock_destroy(rwlock_t *rwlock)
{
	pthread_rwlock_destroy(&rwlock->sys_rwlock);
}

void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file)
{
	pthread_rwlock_rdlock(&rwlock->sys_rwlock);
}

void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file)
{
	pthread_rwlock_wrlock(&rwlock->sys_rwlock);
}

void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file)
{
	pthread_rwlock_unlock(&rwlock->sys_rwlock);
}

void thread_exit_c(int val, int line, char *file)
{
553
	thread_type *th = thread_self();
Jack Moffitt's avatar
Jack Moffitt committed
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

#if defined(DEBUG_MUTEXES) && defined(CHECK_MUTEXES)
	if (th) {
		avl_node *node;
		mutex_t *tmutex;
		char name[40];

		_mutex_lock(&_mutextree_mutex);

		while (node) {
			tmutex = (mutex_t *)node->key;

			if (tmutex->thread_id == th->thread_id) {
				LOG_WARN("Thread %d [%s] exiting in file %s line %d, without unlocking mutex [%s]", 
				     th->thread_id, th->name, file, line, mutex_to_string(tmutex, name));
			}

			node = avl_get_next (node);
		}

		_mutex_unlock(&_mutextree_mutex);
	}
#endif
	
	if (th)	{
579
#ifdef THREAD_DEBUG
580
		LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line);
581
#endif
Jack Moffitt's avatar
Jack Moffitt committed
582
583

		_mutex_lock(&_threadtree_mutex);
584
    	avl_delete(_threadtree, th, _free_thread_if_detached);
Jack Moffitt's avatar
Jack Moffitt committed
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
		_mutex_unlock(&_threadtree_mutex);
	}
	
	pthread_exit((void *)val);
}

/* sleep for a number of microseconds */
void thread_sleep(unsigned long len)
{
#ifdef _WIN32
	Sleep(len / 1000);
#else
# ifdef HAVE_NANOSLEEP
	struct timespec time_sleep;
	struct timespec time_remaining;
	int ret;

	time_sleep.tv_sec = len / 1000000;
603
	time_sleep.tv_nsec = (len % 1000000) * 1000;
Jack Moffitt's avatar
Jack Moffitt committed
604
605
606
607
608
609
610
611
612
613
614
615

	ret = nanosleep(&time_sleep, &time_remaining);
	while (ret != 0 && errno == EINTR) {
		time_sleep.tv_sec = time_remaining.tv_sec;
		time_sleep.tv_nsec = time_remaining.tv_nsec;
		
		ret = nanosleep(&time_sleep, &time_remaining);
	}
# else
	struct timeval tv;

	tv.tv_sec = len / 1000000;
Michael Smith's avatar
Michael Smith committed
616
	tv.tv_usec = (len % 1000000);
Jack Moffitt's avatar
Jack Moffitt committed
617
618
619
620
621
622
623
624
625
626
627

	select(0, NULL, NULL, NULL, &tv);
# endif
#endif
}

static void *_start_routine(void *arg)
{
	thread_start_t *start = (thread_start_t *)arg;
	void *(*start_routine)(void *) = start->start_routine;
	void *real_arg = start->arg;
628
	thread_type *thread = start->thread;
629
    int detach = start->detached;
Jack Moffitt's avatar
Jack Moffitt committed
630
631
632
633
634
635
636
637
638
639
640

	_block_signals();

	free(start);

	/* insert thread into thread tree here */
	_mutex_lock(&_threadtree_mutex);
	thread->sys_thread = pthread_self();
	avl_insert(_threadtree, (void *)thread);
	_mutex_unlock(&_threadtree_mutex);

641
#ifdef THREAD_DEBUG
642
	LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line);
643
#endif
Jack Moffitt's avatar
Jack Moffitt committed
644

645
	if (detach) {
Jack Moffitt's avatar
Jack Moffitt committed
646
		pthread_detach(thread->sys_thread);
647
        thread->detached = 1;
Jack Moffitt's avatar
Jack Moffitt committed
648
649
650
651
652
653
654
655
	}
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

	/* call the real start_routine and start the thread
	** this should never exit!
	*/
	(start_routine)(real_arg);

656
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
657
	LOG_WARN("Thread x should never exit from here!!!");
658
#endif
Jack Moffitt's avatar
Jack Moffitt committed
659
660
661
662

	return NULL;
}

663
thread_type *thread_self(void)
Jack Moffitt's avatar
Jack Moffitt committed
664
665
{
	avl_node *node;
666
	thread_type *th;
Jack Moffitt's avatar
Jack Moffitt committed
667
668
669
670
671
	pthread_t sys_thread = pthread_self();

	_mutex_lock(&_threadtree_mutex);

	if (_threadtree == NULL) {
672
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
673
		LOG_WARN("Thread tree is empty, this must be wrong!");
674
#endif
Jack Moffitt's avatar
Jack Moffitt committed
675
676
677
678
679
680
681
		_mutex_unlock(&_threadtree_mutex);
		return NULL;
	}
	
	node = avl_get_first(_threadtree);
	
	while (node) {
682
		th = (thread_type *)node->key;
Jack Moffitt's avatar
Jack Moffitt committed
683
684
685
686
687
688
689
690
691
692
693

		if (th && pthread_equal(sys_thread, th->sys_thread)) {
			_mutex_unlock(&_threadtree_mutex);
			return th;
		}
		
		node = avl_get_next(node);
	}
	_mutex_unlock(&_threadtree_mutex);


694
#ifdef THREAD_DEBUG
Jack Moffitt's avatar
Jack Moffitt committed
695
	LOG_ERROR("Nonexistant thread alive...");
696
#endif
Jack Moffitt's avatar
Jack Moffitt committed
697
698
699
700
701
702
	
	return NULL;
}

void thread_rename(const char *name)
{
703
	thread_type *th;
Jack Moffitt's avatar
Jack Moffitt committed
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731

	th = thread_self();
	if (th->name) free(th->name);

	th->name = strdup(name);
}

static void _mutex_lock(mutex_t *mutex) 
{
	pthread_mutex_lock(&mutex->sys_mutex);
}

static void _mutex_unlock(mutex_t *mutex)
{
	pthread_mutex_unlock(&mutex->sys_mutex);
}


void thread_library_lock(void)
{
	_mutex_lock(&_library_mutex);
}

void thread_library_unlock(void)
{
	_mutex_unlock(&_library_mutex);
}

732
void thread_join(thread_type *thread)
Jack Moffitt's avatar
Jack Moffitt committed
733
734
735
736
{
	void *ret;
	int i;

Michael Smith's avatar
Michael Smith committed
737
	i = pthread_join(thread->sys_thread, &ret);
738
739
740
    _mutex_lock(&_threadtree_mutex);
    avl_delete(_threadtree, thread, _free_thread);
    _mutex_unlock(&_threadtree_mutex);
Jack Moffitt's avatar
Jack Moffitt committed
741
742
743
744
}

/* AVL tree functions */

745
#ifdef DEBUG_MUTEXES
Jack Moffitt's avatar
Jack Moffitt committed
746
747
748
749
750
751
752
753
754
755
756
757
758
static int _compare_mutexes(void *compare_arg, void *a, void *b)
{
	mutex_t *m1, *m2;

	m1 = (mutex_t *)a;
	m2 = (mutex_t *)b;

	if (m1->mutex_id > m2->mutex_id)
		return 1;
	if (m1->mutex_id < m2->mutex_id)
		return -1;
	return 0;
}
759
#endif
Jack Moffitt's avatar
Jack Moffitt committed
760
761
762

static int _compare_threads(void *compare_arg, void *a, void *b)
{
763
	thread_type *t1, *t2;
Jack Moffitt's avatar
Jack Moffitt committed
764

765
766
	t1 = (thread_type *)a;
	t2 = (thread_type *)b;
Jack Moffitt's avatar
Jack Moffitt committed
767
768
769
770
771
772
773
774

	if (t1->thread_id > t2->thread_id)
		return 1;
	if (t1->thread_id < t2->thread_id)
		return -1;
	return 0;
}

775
#ifdef DEBUG_MUTEXES
Jack Moffitt's avatar
Jack Moffitt committed
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
static int _free_mutex(void *key)
{
	mutex_t *m;

	m = (mutex_t *)key;

	if (m && m->file) {
		free(m->file);
		m->file = NULL;
	}

	/* all mutexes are static.  don't need to free them */

	return 1;
}
791
#endif
Jack Moffitt's avatar
Jack Moffitt committed
792
793
794

static int _free_thread(void *key)
{
795
	thread_type *t;
Jack Moffitt's avatar
Jack Moffitt committed
796

797
	t = (thread_type *)key;
Jack Moffitt's avatar
Jack Moffitt committed
798
799
800
801
802
803
804
805
806
807
808

	if (t->file)
		free(t->file);
	if (t->name)
		free(t->name);

	free(t);

	return 1;
}

809
810
static int _free_thread_if_detached(void *key)
{
811
    thread_type *t = key;
812
813
814
815
    if(t->detached)
        return _free_thread(key);
    return 1;
}
Jack Moffitt's avatar
Jack Moffitt committed
816
817
818
819
820
821
822
823
824
825
826