PJ_DEF(pj_thread_t*) pj_thread_register (const char *cstr_thread_name, pj_thread_desc desc) { 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 NULL; } /* If a thread descriptor has been registered before, just return it. */ if (pj_thread_local_get (thread_tls_id) != 0) { return (pj_thread_t*)pj_thread_local_get (thread_tls_id); } /* Initialize and set the thread entry. */ pj_memset(desc, 0, sizeof(pj_thread_desc)); thread->hthread = GetCurrentThread(); thread->idthread = GetCurrentThreadId(); if (cstr_thread_name && pj_strlen(&thread_name) < sizeof(thread->obj_name)-1) sprintf(thread->obj_name, cstr_thread_name, thread->idthread); else sprintf(thread->obj_name, "thr%p", (void*)thread->idthread); pj_thread_local_set(thread_tls_id, thread); return thread; }
PJ_DEF(pj_pool_t*) pj_pool_create_on_buf(const char *name, void *buf, pj_size_t size) { #if PJ_HAS_POOL_ALT_API == 0 struct creation_param param; long align_diff; PJ_ASSERT_RETURN(buf && size, NULL); if (!is_initialized) { if (pool_buf_initialize() != PJ_SUCCESS) return NULL; is_initialized = 1; } /* Check and align buffer */ align_diff = (long)buf; if (align_diff & (PJ_POOL_ALIGNMENT-1)) { align_diff &= (PJ_POOL_ALIGNMENT-1); buf = (void*) (((char*)buf) + align_diff); size -= align_diff; } param.stack_buf = buf; param.size = size; pj_thread_local_set(tls, ¶m); return pj_pool_create_int(&stack_based_factory, name, size, 0, pj_pool_factory_default_policy.callback); #else PJ_UNUSED_ARG(buf); return pj_pool_create(NULL, name, size, size, NULL); #endif }
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")); #if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0 PJ_LOG(5,(rec->obj_name, "Thread stack max usage=%u by %s:%d", rec->stk_max_usage, rec->caller_file, rec->caller_line)); #endif return (DWORD)result; }
/* * thread_main() * * This is the main entry for all threads. */ static void *thread_main(void *param) { pj_thread_t *rec = (pj_thread_t*)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_mutex_unlock(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; }
/* * mod_ua_load() * * Called when module is being loaded by endpoint. */ static pj_status_t mod_ua_load(pjsip_endpoint *endpt) { pj_status_t status; /* Initialize the user agent. */ mod_ua.endpt = endpt; mod_ua.pool = pjsip_endpt_create_pool( endpt, "ua%p", PJSIP_POOL_LEN_UA, PJSIP_POOL_INC_UA); if (mod_ua.pool == NULL) return PJ_ENOMEM; status = pj_mutex_create_recursive(mod_ua.pool, " ua%p", &mod_ua.mutex); if (status != PJ_SUCCESS) return status; mod_ua.dlg_table = pj_hash_create(mod_ua.pool, PJSIP_MAX_DIALOG_COUNT); if (mod_ua.dlg_table == NULL) return PJ_ENOMEM; pj_list_init(&mod_ua.free_dlgset_nodes); /* Initialize dialog lock. */ status = pj_thread_local_alloc(&pjsip_dlg_lock_tls_id); if (status != PJ_SUCCESS) return status; pj_thread_local_set(pjsip_dlg_lock_tls_id, NULL); return PJ_SUCCESS; }
/* This must be called in the context of the new thread. */ static void thread_initialize( pj_thread_t *thread ) { TRACE_((THIS_FILE, "---new thread initializing...")); /* Set TLS */ pj_thread_local_set(thread_tls_id, thread); /* fill in thread structure */ thread->thread = current; pj_assert(thread->thread != NULL); /* set signal mask to what we want to respond */ siginitsetinv(¤t->blocked, sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)); /* initialise wait queue */ init_waitqueue_head(&thread->queue); /* initialise termination flag */ thread->terminate = 0; /* set name of this process (making sure obj_name is null * terminated first) */ thread->obj_name[PJ_MAX_OBJ_NAME-1] = '\0'; sprintf(current->comm, thread->obj_name); /* tell the creator that we are ready and let him continue */ up(&thread->startstop_sem); }
PJ_DEF(void) pj_pop_exception_handler_(void) { struct pj_exception_state_t *handler; handler = pj_thread_local_get(thread_local_id); pj_assert(handler != NULL); pj_thread_local_set(thread_local_id, handler->prev); }
PJ_DEF(void) pj_pop_exception_handler_(struct pj_exception_state_t *rec) { struct pj_exception_state_t *handler; handler = (struct pj_exception_state_t *) pj_thread_local_get(thread_local_id); if (handler && handler==rec) { pj_thread_local_set(thread_local_id, handler->prev); } }
/* Carefully unlock dialog mutex, protect against situation when the dialog * has already been destroyed. */ static pj_status_t unlock_dialog(pjsip_dlg *dlg, struct dialog_lock_data *lck) { pj_assert(pj_thread_local_get(pjsip_dlg_lock_tls_id) == lck); pj_assert(dlg == lck->dlg); pj_thread_local_set(pjsip_dlg_lock_tls_id, lck->prev); if (lck->is_alive) pj_mutex_unlock(dlg->mutex); return lck->is_alive ? 0 : -1; }
/* Lock dialog mutex. */ static void lock_dialog(pjsip_dlg *dlg, struct dialog_lock_data *lck) { struct dialog_lock_data *prev; pj_mutex_lock(dlg->mutex); prev = pj_thread_local_get(pjsip_dlg_lock_tls_id); lck->prev = prev; lck->dlg = dlg; lck->is_alive = 1; pj_thread_local_set(pjsip_dlg_lock_tls_id, lck); }
/* * 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*)(pj_ssize_t)thread->idthread); rc = pj_thread_local_set(thread_tls_id, thread); if (rc != PJ_SUCCESS) return rc; *thread_ptr = thread; return PJ_SUCCESS; }
PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec) { struct pj_exception_state_t *parent_handler = NULL; if (thread_local_id == -1) { pj_thread_local_alloc(&thread_local_id); pj_assert(thread_local_id != -1); pj_atexit(&exception_cleanup); } parent_handler = pj_thread_local_get(thread_local_id); rec->prev = parent_handler; pj_thread_local_set(thread_local_id, rec); }
static DWORD WINAPI thread_main(void *param) { pj_thread_t *rec = param; void *result; PJ_LOG(6,(rec->obj_name, "Thread started")); pj_thread_local_set(thread_tls_id, rec); result = (*rec->proc)(rec->arg); PJ_LOG(6,(rec->obj_name, "Thread quitting")); return (DWORD)result; }
/* Resume logging facility for this thread */ static void resume_logging(int *saved_level) { #if PJ_HAS_THREADS if (thread_suspended_tls_id != -1) { pj_thread_local_set(thread_suspended_tls_id, (void*)PJ_FALSE); } else #endif { /* Only revert the level if application doesn't change the * logging level between suspend and resume. */ if (pj_log_max_level==0 && *saved_level) pj_log_max_level = *saved_level; } }
/* Temporarily suspend logging facility for this thread. * If thread local storage/variable is not used or not initialized, then * we can only suspend the logging globally across all threads. This may * happen e.g. when log function is called before PJLIB is fully initialized * or after PJLIB is shutdown. */ static void suspend_logging(int *saved_level) { /* Save the level regardless, just in case PJLIB is shutdown * between suspend and resume. */ *saved_level = pj_log_max_level; #if PJ_HAS_THREADS if (thread_suspended_tls_id != -1) { pj_thread_local_set(thread_suspended_tls_id, (void*)PJ_TRUE); } else #endif { pj_log_max_level = 0; } }
pj_status_t pj_thread_init(void) { #if PJ_HAS_THREADS pj_memset(&main_thread, 0, sizeof(main_thread)); main_thread.thread = pthread_self(); sprintf(main_thread.obj_name, "thr%p", &main_thread); thread_tls_id = pj_thread_local_alloc(); if (thread_tls_id == -1) { return -1; } pj_thread_local_set(thread_tls_id, &main_thread); return PJ_OK; #else PJ_LOG(2,(THIS_FILE, "Thread init error. Threading is not enabled!")); return -1; #endif }
PJ_DEF(pj_pool_t*) pj_pool_create_on_buf(const char *name, void *buf, pj_size_t size) { struct creation_param param; PJ_ASSERT_RETURN(buf && size, NULL); if (!is_initialized) { if (pool_buf_initialize() != PJ_SUCCESS) return NULL; is_initialized = 1; } param.stack_buf = buf; param.size = size; pj_thread_local_set(tls, ¶m); return pj_pool_create_int(&stack_based_factory, name, size, 0, pj_pool_factory_default_policy.callback); }
static void* stack_alloc(pj_pool_factory *factory, pj_size_t size) { struct creation_param *param; void *buf; PJ_UNUSED_ARG(factory); param = (struct creation_param*) pj_thread_local_get(tls); if (param == NULL) { /* Don't assert(), this is normal no-memory situation */ return NULL; } pj_thread_local_set(tls, NULL); PJ_ASSERT_RETURN(size <= param->size, NULL); buf = param->stack_buf; /* Prevent the buffer from being reused */ param->stack_buf = NULL; return buf; }
/* * 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 }
// // Set thread specific data. // static pj_status_t set(long index, void *value) { return pj_thread_local_set(index, value); }
static void log_set_indent(int indent) { if (indent < 0) indent = 0; pj_thread_local_set(thread_indent_tls_id, (void*)(long)indent); }