head 1.25; access; symbols libshout-2_0:1.24 libshout-2_0b3:1.24 libshout-2_0b2:1.24 libshout_2_0b1:1.24 libogg2-zerocopy:1.17.0.2 branch-beta2-rewrite:1.5.0.2 start:1.1.1.1 xiph:1.1.1; locks; strict; comment @ * @; 1.25 date 2003.07.14.02.17.52; author brendan; state Exp; branches; next 1.24; 1.24 date 2003.03.15.02.10.18; author msmith; state Exp; branches; next 1.23; 1.23 date 2003.03.12.03.59.55; author karl; state Exp; branches; next 1.22; 1.22 date 2003.03.09.22.56.46; author karl; state Exp; branches; next 1.21; 1.21 date 2003.03.08.16.05.38; author karl; state Exp; branches; next 1.20; 1.20 date 2003.03.04.15.31.34; author msmith; state Exp; branches; next 1.19; 1.19 date 2003.01.17.09.01.04; author msmith; state Exp; branches; next 1.18; 1.18 date 2002.12.29.09.55.50; author msmith; state Exp; branches; next 1.17; 1.17 date 2002.11.22.13.00.44; author msmith; state Exp; branches; next 1.16; 1.16 date 2002.09.24.07.09.08; author msmith; state Exp; branches; next 1.15; 1.15 date 2002.08.16.14.23.17; author msmith; state Exp; branches; next 1.14; 1.14 date 2002.08.13.01.08.15; author msmith; state Exp; branches; next 1.13; 1.13 date 2002.08.10.03.22.44; author msmith; state Exp; branches; next 1.12; 1.12 date 2002.08.09.06.52.07; author msmith; state Exp; branches; next 1.11; 1.11 date 2002.08.05.14.48.03; author msmith; state Exp; branches; next 1.10; 1.10 date 2002.08.03.08.14.56; author msmith; state Exp; branches; next 1.9; 1.9 date 2002.04.30.06.50.47; author msmith; state Exp; branches; next 1.8; 1.8 date 2002.03.05.23.59.38; author jack; state Exp; branches; next 1.7; 1.7 date 2002.02.08.03.51.19; author jack; state Exp; branches; next 1.6; 1.6 date 2002.02.07.01.04.09; author jack; state Exp; branches; next 1.5; 1.5 date 2001.10.21.02.04.27; author jack; state Exp; branches; next 1.4; 1.4 date 2001.10.20.22.27.52; author jack; state Exp; branches; next 1.3; 1.3 date 2001.10.20.05.35.30; author jack; state Exp; branches; next 1.2; 1.2 date 2001.10.20.03.39.10; author jack; state Exp; branches; next 1.1; 1.1 date 2001.09.10.02.26.33; author jack; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2001.09.10.02.26.33; author jack; state Exp; branches; next ; desc @@ 1.25 log @Assign LGP to thread module @ text @/* threads.c: Thread Abstraction Functions * * Copyright (c) 1999, 2000 the icecast team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #ifndef _WIN32 #include #include #else #include #include #include #endif #include #include #include #ifdef THREAD_DEBUG #include #endif #ifdef _WIN32 #define __FUNCTION__ __FILE__ #endif #ifdef THREAD_DEBUG #define CATMODULE "thread" #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) #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) #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) #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) #endif /* 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 */ thread_type *thread; pthread_t sys_thread; } thread_start_t; static long _next_thread_id = 0; static int _initialized = 0; static avl_tree *_threadtree = NULL; #ifdef DEBUG_MUTEXES static mutex_t _threadtree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1, PTHREAD_MUTEX_INITIALIZER}; #else static mutex_t _threadtree_mutex = { PTHREAD_MUTEX_INITIALIZER }; #endif #ifdef DEBUG_MUTEXES static int _logid = -1; static long _next_mutex_id = 0; static avl_tree *_mutextree = NULL; static mutex_t _mutextree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1, PTHREAD_MUTEX_INITIALIZER}; #endif #ifdef DEBUG_MUTEXES static mutex_t _library_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1, PTHREAD_MUTEX_INITIALIZER}; #else static mutex_t _library_mutex = { PTHREAD_MUTEX_INITIALIZER }; #endif /* INTERNAL FUNCTIONS */ /* avl tree functions */ #ifdef DEBUG_MUTEXES static int _compare_mutexes(void *compare_arg, void *a, void *b); static int _free_mutex(void *key); #endif static int _compare_threads(void *compare_arg, void *a, void *b); static int _free_thread(void *key); static int _free_thread_if_detached(void *key); /* 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) { thread_type *thread; /* set up logging */ #ifdef THREAD_DEBUG log_initialize(); _logid = log_open("thread.log"); log_set_level(_logid, THREAD_DEBUG); #endif #ifdef DEBUG_MUTEXES /* create all the internal mutexes, and initialize the mutex tree */ _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); thread = (thread_type *)malloc(sizeof(thread_type)); 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); #ifdef THREAD_DEBUG thread_mutex_destroy(&_mutextree_mutex); avl_tree_free(_mutextree, _free_mutex); #endif avl_tree_free(_threadtree, _free_thread); } #ifdef THREAD_DEBUG log_close(_logid); log_shutdown(); #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); if (pthread_sigmask(SIG_BLOCK, &ss, NULL) != 0) { #ifdef THREAD_DEBUG LOG_ERROR("Pthread_sigmask() failed for blocking signals"); #endif } #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); if (pthread_sigmask(SIG_UNBLOCK, &ss, NULL) != 0) { #ifdef THREAD_DEBUG LOG_ERROR("pthread_sigmask() failed for catching signals!"); #endif } #endif } thread_type *thread_create_c(char *name, void *(*start_routine)(void *), void *arg, int detached, int line, char *file) { int created; thread_type *thread; thread_start_t *start; thread = (thread_type *)malloc(sizeof(thread_type)); 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); thread->detached = 0; start->start_routine = start_routine; start->arg = arg; start->thread = thread; start->detached = detached; created = 0; if (pthread_create(&thread->sys_thread, NULL, _start_routine, start) == 0) created = 1; #ifdef THREAD_DEBUG else LOG_ERROR("Could not create new thread"); #endif if (created == 0) { #ifdef THREAD_DEBUG LOG_ERROR("System won't let me create more threads, giving up"); #endif return NULL; } return thread; } /* _mutex_create ** ** creates a mutex */ static void _mutex_create(mutex_t *mutex) { #ifdef DEBUG_MUTEXES mutex->thread_id = MUTEX_STATE_NEVERLOCKED; mutex->line = -1; #endif 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 thread_type *th = thread_self(); if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line); LOG_DEBUG5("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); # 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 */ LOG_ERROR7("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]", 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); LOG_DEBUG2("Locked %p by thread %d", mutex, th ? th->thread_id : -1); 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 thread_type *th = thread_self(); if (!th) { LOG_ERROR3("No record for %u in unlock [%s:%d]", thread_self(), file, line); } LOG_DEBUG5("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); 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) { LOG_ERROR7("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", 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) { 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); LOG_DEBUG2("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1); 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); } 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); } 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) { thread_type *th = thread_self(); #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) { #ifdef THREAD_DEBUG LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line); #endif _mutex_lock(&_threadtree_mutex); avl_delete(_threadtree, th, _free_thread_if_detached); _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; time_sleep.tv_nsec = (len % 1000000) * 1000; 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; tv.tv_usec = (len % 1000000); 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; thread_type *thread = start->thread; int detach = start->detached; _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); #ifdef THREAD_DEBUG LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line); #endif if (detach) { pthread_detach(thread->sys_thread); thread->detached = 1; } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); /* call the real start_routine and start the thread ** this should never exit! */ (start_routine)(real_arg); #ifdef THREAD_DEBUG LOG_WARN("Thread x should never exit from here!!!"); #endif return NULL; } thread_type *thread_self(void) { avl_node *node; thread_type *th; pthread_t sys_thread = pthread_self(); _mutex_lock(&_threadtree_mutex); if (_threadtree == NULL) { #ifdef THREAD_DEBUG LOG_WARN("Thread tree is empty, this must be wrong!"); #endif _mutex_unlock(&_threadtree_mutex); return NULL; } node = avl_get_first(_threadtree); while (node) { th = (thread_type *)node->key; if (th && pthread_equal(sys_thread, th->sys_thread)) { _mutex_unlock(&_threadtree_mutex); return th; } node = avl_get_next(node); } _mutex_unlock(&_threadtree_mutex); #ifdef THREAD_DEBUG LOG_ERROR("Nonexistant thread alive..."); #endif return NULL; } void thread_rename(const char *name) { thread_type *th; 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); } void thread_join(thread_type *thread) { void *ret; int i; i = pthread_join(thread->sys_thread, &ret); _mutex_lock(&_threadtree_mutex); avl_delete(_threadtree, thread, _free_thread); _mutex_unlock(&_threadtree_mutex); } /* AVL tree functions */ #ifdef DEBUG_MUTEXES 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; } #endif static int _compare_threads(void *compare_arg, void *a, void *b) { thread_type *t1, *t2; t1 = (thread_type *)a; t2 = (thread_type *)b; if (t1->thread_id > t2->thread_id) return 1; if (t1->thread_id < t2->thread_id) return -1; return 0; } #ifdef DEBUG_MUTEXES 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; } #endif static int _free_thread(void *key) { thread_type *t; t = (thread_type *)key; if (t->file) free(t->file); if (t->name) free(t->name); free(t); return 1; } static int _free_thread_if_detached(void *key) { thread_type *t = key; if(t->detached) return _free_thread(key); return 1; } @ 1.24 log @Brendan was getting pissed off about inconsistent indentation styles. Convert all tabs to 4 spaces. All code must now use 4 space indents. @ text @d1 18 a18 19 /* 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. */ @ 1.23 log @avoid freeing a thread structure a second time. @ text @d77 12 a88 12 /* 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 */ thread_type *thread; pthread_t sys_thread; d146 1 a146 1 thread_type *thread; d148 1 a148 1 /* set up logging */ d151 3 a153 3 log_initialize(); _logid = log_open("thread.log"); log_set_level(_logid, THREAD_DEBUG); d157 1 a157 1 /* create all the internal mutexes, and initialize the mutex tree */ d159 1 a159 1 _mutextree = avl_tree_new(_compare_mutexes, NULL); d161 4 a164 4 /* we have to create this one by hand, because there's no ** mutextree_mutex to lock yet! */ _mutex_create(&_mutextree_mutex); d166 2 a167 2 _mutextree_mutex.mutex_id = _next_mutex_id++; avl_insert(_mutextree, (void *)&_mutextree_mutex); d170 2 a171 2 thread_mutex_create(&_threadtree_mutex); thread_mutex_create(&_library_mutex); d173 1 a173 1 /* initialize the thread tree and insert the main thread */ d175 1 a175 1 _threadtree = avl_tree_new(_compare_threads, NULL); d177 1 a177 1 thread = (thread_type *)malloc(sizeof(thread_type)); d179 6 a184 6 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"); d186 1 a186 1 avl_insert(_threadtree, (void *)thread); d188 1 a188 1 _catch_signals(); d190 1 a190 1 _initialized = 1; d195 3 a197 3 if (_initialized == 1) { thread_mutex_destroy(&_library_mutex); thread_mutex_destroy(&_threadtree_mutex); d199 3 a201 3 thread_mutex_destroy(&_mutextree_mutex); avl_tree_free(_mutextree, _free_mutex); d203 2 a204 2 avl_tree_free(_threadtree, _free_thread); } d207 2 a208 2 log_close(_logid); log_shutdown(); d271 8 a278 12 int created; thread_type *thread; thread_start_t *start; thread = (thread_type *)malloc(sizeof(thread_type)); 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); d280 6 a285 2 thread->name = strdup(name); thread->create_time = time(NULL); d288 4 a291 4 start->start_routine = start_routine; start->arg = arg; start->thread = thread; start->detached = detached; d293 3 a295 3 created = 0; if (pthread_create(&thread->sys_thread, NULL, _start_routine, start) == 0) created = 1; d297 2 a298 2 else LOG_ERROR("Could not create new thread"); d301 1 a301 1 if (created == 0) { d303 1 a303 1 LOG_ERROR("System won't let me create more threads, giving up"); d305 2 a306 2 return NULL; } d308 1 a308 1 return thread; d318 2 a319 2 mutex->thread_id = MUTEX_STATE_NEVERLOCKED; mutex->line = -1; d322 1 a322 1 pthread_mutex_init(&mutex->sys_mutex, NULL); d327 1 a327 1 _mutex_create(mutex); d330 4 a333 4 _mutex_lock(&_mutextree_mutex); mutex->mutex_id = _next_mutex_id++; avl_insert(_mutextree, (void *)mutex); _mutex_unlock(&_mutextree_mutex); d339 1 a339 1 pthread_mutex_destroy(&mutex->sys_mutex); d342 3 a344 3 _mutex_lock(&_mutextree_mutex); avl_delete(_mutextree, mutex, _free_mutex); _mutex_unlock(&_mutextree_mutex); d351 1 a351 1 thread_type *th = thread_self(); d353 1 a353 1 if (!th) LOG_WARN("No mt record for %u in lock [%s:%d]", thread_self(), file, line); d355 1 a355 1 LOG_DEBUG5("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); d358 44 a401 44 /* 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 */ LOG_ERROR7("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]", 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); } d403 10 a412 10 _mutex_lock(mutex); _mutex_lock(&_mutextree_mutex); LOG_DEBUG2("Locked %p by thread %d", mutex, th ? th->thread_id : -1); mutex->line = line; if (th) { mutex->thread_id = th->thread_id; } d414 1 a414 1 _mutex_unlock(&_mutextree_mutex); d416 1 a416 1 _mutex_lock(mutex); d423 1 a423 1 thread_type *th = thread_self(); d425 3 a427 3 if (!th) { LOG_ERROR3("No record for %u in unlock [%s:%d]", thread_self(), file, line); } d429 1 a429 1 LOG_DEBUG5("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); d431 1 a431 1 mutex->line = line; d434 20 a453 30 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) { LOG_ERROR7("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", 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) { 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); } d455 12 a466 2 _mutex_unlock(&_mutextree_mutex); } d469 1 a469 1 _mutex_unlock(mutex); d471 1 a471 1 _mutex_lock(&_mutextree_mutex); d473 5 a477 5 LOG_DEBUG2("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1); mutex->line = -1; if (mutex->thread_id == th->thread_id) { mutex->thread_id = MUTEX_STATE_NOTLOCKED; } d479 1 a479 1 _mutex_unlock(&_mutextree_mutex); d481 1 a481 1 _mutex_unlock(mutex); d487 2 a488 2 pthread_cond_init(&cond->sys_cond, NULL); pthread_mutex_init(&cond->cond_mutex, NULL); d493 2 a494 2 pthread_mutex_destroy(&cond->cond_mutex); pthread_cond_destroy(&cond->sys_cond); d499 1 a499 1 pthread_cond_signal(&cond->sys_cond); d504 1 a504 1 pthread_cond_broadcast(&cond->sys_cond); d521 3 a523 3 pthread_mutex_lock(&cond->cond_mutex); pthread_cond_wait(&cond->sys_cond, &cond->cond_mutex); pthread_mutex_unlock(&cond->cond_mutex); d528 1 a528 1 pthread_rwlock_init(&rwlock->sys_rwlock, NULL); d533 1 a533 1 pthread_rwlock_destroy(&rwlock->sys_rwlock); d538 1 a538 1 pthread_rwlock_rdlock(&rwlock->sys_rwlock); d543 1 a543 1 pthread_rwlock_wrlock(&rwlock->sys_rwlock); d548 1 a548 1 pthread_rwlock_unlock(&rwlock->sys_rwlock); d553 1 a553 1 thread_type *th = thread_self(); d556 14 a569 4 if (th) { avl_node *node; mutex_t *tmutex; char name[40]; d571 2 a572 4 _mutex_lock(&_mutextree_mutex); while (node) { tmutex = (mutex_t *)node->key; d574 2 a575 10 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); } d577 2 a578 2 if (th) { d580 1 a580 1 LOG_INFO4("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line); d583 6 a588 6 _mutex_lock(&_threadtree_mutex); avl_delete(_threadtree, th, _free_thread_if_detached); _mutex_unlock(&_threadtree_mutex); } pthread_exit((void *)val); d595 1 a595 1 Sleep(len / 1000); d598 14 a611 14 struct timespec time_sleep; struct timespec time_remaining; int ret; time_sleep.tv_sec = len / 1000000; time_sleep.tv_nsec = (len % 1000000) * 1000; 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); } d613 1 a613 1 struct timeval tv; d615 2 a616 2 tv.tv_sec = len / 1000000; tv.tv_usec = (len % 1000000); d618 1 a618 1 select(0, NULL, NULL, NULL, &tv); d625 4 a628 4 thread_start_t *start = (thread_start_t *)arg; void *(*start_routine)(void *) = start->start_routine; void *real_arg = start->arg; thread_type *thread = start->thread; d631 1 a631 1 _block_signals(); d633 1 a633 1 free(start); d635 5 a639 5 /* insert thread into thread tree here */ _mutex_lock(&_threadtree_mutex); thread->sys_thread = pthread_self(); avl_insert(_threadtree, (void *)thread); _mutex_unlock(&_threadtree_mutex); d642 1 a642 1 LOG_INFO4("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line); d645 2 a646 2 if (detach) { pthread_detach(thread->sys_thread); d648 2 a649 2 } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); d651 4 a654 4 /* call the real start_routine and start the thread ** this should never exit! */ (start_routine)(real_arg); d657 1 a657 1 LOG_WARN("Thread x should never exit from here!!!"); d660 1 a660 1 return NULL; d665 3 a667 3 avl_node *node; thread_type *th; pthread_t sys_thread = pthread_self(); d669 1 a669 1 _mutex_lock(&_threadtree_mutex); d671 1 a671 1 if (_threadtree == NULL) { d673 1 a673 1 LOG_WARN("Thread tree is empty, this must be wrong!"); d675 17 a691 17 _mutex_unlock(&_threadtree_mutex); return NULL; } node = avl_get_first(_threadtree); while (node) { th = (thread_type *)node->key; if (th && pthread_equal(sys_thread, th->sys_thread)) { _mutex_unlock(&_threadtree_mutex); return th; } node = avl_get_next(node); } _mutex_unlock(&_threadtree_mutex); d695 1 a695 1 LOG_ERROR("Nonexistant thread alive..."); d697 2 a698 2 return NULL; d703 1 a703 1 thread_type *th; d705 2 a706 2 th = thread_self(); if (th->name) free(th->name); d708 1 a708 1 th->name = strdup(name); d713 1 a713 1 pthread_mutex_lock(&mutex->sys_mutex); d718 1 a718 1 pthread_mutex_unlock(&mutex->sys_mutex); d724 1 a724 1 _mutex_lock(&_library_mutex); d729 1 a729 1 _mutex_unlock(&_library_mutex); d734 2 a735 2 void *ret; int i; d737 1 a737 1 i = pthread_join(thread->sys_thread, &ret); d748 1 a748 1 mutex_t *m1, *m2; d750 2 a751 2 m1 = (mutex_t *)a; m2 = (mutex_t *)b; d753 5 a757 5 if (m1->mutex_id > m2->mutex_id) return 1; if (m1->mutex_id < m2->mutex_id) return -1; return 0; d763 1 a763 1 thread_type *t1, *t2; d765 2 a766 2 t1 = (thread_type *)a; t2 = (thread_type *)b; d768 5 a772 5 if (t1->thread_id > t2->thread_id) return 1; if (t1->thread_id < t2->thread_id) return -1; return 0; d778 1 a778 1 mutex_t *m; d780 1 a780 1 m = (mutex_t *)key; d782 4 a785 4 if (m && m->file) { free(m->file); m->file = NULL; } d787 1 a787 1 /* all mutexes are static. don't need to free them */ d789 1 a789 1 return 1; d795 1 a795 1 thread_type *t; d797 1 a797 1 t = (thread_type *)key; d799 4 a802 4 if (t->file) free(t->file); if (t->name) free(t->name); d804 1 a804 1 free(t); d806 1 a806 1 return 1; @ 1.22 log @reduce include file namespace clutter for libshout and the associated smaller libs. @ text @a740 1 _free_thread(thread); @ 1.21 log @include the automake config.h file if the application defines one @ text @d45 2 a46 2 #include "thread.h" #include "avl.h" d48 1 a48 1 #include "log.h" @ 1.20 log @Make various thread structures omit the bits only used in debug mode. Some of these are pretty heavily used, so saving 10-20 bytes each can be quite significant. No functional differences. @ text @d21 4 @ 1.19 log @Fix some warnings, fix cflags. @ text @a86 1 static int _logid = -1; d90 2 d94 4 d99 3 d103 1 d107 3 d112 3 d119 1 d121 3 a124 1 static int _free_mutex(void *key); d152 1 a161 1 #ifdef DEBUG_MUTEXES d194 1 d198 1 d313 1 d316 1 a521 2 static int rwlocknum = 0; d742 1 d756 1 d772 1 d788 1 @ 1.18 log @Rename thread_t to avoid problems on OS X @ text @d91 2 a92 1 static mutex_t _threadtree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1 }; d96 4 a99 2 static mutex_t _mutextree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1 }; static mutex_t _library_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1 }; @ 1.17 log @Lots of bugfixes contributed by Karl Heyes. @ text @d83 1 a83 1 thread_t *thread; d121 1 a121 1 thread_t *thread; d152 1 a152 1 thread = (thread_t *)malloc(sizeof(thread_t)); d241 2 a242 1 thread_t *thread_create_c(char *name, void *(*start_routine)(void *), void *arg, int detached, int line, char *file) d245 1 a245 1 thread_t *thread; d248 1 a248 1 thread = (thread_t *)malloc(sizeof(thread_t)); d322 1 a322 1 thread_t *th = thread_self(); d394 1 a394 1 thread_t *th = thread_self(); d526 1 a526 1 thread_t *th = thread_self(); d601 1 a601 1 thread_t *thread = start->thread; d636 1 a636 1 thread_t *thread_self(void) d639 1 a639 1 thread_t *th; d655 1 a655 1 th = (thread_t *)node->key; d676 1 a676 1 thread_t *th; d705 1 a705 1 void thread_join(thread_t *thread) d735 1 a735 1 thread_t *t1, *t2; d737 2 a738 2 t1 = (thread_t *)a; t2 = (thread_t *)b; d765 1 a765 1 thread_t *t; d767 1 a767 1 t = (thread_t *)key; d781 1 a781 1 thread_t *t = key; @ 1.16 log @Bugfix: thread_join is often called after a thread has already exited, which it does using thread_exit(). thread_exit() was freeing the thread structure, so thread_join was using freed memory. Rearrange things so that if the thread is detached, the freeing happens in thread_join instead. @ text @d710 3 @ 1.15 log @Liberally sprinkle #ifdef THREAD_DEBUG around so libshout doesn't need to link with it. @ text @d105 1 d258 1 d556 1 a556 1 avl_delete(_threadtree, th, _free_thread); d619 1 d710 1 d775 7 @ 1.14 log @Timing fixes @ text @a40 1 #include "log.h" d43 3 d51 1 d69 1 d124 1 a125 2 #ifdef THREAD_DEBUG d180 1 a182 1 log_shutdown(); d205 2 a206 1 if (pthread_sigmask(SIG_BLOCK, &ss, NULL) != 0) d209 2 d231 2 a232 1 if (pthread_sigmask(SIG_UNBLOCK, &ss, NULL) != 0) d235 2 d266 1 d269 1 d272 1 d274 1 d549 1 d551 1 d611 1 d613 1 d625 1 d627 1 d641 1 d643 1 d663 1 d665 1 @ 1.13 log @Various cleanups @ text @d571 1 a571 1 tv.tv_usec = (len % 1000000) / 1000; @ 1.12 log @oddsock's xslt stats support, slightly cleaned up @ text @d231 1 a231 1 long thread_create_c(char *name, void *(*start_routine)(void *), void *arg, int detached, int line, char *file) d262 1 a262 1 return -1; d265 1 a265 2 // return thread->thread_id; return thread->sys_thread; d678 1 a678 1 void thread_join(long thread) d683 1 a683 1 i = pthread_join(thread, &ret); @ 1.11 log @Cleaned up version of Ciaran Anscomb's relaying patch. @ text @a117 5 /* this must be called to init pthreads-win32 */ #ifdef _WIN32 ptw32_processInitialize(); #endif d127 1 a127 1 /* create all the interal mutexes, and initialize the mutex tree */ @ 1.10 log @Lots of patches committable now that my sound card works properly again. logging API changed slightly (I got sick of gcc warnings about deprecated features). resampling (for live input, not yet for reencoding) is in there. several patches from Karl Heyes have been incorporated. @ text @d468 12 d486 2 @ 1.9 log @Don't use start after freeing it in thread startup code. @ text @d50 16 a65 16 #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) #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) #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) #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) a257 1 @ 1.8 log @win32 patches from Ed @ text @d577 1 d591 1 a591 1 if (start->detached) { @ 1.7 log @More win32 fixes. @ text @d28 2 d36 1 a38 2 #include d46 1 a46 1 #define __FUNCTION__ __FILE__ ":" __LINE__ @ 1.6 log @minor build fixes for win32 courtesy of Oddsock @ text @d117 5 @ 1.5 log @Revert the stacksize work. It's stupid. The original patch from Ben Laurie some years ago was needed because FreeBSD's default stack size was < 8k and this wasn't acceptable. Both Linux and Solaris had reasonable defaults for stacksize, or grew the stack as needed to a reasonable size. Testing today and consulting documentation shows that the default stack sizes on FreeBSD, Linux, and Solaris are all acceptable. Linux can grow to 2MB, 32bit Solaris defaults to 1MB, 64bit Solaris defaults to 2MB, and FreeBSD defaults to 64k. In my opinion FreeBSD needs to get with the program and provide a reasonable default. 64k is enough for us, but might not be for others. @ text @d31 3 d43 4 @ 1.4 log @Stack size per thread needs to be configurable. Setting it on a global bases is not enough. ices and icecast need this to be different, and if one is interested in tuning memory usage, one will want to alter this per thread. @ text @d223 1 a223 1 long thread_create_c(char *name, void *(*start_routine)(void *), void *arg, int stacksize, int detached, int line, char *file) a224 1 pthread_attr_t attr; a245 2 pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, stacksize); d248 1 a248 1 if (pthread_create(&thread->sys_thread, &attr, _start_routine, start) == 0) a251 2 pthread_attr_destroy(&attr); @ 1.3 log @Win32 fixes. Specifically a header change and not using the gcc extensions for vararg macros. It's not as pretty, but it works. @ text @a58 3 /* INTERNAL DATA */ #define STACKSIZE 8192 d223 1 a223 1 long thread_create_c(char *name, void *(*start_routine)(void *), void *arg, int detached, int line, char *file) d248 1 a248 1 pthread_attr_setstacksize(&attr, STACKSIZE); @ 1.2 log @Oddsock found this bug when working with icecast2 on freebsd. Nanoseconds were off by a few orders of magnitude. @ text @a26 1 #include d30 1 d42 16 a57 4 #define LOG_ERROR(y, z...) log_write(_logid, 1, CATMODULE "/" __FUNCTION__, y, ##z) #define LOG_WARN(y, z...) log_write(_logid, 2, CATMODULE "/" __FUNCTION__, y, ##z) #define LOG_INFO(y, z...) log_write(_logid, 3, CATMODULE "/" __FUNCTION__, y, ##z) #define LOG_DEBUG(y, z...) log_write(_logid, 4, CATMODULE "/" __FUNCTION__, y, ##z) d312 1 a312 1 LOG_DEBUG("Locking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); d334 1 a334 1 LOG_ERROR("DEADLOCK AVOIDED (%d == %d) on mutex [%s] in file %s line %d by thread %d [%s]", d365 1 a365 1 LOG_DEBUG("Locked %p by thread %d", mutex, th ? th->thread_id : -1); d383 1 a383 1 LOG_ERROR("No record for %u in unlock [%s:%d]", thread_self(), file, line); d386 1 a386 1 LOG_DEBUG("Unlocking %p (%s) on line %d in file %s by thread %d", mutex, mutex->name, line, file, th ? th->thread_id : -1); d403 1 a403 1 LOG_ERROR("ILLEGAL UNLOCK (%d != %d) on mutex [%s] in file %s line %d by thread %d [%s]", tmutex->thread_id, th->thread_id, d430 1 a430 1 LOG_DEBUG("Unlocked %p by thread %d", mutex, th ? th->thread_id : -1); d524 1 a524 1 LOG_INFO("Removing thread %d [%s] started at [%s:%d], reason: 'Thread Exited'", th->thread_id, th->name, th->file, th->line); d583 1 a583 1 LOG_INFO("Added thread %d [%s] started at [%s:%d]", thread->thread_id, thread->name, thread->file, thread->line); @ 1.1 log @Initial revision @ text @d534 1 a534 1 time_sleep.tv_nsec = len % 1000000; @ 1.1.1.1 log @move to cvs @ text @@