⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.c,v

📁 版本控制CVS资源库转换成SVN库的转换程序
💻 C,V
📖 第 1 页 / 共 3 页
字号:
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.25date	2003.07.14.02.17.52;	author brendan;	state Exp;branches;next	1.24;1.24date	2003.03.15.02.10.18;	author msmith;	state Exp;branches;next	1.23;1.23date	2003.03.12.03.59.55;	author karl;	state Exp;branches;next	1.22;1.22date	2003.03.09.22.56.46;	author karl;	state Exp;branches;next	1.21;1.21date	2003.03.08.16.05.38;	author karl;	state Exp;branches;next	1.20;1.20date	2003.03.04.15.31.34;	author msmith;	state Exp;branches;next	1.19;1.19date	2003.01.17.09.01.04;	author msmith;	state Exp;branches;next	1.18;1.18date	2002.12.29.09.55.50;	author msmith;	state Exp;branches;next	1.17;1.17date	2002.11.22.13.00.44;	author msmith;	state Exp;branches;next	1.16;1.16date	2002.09.24.07.09.08;	author msmith;	state Exp;branches;next	1.15;1.15date	2002.08.16.14.23.17;	author msmith;	state Exp;branches;next	1.14;1.14date	2002.08.13.01.08.15;	author msmith;	state Exp;branches;next	1.13;1.13date	2002.08.10.03.22.44;	author msmith;	state Exp;branches;next	1.12;1.12date	2002.08.09.06.52.07;	author msmith;	state Exp;branches;next	1.11;1.11date	2002.08.05.14.48.03;	author msmith;	state Exp;branches;next	1.10;1.10date	2002.08.03.08.14.56;	author msmith;	state Exp;branches;next	1.9;1.9date	2002.04.30.06.50.47;	author msmith;	state Exp;branches;next	1.8;1.8date	2002.03.05.23.59.38;	author jack;	state Exp;branches;next	1.7;1.7date	2002.02.08.03.51.19;	author jack;	state Exp;branches;next	1.6;1.6date	2002.02.07.01.04.09;	author jack;	state Exp;branches;next	1.5;1.5date	2001.10.21.02.04.27;	author jack;	state Exp;branches;next	1.4;1.4date	2001.10.20.22.27.52;	author jack;	state Exp;branches;next	1.3;1.3date	2001.10.20.05.35.30;	author jack;	state Exp;branches;next	1.2;1.2date	2001.10.20.03.39.10;	author jack;	state Exp;branches;next	1.1;1.1date	2001.09.10.02.26.33;	author jack;	state Exp;branches	1.1.1.1;next	;1.1.1.1date	2001.09.10.02.26.33;	author jack;	state Exp;branches;next	;desc@@1.25log@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_MUTEXESstatic mutex_t _threadtree_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1,     PTHREAD_MUTEX_INITIALIZER};#elsestatic mutex_t _threadtree_mutex = { PTHREAD_MUTEX_INITIALIZER };#endif#ifdef DEBUG_MUTEXESstatic 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_MUTEXESstatic mutex_t _library_mutex = { -1, NULL, MUTEX_STATE_UNINIT, NULL, -1,    PTHREAD_MUTEX_INITIALIZER};#elsestatic mutex_t _library_mutex = { PTHREAD_MUTEX_INITIALIZER };#endif/* INTERNAL FUNCTIONS *//* avl tree functions */#ifdef DEBUG_MUTEXESstatic int _compare_mutexes(void *compare_arg, void *a, void *b);static int _free_mutex(void *key);#endifstatic 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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -