You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
2.2 KiB
136 lines
2.2 KiB
/*
|
|
* The UCW Library -- Threading Helpers
|
|
*
|
|
* (c) 2006--2010 Martin Mares <mj@ucw.cz>
|
|
*
|
|
* This software may be freely distributed and used according to the terms
|
|
* of the GNU Lesser General Public License.
|
|
*/
|
|
|
|
#include <ucw/lib.h>
|
|
#include <ucw/threads.h>
|
|
|
|
#ifdef CONFIG_UCW_THREADS
|
|
|
|
#include <pthread.h>
|
|
|
|
#ifdef CONFIG_LINUX
|
|
#include <sys/types.h>
|
|
#include <sys/syscall.h>
|
|
#include <unistd.h>
|
|
#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
|
|
|