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

📄 os_core_unix.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: os_core_unix.c 1075 2007-03-16 18:41:07Z bennylp $ *//*  * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org> * * 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 later 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  *//* * Contributors: * - Thanks for Zetron, Inc. (Phil Torre, ptorre@zetron.com) for donating *   the RTEMS port. */#define _GNU_SOURCE#include <pj/os.h>#include <pj/assert.h>#include <pj/pool.h>#include <pj/log.h>#include <pj/rand.h>#include <pj/string.h>#include <pj/guid.h>#include <pj/except.h>#include <pj/errno.h>#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0#  include <semaphore.h>#endif#include <unistd.h>	    // getpid()#include <errno.h>	    // errno#include <pthread.h>#define THIS_FILE   "os_core_unix.c"#define SIGNATURE1  0xDEAFBEEF#define SIGNATURE2  0xDEADC0DEstruct pj_thread_t{    char	    obj_name[PJ_MAX_OBJ_NAME];    pthread_t	    thread;    pj_thread_proc *proc;    void	   *arg;    pj_uint32_t	    signature1;    pj_uint32_t	    signature2;    pj_mutex_t	   *suspended_mutex;#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0    pj_uint32_t	    stk_size;    pj_uint32_t	    stk_max_usage;    char	   *stk_start;    const char	   *caller_file;    int		    caller_line;#endif};struct pj_atomic_t{    pj_mutex_t	       *mutex;    pj_atomic_value_t	value;};struct pj_mutex_t{    pthread_mutex_t     mutex;    char		obj_name[PJ_MAX_OBJ_NAME];#if PJ_DEBUG    int		        nesting_level;    pj_thread_t	       *owner;    char		owner_name[PJ_MAX_OBJ_NAME];#endif};#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0struct pj_sem_t{    sem_t		sem;    char		obj_name[PJ_MAX_OBJ_NAME];};#endif /* PJ_HAS_SEMAPHORE */#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0struct pj_event_t{    char		obj_name[PJ_MAX_OBJ_NAME];};#endif	/* PJ_HAS_EVENT_OBJ */#if PJ_HAS_THREADS    static pj_thread_t main_thread;    static long thread_tls_id;    static pj_mutex_t critical_section;#else#   define MAX_THREADS 32    static int tls_flag[MAX_THREADS];    static void *tls[MAX_THREADS];#endifstatic unsigned atexit_count;static void (*atexit_func[32])(void);static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name, int type);/* * pj_init(void). * Init PJLIB! */PJ_DEF(pj_status_t) pj_init(void){    char dummy_guid[PJ_GUID_MAX_LENGTH];    pj_str_t guid;    pj_status_t rc;#if PJ_HAS_THREADS    /* Init this thread's TLS. */    if ((rc=pj_thread_init()) != 0) {	return rc;    }    /* Critical section. */    if ((rc=init_mutex(&critical_section, "critsec", PJ_MUTEX_RECURSE)) != 0)	return rc;#endif    /* Initialize exception ID for the pool.      * Must do so after critical section is configured.     */    rc = pj_exception_id_alloc("PJLIB/No memory", &PJ_NO_MEMORY_EXCEPTION);    if (rc != PJ_SUCCESS)        return rc;        /* Init random seed. */    pj_srand( clock() );    /* Startup GUID. */    guid.ptr = dummy_guid;    pj_generate_unique_string( &guid );    /* Startup timestamp */#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0    {	pj_timestamp dummy_ts;	if ((rc=pj_get_timestamp(&dummy_ts)) != 0) {	    return rc;	}    }#endif       PJ_LOG(4,(THIS_FILE, "pjlib %s for POSIX initialized",	      PJ_VERSION));    return PJ_SUCCESS;}/* * pj_atexit() */PJ_DEF(pj_status_t) pj_atexit(void (*func)(void)){    if (atexit_count >= PJ_ARRAY_SIZE(atexit_func))	return PJ_ETOOMANY;    atexit_func[atexit_count++] = func;    return PJ_SUCCESS;}/* * pj_shutdown(void) */PJ_DEF(void) pj_shutdown(){    int i;    /* Call atexit() functions */    for (i=atexit_count-1; i>=0; --i) {	(*atexit_func[i])();    }    atexit_count = 0;    /* Free exception ID */    if (PJ_NO_MEMORY_EXCEPTION != -1) {	pj_exception_id_free(PJ_NO_MEMORY_EXCEPTION);	PJ_NO_MEMORY_EXCEPTION = -1;    }#if PJ_HAS_THREADS    /* Destroy PJLIB critical section */    pj_mutex_destroy(&critical_section);    /* Free PJLIB TLS */    if (thread_tls_id != -1) {	pj_thread_local_free(thread_tls_id);	thread_tls_id = -1;    }#endif    /* Clear static variables */    pj_errno_clear_handlers();}/* * pj_getpid(void) */PJ_DEF(pj_uint32_t) pj_getpid(void){    PJ_CHECK_STACK();    return getpid();}/* * Check if this thread has been registered to PJLIB. */PJ_DEF(pj_bool_t) pj_thread_is_registered(void){#if PJ_HAS_THREADS    return pj_thread_local_get(thread_tls_id) != 0;#else    pj_assert("pj_thread_is_registered() called in non-threading mode!");    return PJ_TRUE;#endif}/* * pj_thread_register(..) */PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,					 pj_thread_desc desc,					 pj_thread_t **ptr_thread){#if PJ_HAS_THREADS    char stack_ptr;    pj_status_t rc;    pj_thread_t *thread = (pj_thread_t *)desc;    pj_str_t thread_name = pj_str((char*)cstr_thread_name);    /* Size sanity check. */    if (sizeof(pj_thread_desc) < sizeof(pj_thread_t)) {	pj_assert(!"Not enough pj_thread_desc size!");	return PJ_EBUG;    }    /* Warn if this thread has been registered before */    if (pj_thread_local_get (thread_tls_id) != 0) {	// 2006-02-26 bennylp:	//  This wouldn't work in all cases!.	//  If thread is created by external module (e.g. sound thread),	//  thread may be reused while the pool used for the thread descriptor	//  has been deleted by application.	//*thread_ptr = (pj_thread_t*)pj_thread_local_get (thread_tls_id);        //return PJ_SUCCESS;	PJ_LOG(4,(THIS_FILE, "Info: possibly re-registering existing "			     "thread"));    }    /* On the other hand, also warn if the thread descriptor buffer seem to     * have been used to register other threads.     */    pj_assert(thread->signature1 != SIGNATURE1 ||	      thread->signature2 != SIGNATURE2 ||	      (thread->thread == pthread_self()));    /* Initialize and set the thread entry. */    pj_bzero(desc, sizeof(struct pj_thread_t));    thread->thread = pthread_self();    thread->signature1 = SIGNATURE1;    thread->signature2 = SIGNATURE2;    if(cstr_thread_name && pj_strlen(&thread_name) < sizeof(thread->obj_name)-1)	pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 			 cstr_thread_name, thread->thread);    else	pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 			 "thr%p", (void*)thread->thread);        rc = pj_thread_local_set(thread_tls_id, thread);    if (rc != PJ_SUCCESS) {	pj_bzero(desc, sizeof(struct pj_thread_t));	return rc;    }#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0    thread->stk_start = &stack_ptr;    thread->stk_size = 0xFFFFFFFFUL;    thread->stk_max_usage = 0;#else    stack_ptr = '\0';#endif    *ptr_thread = thread;    return PJ_SUCCESS;#else    pj_thread_t *thread = (pj_thread_t*)desc;    *ptr_thread = thread;    return PJ_SUCCESS;#endif}/* * pj_thread_init(void) */pj_status_t pj_thread_init(void){#if PJ_HAS_THREADS    pj_status_t rc;    pj_thread_t *dummy;    rc = pj_thread_local_alloc(&thread_tls_id );    if (rc != PJ_SUCCESS) {	return rc;    }    return pj_thread_register("thr%p", (long*)&main_thread, &dummy);#else    PJ_LOG(2,(THIS_FILE, "Thread init error. Threading is not enabled!"));    return PJ_EINVALIDOP;#endif}#if PJ_HAS_THREADS/* * thread_main() * * This is the main entry for all threads. */static void *thread_main(void *param){    pj_thread_t *rec = param;    void *result;    pj_status_t rc;#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0    rec->stk_start = (char*)&rec;#endif    /* Set current thread id. */    rc = pj_thread_local_set(thread_tls_id, rec);    if (rc != PJ_SUCCESS) {	pj_assert(!"Thread TLS ID is not set (pj_init() error?)");    }    /* Check if suspension is required. */    if (rec->suspended_mutex)	pj_mutex_lock(rec->suspended_mutex);    PJ_LOG(6,(rec->obj_name, "Thread started"));    /* Call user's entry! */    result = (void*)(long)(*rec->proc)(rec->arg);    /* Done. */    PJ_LOG(6,(rec->obj_name, "Thread quitting"));    return result;}#endif/* * pj_thread_create(...) */PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, 				      const char *thread_name,				      pj_thread_proc *proc, 				      void *arg,				      pj_size_t stack_size, 				      unsigned flags,				      pj_thread_t **ptr_thread){#if PJ_HAS_THREADS    pj_thread_t *rec;    pthread_attr_t thread_attr;    void *stack_addr;    int rc;    PJ_UNUSED_ARG(stack_addr);    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(pool && proc && ptr_thread, PJ_EINVAL);    /* Create thread record and assign name for the thread */    rec = (struct pj_thread_t*) pj_pool_zalloc(pool, sizeof(pj_thread_t));    PJ_ASSERT_RETURN(rec, PJ_ENOMEM);        /* Set name. */    if (!thread_name) 	thread_name = "thr%p";        if (strchr(thread_name, '%')) {	pj_ansi_snprintf(rec->obj_name, PJ_MAX_OBJ_NAME, thread_name, rec);    } else {	strncpy(rec->obj_name, thread_name, PJ_MAX_OBJ_NAME);	rec->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';    }    /* Set default stack size */    if (stack_size == 0)	stack_size = PJ_THREAD_DEFAULT_STACK_SIZE;#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0    rec->stk_size = stack_size;    rec->stk_max_usage = 0;#endif    /* Emulate suspended thread with mutex. */    if (flags & PJ_THREAD_SUSPENDED) {	rc = pj_mutex_create_simple(pool, NULL, &rec->suspended_mutex);	if (rc != PJ_SUCCESS) {	    return rc;	}	pj_mutex_lock(rec->suspended_mutex);    } else {	pj_assert(rec->suspended_mutex == NULL);    }        /* Init thread attributes */    pthread_attr_init(&thread_attr);#if defined(PJ_THREAD_SET_STACK_SIZE) && PJ_THREAD_SET_STACK_SIZE!=0    /* Set thread's stack size */    rc = pthread_attr_setstacksize(&thread_attr, stack_size);    if (rc != 0)	return PJ_RETURN_OS_ERROR(rc);#endif	/* PJ_THREAD_SET_STACK_SIZE */#if defined(PJ_THREAD_ALLOCATE_STACK) && PJ_THREAD_ALLOCATE_STACK!=0    /* Allocate memory for the stack */    stack_addr = pj_pool_alloc(pool, stack_size);    PJ_ASSERT_RETURN(stack_addr, PJ_ENOMEM);    rc = pthread_attr_setstackaddr(&thread_attr, stack_addr);    if (rc != 0)	return PJ_RETURN_OS_ERROR(rc);#endif	/* PJ_THREAD_ALLOCATE_STACK */    /* Create the thread. */    rec->proc = proc;    rec->arg = arg;    rc = pthread_create( &rec->thread, &thread_attr, &thread_main, rec);    if (rc != 0) {	return PJ_RETURN_OS_ERROR(rc);    }    *ptr_thread = rec;    PJ_LOG(6, (rec->obj_name, "Thread created"));    return PJ_SUCCESS;#else    pj_assert(!"Threading is disabled!");    return PJ_EINVALIDOP;#endif}/* * pj_thread-get_name() */PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *p){#if PJ_HAS_THREADS    pj_thread_t *rec = (pj_thread_t*)p;    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(p, "");    return rec->obj_name;#else    return "";#endif}/* * pj_thread_resume() */PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *p){    pj_status_t rc;    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(p, PJ_EINVAL);    rc = pj_mutex_unlock(p->suspended_mutex);    return rc;}/* * pj_thread_this() */PJ_DEF(pj_thread_t*) pj_thread_this(void){#if PJ_HAS_THREADS    pj_thread_t *rec = pj_thread_local_get(thread_tls_id);        if (rec == NULL) {	pj_assert(!"Calling pjlib from unknown/external thread. You must "		   "register external threads with pj_thread_register() "		   "before calling any pjlib functions.");    }    /*     * MUST NOT check stack because this function is called     * by PJ_CHECK_STACK() itself!!!     *     */

⌨️ 快捷键说明

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