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