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

📄 os_core_win32.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: os_core_win32.c 1045 2007-03-06 23:32:25Z 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  */#include <pj/os.h>#include <pj/pool.h>#include <pj/log.h>#include <pj/string.h>#include <pj/guid.h>#include <pj/rand.h>#include <pj/assert.h>#include <pj/errno.h>#include <pj/except.h>#include <stddef.h>#include <stdlib.h>#include <stdio.h>#if defined(PJ_HAS_WINSOCK_H) && PJ_HAS_WINSOCK_H != 0#  include <winsock.h>#endif#if defined(PJ_HAS_WINSOCK2_H) && PJ_HAS_WINSOCK2_H != 0#  include <winsock2.h>#endif#define THIS_FILE	"os_core_win32.c"/* * Implementation of pj_thread_t. */struct pj_thread_t{    char	    obj_name[PJ_MAX_OBJ_NAME];    HANDLE	    hthread;    DWORD	    idthread;    pj_thread_proc *proc;    void	   *arg;#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};/* * Implementation of pj_mutex_t. */struct pj_mutex_t{#if PJ_WIN32_WINNT >= 0x0400    CRITICAL_SECTION	crit;#else    HANDLE		hMutex;#endif    char		obj_name[PJ_MAX_OBJ_NAME];#if PJ_DEBUG    int		        nesting_level;    pj_thread_t	       *owner;#endif};/* * Implementation of pj_sem_t. */typedef struct pj_sem_t{    HANDLE		hSemaphore;    char		obj_name[PJ_MAX_OBJ_NAME];} pj_mem_t;/* * Implementation of pj_event_t. */struct pj_event_t{    HANDLE		hEvent;    char		obj_name[PJ_MAX_OBJ_NAME];};/* * Implementation of pj_atomic_t. */struct pj_atomic_t{    long value;};/* * Static global variables. */static pj_thread_desc main_thread;static long thread_tls_id = -1;static pj_mutex_t critical_section_mutex;static unsigned atexit_count;static void (*atexit_func[32])(void);/* * Some static prototypes. */static pj_status_t init_mutex(pj_mutex_t *mutex, const char *name);/* * pj_init(void). * Init PJLIB! */PJ_DEF(pj_status_t) pj_init(void){    WSADATA wsa;    char dummy_guid[32]; /* use maximum GUID length */    pj_str_t guid;    pj_status_t rc;    /* Init Winsock.. */    if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {	return PJ_RETURN_OS_ERROR(WSAGetLastError());    }    /* Init this thread's TLS. */    if ((rc=pj_thread_init()) != PJ_SUCCESS) {	return rc;    }        /* Init random seed. */    pj_srand( GetCurrentProcessId() );    /* Startup GUID. */    guid.ptr = dummy_guid;    pj_generate_unique_string( &guid );    /* Initialize critical section. */    if ((rc=init_mutex(&critical_section_mutex, "pj%p")) != PJ_SUCCESS)	return rc;    /* 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;    /* Startup timestamp */#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0    {	pj_timestamp dummy_ts;	if ((rc=pj_get_timestamp_freq(&dummy_ts)) != PJ_SUCCESS) {	    return rc;	}	if ((rc=pj_get_timestamp(&dummy_ts)) != PJ_SUCCESS) {	    return rc;	}    }#endif       PJ_LOG(4,(THIS_FILE, "pjlib %s for win32 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;    }    /* Destroy PJLIB critical section */    pj_mutex_destroy(&critical_section_mutex);    /* Free PJLIB TLS */    if (thread_tls_id != -1) {	pj_thread_local_free(thread_tls_id);	thread_tls_id = -1;    }    /* Clear static variables */    pj_errno_clear_handlers();    /* Shutdown Winsock */    //WSACleanup();}/* * pj_getpid(void) */PJ_DEF(pj_uint32_t) pj_getpid(void){    PJ_CHECK_STACK();    return GetCurrentProcessId();}/* * Check if this thread has been registered to PJLIB. */PJ_DEF(pj_bool_t) pj_thread_is_registered(void){    return pj_thread_local_get(thread_tls_id) != 0;}/* * pj_thread_register(..) */PJ_DEF(pj_status_t) pj_thread_register ( const char *cstr_thread_name,					 pj_thread_desc desc,                                         pj_thread_t **thread_ptr){    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;    }    /* If a thread descriptor has been registered before, just return it. */    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;    }    /* Initialize and set the thread entry. */    pj_bzero(desc, sizeof(struct pj_thread_t));    thread->hthread = GetCurrentThread();    thread->idthread = GetCurrentThreadId();#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    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->idthread);    else	pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 		         "thr%p", (void*)thread->idthread);        rc = pj_thread_local_set(thread_tls_id, thread);    if (rc != PJ_SUCCESS)	return rc;    *thread_ptr = thread;    return PJ_SUCCESS;}/* * pj_thread_init(void) */pj_status_t pj_thread_init(void){    pj_status_t rc;    pj_thread_t *thread;    rc = pj_thread_local_alloc(&thread_tls_id);    if (rc != PJ_SUCCESS)	return rc;    return pj_thread_register("thr%p", main_thread, &thread);}static DWORD WINAPI thread_main(void *param){    pj_thread_t *rec = param;    DWORD result;#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0    rec->stk_start = (char*)&rec;#endif    if (pj_thread_local_set(thread_tls_id, rec) != PJ_SUCCESS) {	pj_assert(!"TLS is not set (pj_init() error?)");    }    PJ_LOG(6,(rec->obj_name, "Thread started"));    result = (*rec->proc)(rec->arg);    PJ_LOG(6,(rec->obj_name, "Thread quitting"));    return (DWORD)result;}/* * 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 **thread_ptr){    DWORD dwflags = 0;    pj_thread_t *rec;    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(pool && proc && thread_ptr, PJ_EINVAL);    /* Set flags */    if (flags & PJ_THREAD_SUSPENDED)	dwflags |= CREATE_SUSPENDED;    /* Create thread record and assign name for the thread */    rec = (struct pj_thread_t*) pj_pool_calloc(pool, 1, sizeof(pj_thread_t));    if (!rec)	return 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 {	pj_ansi_strncpy(rec->obj_name, thread_name, PJ_MAX_OBJ_NAME);	rec->obj_name[PJ_MAX_OBJ_NAME-1] = '\0';    }    PJ_LOG(6, (rec->obj_name, "Thread created"));#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0    rec->stk_size = stack_size ? stack_size : 0xFFFFFFFFUL;    rec->stk_max_usage = 0;#endif    /* Create the thread. */    rec->proc = proc;    rec->arg = arg;    rec->hthread = CreateThread(NULL, stack_size, 				thread_main, rec,				dwflags, &rec->idthread);    if (rec->hthread == NULL)	return PJ_RETURN_OS_ERROR(GetLastError());    /* Success! */    *thread_ptr = rec;    return PJ_SUCCESS;}/* * pj_thread-get_name() */PJ_DEF(const char*) pj_thread_get_name(pj_thread_t *p){    pj_thread_t *rec = (pj_thread_t*)p;    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(p, "");    return rec->obj_name;}/* * pj_thread_resume() */PJ_DEF(pj_status_t) pj_thread_resume(pj_thread_t *p){    pj_thread_t *rec = (pj_thread_t*)p;    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(p, PJ_EINVAL);    if (ResumeThread(rec->hthread) == (DWORD)-1)        return PJ_RETURN_OS_ERROR(GetLastError());    else        return PJ_SUCCESS;}/* * pj_thread_this() */PJ_DEF(pj_thread_t*) pj_thread_this(void){    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!!!     *     */    return rec;}/* * pj_thread_join() */PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p){    pj_thread_t *rec = (pj_thread_t *)p;    DWORD rc;    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(p, PJ_EINVAL);    PJ_LOG(6, (pj_thread_this()->obj_name, "Joining thread %s", p->obj_name));    rc = WaitForSingleObject(rec->hthread, INFINITE);    if (rc==WAIT_OBJECT_0)        return PJ_SUCCESS;    else if (rc==WAIT_TIMEOUT)        return PJ_ETIMEDOUT;    else        return PJ_RETURN_OS_ERROR(GetLastError());}/* * pj_thread_destroy() */PJ_DEF(pj_status_t) pj_thread_destroy(pj_thread_t *p){    pj_thread_t *rec = (pj_thread_t *)p;    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(p, PJ_EINVAL);    if (CloseHandle(rec->hthread) == TRUE)        return PJ_SUCCESS;    else        return PJ_RETURN_OS_ERROR(GetLastError());}/* * pj_thread_sleep() */PJ_DEF(pj_status_t) pj_thread_sleep(unsigned msec){    PJ_CHECK_STACK();    Sleep(msec);    return PJ_SUCCESS;}#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK != 0/* * pj_thread_check_stack() * Implementation for PJ_CHECK_STACK() */PJ_DEF(void) pj_thread_check_stack(const char *file, int line){    char stk_ptr;    pj_uint32_t usage;    pj_thread_t *thread = pj_thread_this();    pj_assert(thread);    /* Calculate current usage. */    usage = (&stk_ptr > thread->stk_start) ? &stk_ptr - thread->stk_start :		thread->stk_start - &stk_ptr;    /* Assert if stack usage is dangerously high. */    pj_assert("STACK OVERFLOW!! " && (usage <= thread->stk_size - 128));    /* Keep statistic. */    if (usage > thread->stk_max_usage) {	thread->stk_max_usage = usage;	thread->caller_file = file;	thread->caller_line = line;    }}/* * pj_thread_get_stack_max_usage() */PJ_DEF(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread){    return thread->stk_max_usage;}/* * pj_thread_get_stack_info() */PJ_DEF(pj_status_t) pj_thread_get_stack_info( pj_thread_t *thread,					      const char **file,					      int *line ){    pj_assert(thread);    *file = thread->caller_file;    *line = thread->caller_line;    return 0;}#endif	/* PJ_OS_HAS_CHECK_STACK */////////////////////////////////////////////////////////////////////////////////* * pj_atomic_create() */PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool,                                       pj_atomic_value_t initial,                                      pj_atomic_t **atomic_ptr){    pj_atomic_t *atomic_var = pj_pool_alloc(pool, sizeof(pj_atomic_t));    if (!atomic_var)	return PJ_ENOMEM;    atomic_var->value = initial;    *atomic_ptr = atomic_var;    return PJ_SUCCESS;}/* * pj_atomic_destroy() */PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *var ){    PJ_UNUSED_ARG(var);    PJ_ASSERT_RETURN(var, PJ_EINVAL);    return 0;}/* * pj_atomic_set() */PJ_DEF(void) pj_atomic_set( pj_atomic_t *atomic_var, pj_atomic_value_t value){    PJ_CHECK_STACK();    InterlockedExchange(&atomic_var->value, value);}/* * pj_atomic_get() */PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var){    PJ_CHECK_STACK();    PJ_ASSERT_RETURN(atomic_var, 0);    return atomic_var->value;}/* * pj_atomic_inc_and_get() */PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var){    PJ_CHECK_STACK();#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400    return InterlockedIncrement(&atomic_var->value);#else    return InterlockedIncrement(&atomic_var->value);#endif}/* * pj_atomic_inc() */PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var){    pj_atomic_inc_and_get(atomic_var);}/* * pj_atomic_dec_and_get() */PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var){    PJ_CHECK_STACK();#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400    return InterlockedDecrement(&atomic_var->value);#else    return InterlockedDecrement(&atomic_var->value);#endif}/* * pj_atomic_dec() */PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var){    pj_atomic_dec_and_get(atomic_var);}/* * pj_atomic_add() */PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,			    pj_atomic_value_t value ){#if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400    InterlockedExchangeAdd( &atomic_var->value, value );#else    InterlockedExchangeAdd( &atomic_var->value, value );

⌨️ 快捷键说明

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