]> mj.ucw.cz Git - libucw.git/blob - ucw/threads.c
Implemented a new growing array module
[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 #ifdef CONFIG_UCW_TLS
71
72 __thread struct ucwlib_context ucwlib_context;
73
74 int
75 ucwlib_thread_id(struct ucwlib_context *c)
76 {
77   if (!c->_thread_id)
78     c->_thread_id = ucwlib_tid();
79   return c->_thread_id;
80 }
81
82 #else
83
84 static pthread_key_t ucwlib_context_key;
85
86 static void
87 ucwlib_free_thread_context(void *p)
88 {
89   xfree(p);
90 }
91
92 static void CONSTRUCTOR
93 ucwlib_threads_init(void)
94 {
95   if (pthread_key_create(&ucwlib_context_key, ucwlib_free_thread_context) < 0)
96     die("Cannot create pthread_key: %m");
97   pthread_mutex_init(&ucwlib_master_mutex, NULL);
98 }
99
100 struct ucwlib_context *
101 ucwlib_thread_context(void)
102 {
103   struct ucwlib_context *c = pthread_getspecific(ucwlib_context_key);
104   if (!c)
105     {
106       c = xmalloc_zero(sizeof(*c));
107       c->_thread_id = ucwlib_tid();
108       pthread_setspecific(ucwlib_context_key, c);
109     }
110   return c;
111 }
112
113 #endif /* CONFIG_UCW_TLS */
114
115 #else /* !CONFIG_UCW_THREADS */
116
117 struct ucwlib_context default_ucwlib_context;
118
119 #endif
120
121 #ifdef TEST
122
123 int main(void)
124 {
125   ucwlib_lock();
126   ucwlib_unlock();
127   msg(L_INFO, "tid=%d", ucwlib_thread_id(ucwlib_thread_context()));
128   return 0;
129 }
130
131 #endif