blob: 83c8c5fe5d6b0839a230100222a9d96cdd5d8247 [file] [log] [blame]
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 <team@@icecast.org>
*
* 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 <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <pthread.h>
#ifndef _WIN32
#include <unistd.h>
#include <sys/time.h>
#else
#include <windows.h>
#include <winbase.h>
#include <implement.h>
#endif
#include <signal.h>
#include <thread/thread.h>
#include <avl/avl.h>
#ifdef THREAD_DEBUG
#include <log/log.h>
#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 <pthread.h>
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 <sys/time.h>
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
@@