0
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
|
4 */
|
|
5
|
|
6
|
|
7 #include <ngx_config.h>
|
|
8 #include <ngx_core.h>
|
|
9
|
|
10
|
|
11 static ngx_uint_t nthreads;
|
|
12 static ngx_uint_t max_threads;
|
|
13
|
|
14
|
|
15 static pthread_attr_t thr_attr;
|
|
16
|
|
17
|
112
|
18 ngx_err_t
|
|
19 ngx_create_thread(ngx_tid_t *tid, ngx_thread_value_t (*func)(void *arg),
|
|
20 void *arg, ngx_log_t *log)
|
0
|
21 {
|
|
22 int err;
|
|
23
|
|
24 if (nthreads >= max_threads) {
|
|
25 ngx_log_error(NGX_LOG_CRIT, log, 0,
|
10
|
26 "no more than %ui threads can be created", max_threads);
|
0
|
27 return NGX_ERROR;
|
|
28 }
|
|
29
|
|
30 err = pthread_create(tid, &thr_attr, func, arg);
|
|
31
|
|
32 if (err != 0) {
|
|
33 ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_create() failed");
|
|
34 return err;
|
|
35 }
|
|
36
|
|
37 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
|
10
|
38 "thread is created: " NGX_TID_T_FMT, *tid);
|
0
|
39
|
|
40 nthreads++;
|
|
41
|
|
42 return err;
|
|
43 }
|
|
44
|
|
45
|
112
|
46 ngx_int_t
|
|
47 ngx_init_threads(int n, size_t size, ngx_cycle_t *cycle)
|
126
|
48 {
|
0
|
49 int err;
|
|
50
|
|
51 max_threads = n;
|
|
52
|
|
53 err = pthread_attr_init(&thr_attr);
|
|
54
|
|
55 if (err != 0) {
|
|
56 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
|
|
57 "pthread_attr_init() failed");
|
|
58 return NGX_ERROR;
|
|
59 }
|
|
60
|
|
61 err = pthread_attr_setstacksize(&thr_attr, size);
|
|
62
|
|
63 if (err != 0) {
|
|
64 ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
|
|
65 "pthread_attr_setstacksize() failed");
|
|
66 return NGX_ERROR;
|
|
67 }
|
|
68
|
|
69 ngx_threaded = 1;
|
|
70
|
|
71 return NGX_OK;
|
|
72 }
|
|
73
|
|
74
|
112
|
75 ngx_mutex_t *
|
|
76 ngx_mutex_init(ngx_log_t *log, ngx_uint_t flags)
|
0
|
77 {
|
|
78 int err;
|
|
79 ngx_mutex_t *m;
|
|
80
|
50
|
81 m = ngx_alloc(sizeof(ngx_mutex_t), log);
|
|
82 if (m == NULL) {
|
0
|
83 return NULL;
|
|
84 }
|
126
|
85
|
0
|
86 m->log = log;
|
|
87
|
|
88 err = pthread_mutex_init(&m->mutex, NULL);
|
|
89
|
|
90 if (err != 0) {
|
|
91 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
|
92 "pthread_mutex_init() failed");
|
|
93 return NULL;
|
|
94 }
|
|
95
|
|
96 return m;
|
|
97 }
|
|
98
|
|
99
|
112
|
100 void
|
|
101 ngx_mutex_destroy(ngx_mutex_t *m)
|
0
|
102 {
|
|
103 int err;
|
|
104
|
|
105 err = pthread_mutex_destroy(&m->mutex);
|
|
106
|
|
107 if (err != 0) {
|
|
108 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
109 "pthread_mutex_destroy(%p) failed", m);
|
0
|
110 }
|
|
111
|
|
112 ngx_free(m);
|
|
113 }
|
|
114
|
|
115
|
112
|
116 void
|
|
117 ngx_mutex_lock(ngx_mutex_t *m)
|
0
|
118 {
|
|
119 int err;
|
|
120
|
|
121 if (!ngx_threaded) {
|
112
|
122 return;
|
0
|
123 }
|
|
124
|
10
|
125 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "lock mutex %p", m);
|
0
|
126
|
|
127 err = pthread_mutex_lock(&m->mutex);
|
|
128
|
|
129 if (err != 0) {
|
|
130 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
131 "pthread_mutex_lock(%p) failed", m);
|
112
|
132 ngx_abort();
|
0
|
133 }
|
|
134
|
10
|
135 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
|
0
|
136
|
112
|
137 return;
|
0
|
138 }
|
|
139
|
|
140
|
112
|
141 ngx_int_t
|
|
142 ngx_mutex_trylock(ngx_mutex_t *m)
|
0
|
143 {
|
|
144 int err;
|
|
145
|
|
146 if (!ngx_threaded) {
|
|
147 return NGX_OK;
|
|
148 }
|
|
149
|
10
|
150 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "try lock mutex %p", m);
|
0
|
151
|
|
152 err = pthread_mutex_trylock(&m->mutex);
|
|
153
|
|
154 if (err == NGX_EBUSY) {
|
|
155 return NGX_AGAIN;
|
|
156 }
|
|
157
|
|
158 if (err != 0) {
|
|
159 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
160 "pthread_mutex_trylock(%p) failed", m);
|
112
|
161 ngx_abort();
|
0
|
162 }
|
|
163
|
10
|
164 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
|
0
|
165
|
|
166 return NGX_OK;
|
|
167 }
|
|
168
|
|
169
|
112
|
170 void
|
|
171 ngx_mutex_unlock(ngx_mutex_t *m)
|
0
|
172 {
|
|
173 int err;
|
|
174
|
|
175 if (!ngx_threaded) {
|
112
|
176 return;
|
0
|
177 }
|
|
178
|
10
|
179 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "unlock mutex %p", m);
|
0
|
180
|
|
181 err = pthread_mutex_unlock(&m->mutex);
|
|
182
|
|
183 if (err != 0) {
|
|
184 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
185 "pthread_mutex_unlock(%p) failed", m);
|
112
|
186 ngx_abort();
|
0
|
187 }
|
|
188
|
10
|
189 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is unlocked", m);
|
0
|
190
|
112
|
191 return;
|
0
|
192 }
|
|
193
|
|
194
|
112
|
195 ngx_cond_t *
|
|
196 ngx_cond_init(ngx_log_t *log)
|
0
|
197 {
|
|
198 int err;
|
|
199 ngx_cond_t *cv;
|
|
200
|
50
|
201 cv = ngx_alloc(sizeof(ngx_cond_t), log);
|
|
202 if (cv == NULL) {
|
0
|
203 return NULL;
|
|
204 }
|
126
|
205
|
0
|
206 cv->log = log;
|
|
207
|
|
208 err = pthread_cond_init(&cv->cond, NULL);
|
|
209
|
|
210 if (err != 0) {
|
|
211 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
|
212 "pthread_cond_init() failed");
|
|
213 return NULL;
|
|
214 }
|
|
215
|
|
216 return cv;
|
|
217 }
|
|
218
|
|
219
|
112
|
220 void
|
|
221 ngx_cond_destroy(ngx_cond_t *cv)
|
0
|
222 {
|
|
223 int err;
|
|
224
|
|
225 err = pthread_cond_destroy(&cv->cond);
|
|
226
|
|
227 if (err != 0) {
|
|
228 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
10
|
229 "pthread_cond_destroy(%p) failed", cv);
|
0
|
230 }
|
|
231
|
|
232 ngx_free(cv);
|
|
233 }
|
|
234
|
|
235
|
112
|
236 ngx_int_t
|
|
237 ngx_cond_wait(ngx_cond_t *cv, ngx_mutex_t *m)
|
0
|
238 {
|
|
239 int err;
|
|
240
|
10
|
241 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p wait", cv);
|
0
|
242
|
|
243 err = pthread_cond_wait(&cv->cond, &m->mutex);
|
|
244
|
|
245 if (err != 0) {
|
|
246 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
10
|
247 "pthread_cond_wait(%p) failed", cv);
|
0
|
248 return NGX_ERROR;
|
|
249 }
|
|
250
|
10
|
251 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is waked up", cv);
|
0
|
252
|
10
|
253 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
|
0
|
254
|
|
255 return NGX_OK;
|
|
256 }
|
|
257
|
|
258
|
112
|
259 ngx_int_t
|
|
260 ngx_cond_signal(ngx_cond_t *cv)
|
0
|
261 {
|
|
262 int err;
|
|
263
|
10
|
264 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p to signal", cv);
|
0
|
265
|
|
266 err = pthread_cond_signal(&cv->cond);
|
|
267
|
|
268 if (err != 0) {
|
|
269 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
10
|
270 "pthread_cond_signal(%p) failed", cv);
|
0
|
271 return NGX_ERROR;
|
|
272 }
|
|
273
|
10
|
274 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is signaled", cv);
|
0
|
275
|
|
276 return NGX_OK;
|
|
277 }
|