From 8484f7456cfd21a5721c73615d12b3b3bb0f8f81 Mon Sep 17 00:00:00 2001 From: Karl Heyes Date: Fri, 16 Sep 2005 22:04:44 +0000 Subject: [PATCH] checkin compile conditional work, reduce stack allocations to keep in sync with trunk svn path=/icecast/branches/kh/thread/; revision=10022 --- src/thread/thread.c | 45 ++++++---- src/thread/thread.h | 194 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+), 16 deletions(-) create mode 100644 src/thread/thread.h diff --git a/src/thread/thread.c b/src/thread/thread.c index d2a7368b..c1776bce 100644 --- a/src/thread/thread.c +++ b/src/thread/thread.c @@ -28,15 +28,12 @@ #include #include -#include - #ifndef _WIN32 #include #include #else #include #include -#include #endif #include @@ -68,6 +65,7 @@ #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_DEBUG1(y, z1) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1) #define LOG_DEBUG2(y, z1, z2) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1, z2) #define LOG_DEBUG3(y, z1, z2, z3) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1, z2, z3) #define LOG_DEBUG4(y, z1, z2, z3, z4) log_write(_logid, 4, CATMODULE "/", __FUNCTION__, y, z1, z2, z3, z4) @@ -112,12 +110,9 @@ static int _logid = -1; static long _next_mutex_id = 0; static avl_tree *_mutextree = NULL; -static mutex_t _threadtree_mutex = { -1, "unset", MUTEX_STATE_UNINIT, - (unsigned long long)0, NULL, -1, PTHREAD_MUTEX_INITIALIZER}; -static mutex_t _mutextree_mutex = { -1, "unset", MUTEX_STATE_UNINIT, - (unsigned long long)0, NULL, -1, PTHREAD_MUTEX_INITIALIZER}; -static mutex_t _library_mutex = { -1, NULL, MUTEX_STATE_UNINIT, - (unsigned long long)0, NULL, -1, PTHREAD_MUTEX_INITIALIZER}; +static mutex_t _threadtree_mutex; +static mutex_t _mutextree_mutex; +static mutex_t _library_mutex; static int _compare_mutexes(void *compare_arg, void *a, void *b); static int _free_mutex(void *key); @@ -301,6 +296,7 @@ thread_type *thread_create_c(char *name, void *(*start_routine)(void *), start->arg = arg; start->thread = thread; + pthread_attr_setstacksize (&attr, 512*1024); pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED); if (detached) { @@ -363,10 +359,10 @@ void thread_mutex_destroy (mutex_t *mutex) pthread_mutex_destroy(&mutex->sys_mutex); #ifdef THREAD_DEBUG - free (mutex->file); _mutex_lock(&_mutextree_mutex); avl_delete(_mutextree, mutex, _free_mutex); _mutex_unlock(&_mutextree_mutex); + free (mutex->name); #endif } @@ -435,29 +431,46 @@ void thread_cond_wait_c(cond_t *cond, int line, char *file) pthread_mutex_unlock(&cond->cond_mutex); } -void thread_rwlock_create_c(rwlock_t *rwlock, int line, char *file) +void thread_rwlock_create_c(const char *name, rwlock_t *rwlock, int line, const char *file) { pthread_rwlock_init(&rwlock->sys_rwlock, NULL); +#ifdef THREAD_DEBUG + rwlock->name = strdup (name); + LOG_DEBUG3 ("rwlock %s created (%s:%d)", rwlock->name, file, line); +#endif } void thread_rwlock_destroy(rwlock_t *rwlock) { pthread_rwlock_destroy(&rwlock->sys_rwlock); +#ifdef THREAD_DEBUG + LOG_DEBUG1 ("rwlock %s destroyed", rwlock->name); + free (rwlock->name); +#endif } -void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, char *file) +void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, const char *file) { +#ifdef THREAD_DEBUG + LOG_DEBUG3("rLock on %s requested at %s:%d", rwlock->name, file, line); +#endif pthread_rwlock_rdlock(&rwlock->sys_rwlock); } -void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, char *file) +void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, const char *file) { +#ifdef THREAD_DEBUG + LOG_DEBUG3("wLock on %s requested at %s:%d", rwlock->name, file, line); +#endif pthread_rwlock_wrlock(&rwlock->sys_rwlock); } -void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, char *file) +void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, const char *file) { pthread_rwlock_unlock(&rwlock->sys_rwlock); +#ifdef THREAD_DEBUG + LOG_DEBUG3 ("rwlock %s, at %s:%d", rwlock->name, file, line); +#endif } void thread_exit_c(long val, int line, char *file) @@ -487,7 +500,7 @@ void thread_exit_c(long val, int line, char *file) } #endif #ifdef __OpenBSD__ - thread->running = 0; + th->running = 0; #endif if (th && th->detached) @@ -563,7 +576,7 @@ static void *_start_routine(void *arg) (start_routine)(real_arg); #ifdef __OpenBSD__ - thread->running = 0; + th->running = 0; #endif if (thread->detached) diff --git a/src/thread/thread.h b/src/thread/thread.h new file mode 100644 index 00000000..fba8fb12 --- /dev/null +++ b/src/thread/thread.h @@ -0,0 +1,194 @@ +/* thread.h + * - Thread Abstraction Function Headers + * + * 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 + */ + +#ifndef __THREAD_H__ +#define __THREAD_H__ + +#include + +/* renamed from thread_t due to conflict on OS X */ + +typedef struct { + /* the local id for the thread, and it's name */ + long thread_id; + char *name; + + /* the time the thread was created */ + time_t create_time; + + /* the file and line which created this thread */ + char *file; + int line; + + /* is the thread running detached? */ + int detached; + +#ifdef __OpenBSD__ + int running; +#endif + + /* the system specific thread */ + pthread_t sys_thread; +} thread_type; + +typedef struct { +#ifdef THREAD_DEBUG + /* the local id and name of the mutex */ + long mutex_id; + char *name; + + /* the thread which is currently locking this mutex */ + long thread_id; + + /* time the lock was taken */ + unsigned long long lock_start; + + /* the file and line where the mutex was locked */ + char *file; + int line; + +#endif + + /* the system specific mutex */ + pthread_mutex_t sys_mutex; +} mutex_t; + +typedef struct { +#ifdef THREAD_DEBUG + long cond_id; + char *name; +#endif + + pthread_mutex_t cond_mutex; + pthread_cond_t sys_cond; +} cond_t; + +typedef struct { +#ifdef THREAD_DEBUG + long rwlock_id; + char *name; + + /* information on which thread and where in the code + ** this rwlock was write locked + */ + long thread_id; + char *file; + int line; + + /* time the lock was taken */ + unsigned long long lock_start; +#endif + + pthread_rwlock_t sys_rwlock; +} rwlock_t; + +#define thread_create(n,x,y,z) thread_create_c(n,x,y,z,__LINE__,__FILE__) +#define thread_mutex_create(name,x) thread_mutex_create_c(name,x,__LINE__,__FILE__) +#define thread_mutex_lock(x) thread_mutex_lock_c(x,__LINE__,__FILE__) +#define thread_mutex_unlock(x) thread_mutex_unlock_c(x,__LINE__,__FILE__) +#define thread_cond_create(x) thread_cond_create_c(x,__LINE__,__FILE__) +#define thread_cond_signal(x) thread_cond_signal_c(x,__LINE__,__FILE__) +#define thread_cond_broadcast(x) thread_cond_broadcast_c(x,__LINE__,__FILE__) +#define thread_cond_wait(x) thread_cond_wait_c(x,__LINE__,__FILE__) +#define thread_cond_timedwait(x,t) thread_cond_wait_c(x,t,__LINE__,__FILE__) +#define thread_rwlock_create(x) thread_rwlock_create_c(__FILE__,(x),__LINE__,__FILE__) +#define thread_rwlock_rlock(x) thread_rwlock_rlock_c(x,__LINE__,__FILE__) +#define thread_rwlock_wlock(x) thread_rwlock_wlock_c(x,__LINE__,__FILE__) +#define thread_rwlock_unlock(x) thread_rwlock_unlock_c(x,__LINE__,__FILE__) +#define thread_exit(x) thread_exit_c(x,__LINE__,__FILE__) + +#define MUTEX_STATE_NOTLOCKED -1 +#define MUTEX_STATE_NEVERLOCKED -2 +#define MUTEX_STATE_UNINIT -3 +#define THREAD_DETACHED 1 +#define THREAD_ATTACHED 0 + +#ifdef _mangle +# define thread_initialize _mangle(thread_initialize) +# define thread_initialize_with_log_id _mangle(thread_initialize_with_log_id) +# define thread_shutdown _mangle(thread_shutdown) +# define thread_create_c _mangle(thread_create_c) +# define thread_mutex_create_c _mangle(thread_mutex_create) +# define thread_mutex_lock_c _mangle(thread_mutex_lock_c) +# define thread_mutex_unlock_c _mangle(thread_mutex_unlock_c) +# define thread_mutex_destroy _mangle(thread_mutex_destroy) +# define thread_cond_create_c _mangle(thread_cond_create_c) +# define thread_cond_signal_c _mangle(thread_cond_signal_c) +# define thread_cond_broadcast_c _mangle(thread_cond_broadcast_c) +# define thread_cond_wait_c _mangle(thread_cond_wait_c) +# define thread_cond_timedwait_c _mangle(thread_cond_timedwait_c) +# define thread_cond_destroy _mangle(thread_cond_destroy) +# define thread_rwlock_create_c _mangle(thread_rwlock_create_c) +# define thread_rwlock_rlock_c _mangle(thread_rwlock_rlock_c) +# define thread_rwlock_wlock_c _mangle(thread_rwlock_wlock_c) +# define thread_rwlock_unlock_c _mangle(thread_rwlock_unlock_c) +# define thread_rwlock_destroy _mangle(thread_rwlock_destroy) +# define thread_exit_c _mangle(thread_exit_c) +# define thread_sleep _mangle(thread_sleep) +# define thread_library_lock _mangle(thread_library_lock) +# define thread_library_unlock _mangle(thread_library_unlock) +# define thread_self _mangle(thread_self) +# define thread_rename _mangle(thread_rename) +# define thread_join _mangle(thread_join) +#endif + +/* init/shutdown of the library */ +void thread_initialize(void); +void thread_initialize_with_log_id(int log_id); +void thread_shutdown(void); + +/* creation, destruction, locking, unlocking, signalling and waiting */ +thread_type *thread_create_c(char *name, void *(*start_routine)(void *), + void *arg, int detached, int line, char *file); +void thread_mutex_create_c(const char *name, mutex_t *mutex, int line, const char *file); +void thread_mutex_lock_c(mutex_t *mutex, int line, char *file); +void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file); +void thread_mutex_destroy(mutex_t *mutex); +void thread_cond_create_c(cond_t *cond, int line, char *file); +void thread_cond_signal_c(cond_t *cond, int line, char *file); +void thread_cond_broadcast_c(cond_t *cond, int line, char *file); +void thread_cond_wait_c(cond_t *cond, int line, char *file); +void thread_cond_timedwait_c(cond_t *cond, int millis, int line, char *file); +void thread_cond_destroy(cond_t *cond); +void thread_rwlock_create_c(const char *name, rwlock_t *rwlock, int line, const char *file); +void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, const char *file); +void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, const char *file); +void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, const char *file); +void thread_rwlock_destroy(rwlock_t *rwlock); +void thread_exit_c(long val, int line, char *file); + +/* sleeping */ +void thread_sleep(unsigned long len); + +/* for using library functions which aren't threadsafe */ +void thread_library_lock(void); +void thread_library_unlock(void); +#define PROTECT_CODE(code) { thread_library_lock(); code; thread_library_unlock(); } + +/* thread information functions */ +thread_type *thread_self(void); + +/* renames current thread */ +void thread_rename(const char *name); + +/* waits until thread_exit is called for another thread */ +void thread_join(thread_type *thread); + +#endif /* __THREAD_H__ */