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