]> mj.ucw.cz Git - libucw.git/blob - ucw/threads.c
Merge branch 'master' into dev-sizet
[libucw.git] / ucw / threads.c
1 /*
2  *      The UCW Library -- Threading Helpers
3  *
4  *      (c) 2006--2010 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/threads.h>
12
13 #ifdef CONFIG_UCW_THREADS
14
15 #include <pthread.h>
16
17 #ifdef CONFIG_LINUX
18 #include <sys/types.h>
19 #include <sys/syscall.h>
20 #include <unistd.h>
21 #ifdef __NR_gettid
22 static pid_t
23 gettid(void)
24 {
25   return syscall(__NR_gettid);
26 }
27 #define CONFIG_USE_GETTID
28 #endif
29 #endif
30
31 /*** Library lock ***/
32
33 static pthread_mutex_t ucwlib_master_mutex;
34
35 void
36 ucwlib_lock(void)
37 {
38   pthread_mutex_lock(&ucwlib_master_mutex);
39 }
40
41 void
42 ucwlib_unlock(void)
43 {
44   pthread_mutex_unlock(&ucwlib_master_mutex);
45 }
46
47 /*** Thread identifiers ***/
48
49 static int
50 ucwlib_tid(void)
51 {
52   static int tid_counter;
53   int tid;
54
55 #ifdef CONFIG_USE_GETTID
56   tid = gettid();
57   if (tid > 0)
58     return tid;
59   /* The syscall might be unimplemented */
60 #endif
61
62   ucwlib_lock();
63   tid = ++tid_counter;
64   ucwlib_unlock();
65   return tid;
66 }
67
68 /*** Thread context ***/
69
70 static void CONSTRUCTOR_WITH_PRIORITY(10000)
71 ucwlib_threads_init_master(void)
72 {
73   pthread_mutex_init(&ucwlib_master_mutex, NULL);
74 }
75
76 #ifdef CONFIG_UCW_TLS
77
78 __thread struct ucwlib_context ucwlib_context;
79
80 int
81 ucwlib_thread_id(struct ucwlib_context *c)
82 {
83   if (!c->_thread_id)
84     c->_thread_id = ucwlib_tid();
85   return c->_thread_id;
86 }
87
88 #else
89
90 static pthread_key_t ucwlib_context_key;
91
92 static void
93 ucwlib_free_thread_context(void *p)
94 {
95   xfree(p);
96 }
97
98 static void CONSTRUCTOR_WITH_PRIORITY(10000)
99 ucwlib_threads_init(void)
100 {
101   if (pthread_key_create(&ucwlib_context_key, ucwlib_free_thread_context) < 0)
102     die("Cannot create pthread_key: %m");
103 }
104
105 struct ucwlib_context *
106 ucwlib_thread_context(void)
107 {
108   struct ucwlib_context *c = pthread_getspecific(ucwlib_context_key);
109   if (!c)
110     {
111       c = xmalloc_zero(sizeof(*c));
112       c->_thread_id = ucwlib_tid();
113       pthread_setspecific(ucwlib_context_key, c);
114     }
115   return c;
116 }
117
118 #endif /* CONFIG_UCW_TLS */
119
120 #else /* !CONFIG_UCW_THREADS */
121
122 struct ucwlib_context ucwlib_default_context;
123
124 #endif
125
126 #ifdef TEST
127
128 int main(void)
129 {
130   ucwlib_lock();
131   ucwlib_unlock();
132   msg(L_INFO, "tid=%d", ucwlib_thread_id(ucwlib_thread_context()));
133   return 0;
134 }
135
136 #endif