xref: /unit/src/nxt_thread.h (revision 0)
1*0Sigor@sysoev.ru 
2*0Sigor@sysoev.ru /*
3*0Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
4*0Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
5*0Sigor@sysoev.ru  */
6*0Sigor@sysoev.ru 
7*0Sigor@sysoev.ru #ifndef _NXT_UNIX_THREAD_H_INCLUDED_
8*0Sigor@sysoev.ru #define _NXT_UNIX_THREAD_H_INCLUDED_
9*0Sigor@sysoev.ru 
10*0Sigor@sysoev.ru 
11*0Sigor@sysoev.ru #if (NXT_THREADS)
12*0Sigor@sysoev.ru 
13*0Sigor@sysoev.ru /*
14*0Sigor@sysoev.ru  * Thread Specific Data
15*0Sigor@sysoev.ru  *
16*0Sigor@sysoev.ru  * The interface unifies two TSD implementations: the __thread storage
17*0Sigor@sysoev.ru  * class and pthread specific data.  It works also in non-threaded mode.
18*0Sigor@sysoev.ru  * The interface is optimized for the __thread storage class and non-threaded
19*0Sigor@sysoev.ru  * mode, since the __thread storage is faster and is supported in modern
20*0Sigor@sysoev.ru  * versions of Linux, FreeBSD, Solaris, and MacOSX.  Pthread specific data
21*0Sigor@sysoev.ru  * is considered as a fallback option.
22*0Sigor@sysoev.ru  *
23*0Sigor@sysoev.ru  * The underlining interfaces are different: pthread data must be allocated
24*0Sigor@sysoev.ru  * by hand and may be accessed only by using pointers whereas __thread data
25*0Sigor@sysoev.ru  * allocation is transparent and it is accessed directly.
26*0Sigor@sysoev.ru  *
27*0Sigor@sysoev.ru  * pthread_getspecific() is usually faster than pthread_setspecific()
28*0Sigor@sysoev.ru  * (much faster on MacOSX), so there is no nxt_thread_set_data() interface
29*0Sigor@sysoev.ru  * for this reason.  It is better to store frequently alterable thread
30*0Sigor@sysoev.ru  * log pointer in nxt_thread_t, but not in a dedicated key.
31*0Sigor@sysoev.ru  */
32*0Sigor@sysoev.ru 
33*0Sigor@sysoev.ru #if (NXT_HAVE_THREAD_STORAGE_CLASS)
34*0Sigor@sysoev.ru 
35*0Sigor@sysoev.ru #define                                                                       \
36*0Sigor@sysoev.ru nxt_thread_extern_data(type, tsd)                                             \
37*0Sigor@sysoev.ru     NXT_EXPORT extern __thread type  tsd
38*0Sigor@sysoev.ru 
39*0Sigor@sysoev.ru #define                                                                       \
40*0Sigor@sysoev.ru nxt_thread_declare_data(type, tsd)                                            \
41*0Sigor@sysoev.ru     __thread type  tsd
42*0Sigor@sysoev.ru 
43*0Sigor@sysoev.ru #define                                                                       \
44*0Sigor@sysoev.ru nxt_thread_init_data(tsd)
45*0Sigor@sysoev.ru 
46*0Sigor@sysoev.ru #define                                                                       \
47*0Sigor@sysoev.ru nxt_thread_get_data(tsd)                                                      \
48*0Sigor@sysoev.ru     &tsd
49*0Sigor@sysoev.ru 
50*0Sigor@sysoev.ru 
51*0Sigor@sysoev.ru #else /* NXT_HAVE_PTHREAD_SPECIFIC_DATA */
52*0Sigor@sysoev.ru 
53*0Sigor@sysoev.ru /*
54*0Sigor@sysoev.ru  * nxt_thread_get_data() is used as
55*0Sigor@sysoev.ru  *    p = nxt_thread_get_data(tsd),
56*0Sigor@sysoev.ru  * but the tsd address is actually required.  This could be resolved by macro
57*0Sigor@sysoev.ru  *    #define nxt_thread_get_data(tsd)  nxt_thread_get_data_addr(&tsd)
58*0Sigor@sysoev.ru  * or by definition nxt_thread_specific_data_t as an array.
59*0Sigor@sysoev.ru  *
60*0Sigor@sysoev.ru  * On Linux and Solaris pthread_key_t is unsigned integer.
61*0Sigor@sysoev.ru  * On FreeBSD, NetBSD, OpenBSD, and HP-UX pthread_key_t is integer.
62*0Sigor@sysoev.ru  * On MacOSX and AIX pthread_key_t is unsigned long integer.
63*0Sigor@sysoev.ru  * On Cygwin pthread_key_t is pointer to void.
64*0Sigor@sysoev.ru  */
65*0Sigor@sysoev.ru 
66*0Sigor@sysoev.ru typedef struct {
67*0Sigor@sysoev.ru     nxt_atomic_t             key;
68*0Sigor@sysoev.ru     size_t                   size;
69*0Sigor@sysoev.ru } nxt_thread_specific_data_t[1];
70*0Sigor@sysoev.ru 
71*0Sigor@sysoev.ru 
72*0Sigor@sysoev.ru #define                                                                       \
73*0Sigor@sysoev.ru nxt_thread_extern_data(type, tsd)                                             \
74*0Sigor@sysoev.ru     NXT_EXPORT extern nxt_thread_specific_data_t  tsd
75*0Sigor@sysoev.ru 
76*0Sigor@sysoev.ru #define                                                                       \
77*0Sigor@sysoev.ru nxt_thread_declare_data(type, tsd)                                            \
78*0Sigor@sysoev.ru     nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } }
79*0Sigor@sysoev.ru 
80*0Sigor@sysoev.ru NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd);
81*0Sigor@sysoev.ru 
82*0Sigor@sysoev.ru #define                                                                       \
83*0Sigor@sysoev.ru nxt_thread_get_data(tsd)                                                      \
84*0Sigor@sysoev.ru     pthread_getspecific((pthread_key_t) tsd->key)
85*0Sigor@sysoev.ru 
86*0Sigor@sysoev.ru #endif
87*0Sigor@sysoev.ru 
88*0Sigor@sysoev.ru 
89*0Sigor@sysoev.ru typedef void (*nxt_thread_start_t)(void *data);
90*0Sigor@sysoev.ru 
91*0Sigor@sysoev.ru typedef struct {
92*0Sigor@sysoev.ru     nxt_thread_start_t       start;
93*0Sigor@sysoev.ru     void                     *data;
94*0Sigor@sysoev.ru     nxt_event_engine_t       *engine;
95*0Sigor@sysoev.ru     nxt_work_handler_t       exit;
96*0Sigor@sysoev.ru } nxt_thread_link_t;
97*0Sigor@sysoev.ru 
98*0Sigor@sysoev.ru 
99*0Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle,
100*0Sigor@sysoev.ru     nxt_thread_link_t *link);
101*0Sigor@sysoev.ru NXT_EXPORT nxt_thread_t *nxt_thread_init(void);
102*0Sigor@sysoev.ru NXT_EXPORT void nxt_thread_exit(nxt_thread_t *thr);
103*0Sigor@sysoev.ru NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle);
104*0Sigor@sysoev.ru NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle);
105*0Sigor@sysoev.ru 
106*0Sigor@sysoev.ru 
107*0Sigor@sysoev.ru #define                                                                       \
108*0Sigor@sysoev.ru nxt_thread_handle()                                                           \
109*0Sigor@sysoev.ru     pthread_self()
110*0Sigor@sysoev.ru 
111*0Sigor@sysoev.ru 
112*0Sigor@sysoev.ru typedef pthread_mutex_t      nxt_thread_mutex_t;
113*0Sigor@sysoev.ru 
114*0Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx);
115*0Sigor@sysoev.ru NXT_EXPORT void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx);
116*0Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx);
117*0Sigor@sysoev.ru NXT_EXPORT nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx);
118*0Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx);
119*0Sigor@sysoev.ru 
120*0Sigor@sysoev.ru 
121*0Sigor@sysoev.ru typedef pthread_cond_t       nxt_thread_cond_t;
122*0Sigor@sysoev.ru 
123*0Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond);
124*0Sigor@sysoev.ru NXT_EXPORT void nxt_thread_cond_destroy(nxt_thread_cond_t *cond);
125*0Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond);
126*0Sigor@sysoev.ru NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond,
127*0Sigor@sysoev.ru     nxt_thread_mutex_t *mtx, nxt_nsec_t timeout);
128*0Sigor@sysoev.ru 
129*0Sigor@sysoev.ru 
130*0Sigor@sysoev.ru #else /* !(NXT_THREADS) */
131*0Sigor@sysoev.ru 
132*0Sigor@sysoev.ru #define                                                                       \
133*0Sigor@sysoev.ru nxt_thread_extern_data(type, tsd)                                             \
134*0Sigor@sysoev.ru     NXT_EXPORT extern type  tsd
135*0Sigor@sysoev.ru 
136*0Sigor@sysoev.ru #define                                                                       \
137*0Sigor@sysoev.ru nxt_thread_declare_data(type, tsd)                                            \
138*0Sigor@sysoev.ru     type  tsd
139*0Sigor@sysoev.ru 
140*0Sigor@sysoev.ru #define                                                                       \
141*0Sigor@sysoev.ru nxt_thread_init_data(tsd)
142*0Sigor@sysoev.ru 
143*0Sigor@sysoev.ru #define                                                                       \
144*0Sigor@sysoev.ru nxt_thread_get_data(tsd)                                                      \
145*0Sigor@sysoev.ru     &tsd
146*0Sigor@sysoev.ru 
147*0Sigor@sysoev.ru #endif /* NXT_THREADS */
148*0Sigor@sysoev.ru 
149*0Sigor@sysoev.ru 
150*0Sigor@sysoev.ru #if (NXT_HAVE_PTHREAD_YIELD)
151*0Sigor@sysoev.ru #define                                                                       \
152*0Sigor@sysoev.ru nxt_thread_yield()                                                            \
153*0Sigor@sysoev.ru     pthread_yield()
154*0Sigor@sysoev.ru 
155*0Sigor@sysoev.ru #elif (NXT_HAVE_PTHREAD_YIELD_NP)
156*0Sigor@sysoev.ru #define                                                                       \
157*0Sigor@sysoev.ru nxt_thread_yield()                                                            \
158*0Sigor@sysoev.ru     pthread_yield_np()
159*0Sigor@sysoev.ru 
160*0Sigor@sysoev.ru #else
161*0Sigor@sysoev.ru #define                                                                       \
162*0Sigor@sysoev.ru nxt_thread_yield()                                                            \
163*0Sigor@sysoev.ru     nxt_sched_yield()
164*0Sigor@sysoev.ru 
165*0Sigor@sysoev.ru #endif
166*0Sigor@sysoev.ru 
167*0Sigor@sysoev.ru 
168*0Sigor@sysoev.ru struct nxt_thread_s {
169*0Sigor@sysoev.ru     nxt_log_t                *log;
170*0Sigor@sysoev.ru     nxt_log_t                main_log;
171*0Sigor@sysoev.ru 
172*0Sigor@sysoev.ru     nxt_tid_t                tid;
173*0Sigor@sysoev.ru     nxt_thread_handle_t      handle;
174*0Sigor@sysoev.ru #if (NXT_THREADS)
175*0Sigor@sysoev.ru     nxt_thread_link_t        *link;
176*0Sigor@sysoev.ru     nxt_thread_pool_t        *thread_pool;
177*0Sigor@sysoev.ru #endif
178*0Sigor@sysoev.ru 
179*0Sigor@sysoev.ru     nxt_thread_time_t        time;
180*0Sigor@sysoev.ru 
181*0Sigor@sysoev.ru     nxt_event_engine_t       *engine;
182*0Sigor@sysoev.ru     nxt_thread_work_queue_t  work_queue;
183*0Sigor@sysoev.ru 
184*0Sigor@sysoev.ru     /*
185*0Sigor@sysoev.ru      * Although pointer to a current fiber should be a property of
186*0Sigor@sysoev.ru      * engine->fibers, its placement here eliminates 2 memory accesses.
187*0Sigor@sysoev.ru      */
188*0Sigor@sysoev.ru     nxt_fiber_t              *fiber;
189*0Sigor@sysoev.ru };
190*0Sigor@sysoev.ru 
191*0Sigor@sysoev.ru 
192*0Sigor@sysoev.ru #endif /* _NXT_UNIX_THREAD_H_INCLUDED_ */
193