/* * The UCW Library -- Threading Helpers * * (c) 2006--2010 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. */ #include #include #ifdef CONFIG_UCW_THREADS #include #ifdef CONFIG_LINUX #include #include #include #ifdef __NR_gettid static pid_t ucw_gettid(void) { return syscall(__NR_gettid); } #define CONFIG_USE_GETTID #endif #endif /*** Library lock ***/ static pthread_mutex_t ucwlib_master_mutex; void ucwlib_lock(void) { pthread_mutex_lock(&ucwlib_master_mutex); } void ucwlib_unlock(void) { pthread_mutex_unlock(&ucwlib_master_mutex); } /*** Thread identifiers ***/ static int ucwlib_tid(void) { static int tid_counter; int tid; #ifdef CONFIG_USE_GETTID tid = ucw_gettid(); if (tid > 0) return tid; /* The syscall might be unimplemented */ #endif ucwlib_lock(); tid = ++tid_counter; ucwlib_unlock(); return tid; } /*** Thread context ***/ static void CONSTRUCTOR_WITH_PRIORITY(10000) ucwlib_threads_init_master(void) { pthread_mutex_init(&ucwlib_master_mutex, NULL); } #ifdef CONFIG_UCW_TLS __thread struct ucwlib_context ucwlib_context; int ucwlib_thread_id(struct ucwlib_context *c) { if (!c->_thread_id) c->_thread_id = ucwlib_tid(); return c->_thread_id; } #else static pthread_key_t ucwlib_context_key; static void ucwlib_free_thread_context(void *p) { xfree(p); } static void CONSTRUCTOR_WITH_PRIORITY(10000) ucwlib_threads_init(void) { if (pthread_key_create(&ucwlib_context_key, ucwlib_free_thread_context) < 0) die("Cannot create pthread_key: %m"); } struct ucwlib_context * ucwlib_thread_context(void) { struct ucwlib_context *c = pthread_getspecific(ucwlib_context_key); if (!c) { c = xmalloc_zero(sizeof(*c)); c->_thread_id = ucwlib_tid(); pthread_setspecific(ucwlib_context_key, c); } return c; } #endif /* CONFIG_UCW_TLS */ #else /* !CONFIG_UCW_THREADS */ struct ucwlib_context ucwlib_default_context; #endif #ifdef TEST int main(void) { ucwlib_lock(); ucwlib_unlock(); msg(L_INFO, "tid=%d", ucwlib_thread_id(ucwlib_thread_context())); return 0; } #endif