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
|
|
78 if (!(m = ngx_alloc(sizeof(ngx_mutex_t), log))) {
|
|
79 return NULL;
|
|
80 }
|
|
81
|
|
82 m->log = log;
|
|
83
|
|
84 err = pthread_mutex_init(&m->mutex, NULL);
|
|
85
|
|
86 if (err != 0) {
|
|
87 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
|
88 "pthread_mutex_init() failed");
|
|
89 return NULL;
|
|
90 }
|
|
91
|
|
92 return m;
|
|
93 }
|
|
94
|
|
95
|
|
96 void ngx_mutex_destroy(ngx_mutex_t *m)
|
|
97 {
|
|
98 int err;
|
|
99
|
|
100 err = pthread_mutex_destroy(&m->mutex);
|
|
101
|
|
102 if (err != 0) {
|
|
103 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
104 "pthread_mutex_destroy(%p) failed", m);
|
0
|
105 }
|
|
106
|
|
107 ngx_free(m);
|
|
108 }
|
|
109
|
|
110
|
|
111 ngx_int_t ngx_mutex_lock(ngx_mutex_t *m)
|
|
112 {
|
|
113 int err;
|
|
114
|
|
115 if (!ngx_threaded) {
|
|
116 return NGX_OK;
|
|
117 }
|
|
118
|
10
|
119 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "lock mutex %p", m);
|
0
|
120
|
|
121 err = pthread_mutex_lock(&m->mutex);
|
|
122
|
|
123 if (err != 0) {
|
|
124 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
125 "pthread_mutex_lock(%p) failed", m);
|
0
|
126 return NGX_ERROR;
|
|
127 }
|
|
128
|
10
|
129 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
|
0
|
130
|
|
131 return NGX_OK;
|
|
132 }
|
|
133
|
|
134
|
|
135 ngx_int_t ngx_mutex_trylock(ngx_mutex_t *m)
|
|
136 {
|
|
137 int err;
|
|
138
|
|
139 if (!ngx_threaded) {
|
|
140 return NGX_OK;
|
|
141 }
|
|
142
|
10
|
143 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "try lock mutex %p", m);
|
0
|
144
|
|
145 err = pthread_mutex_trylock(&m->mutex);
|
|
146
|
|
147 if (err == NGX_EBUSY) {
|
|
148 return NGX_AGAIN;
|
|
149 }
|
|
150
|
|
151 if (err != 0) {
|
|
152 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
153 "pthread_mutex_trylock(%p) failed", m);
|
0
|
154 return NGX_ERROR;
|
|
155 }
|
|
156
|
10
|
157 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
|
0
|
158
|
|
159 return NGX_OK;
|
|
160 }
|
|
161
|
|
162
|
|
163 ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m)
|
|
164 {
|
|
165 int err;
|
|
166
|
|
167 if (!ngx_threaded) {
|
|
168 return NGX_OK;
|
|
169 }
|
|
170
|
10
|
171 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "unlock mutex %p", m);
|
0
|
172
|
|
173 err = pthread_mutex_unlock(&m->mutex);
|
|
174
|
|
175 if (err != 0) {
|
|
176 ngx_log_error(NGX_LOG_ALERT, m->log, err,
|
10
|
177 "pthread_mutex_unlock(%p) failed", m);
|
0
|
178 return NGX_ERROR;
|
|
179 }
|
|
180
|
10
|
181 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is unlocked", m);
|
0
|
182
|
|
183 return NGX_OK;
|
|
184 }
|
|
185
|
|
186
|
|
187 ngx_cond_t *ngx_cond_init(ngx_log_t *log)
|
|
188 {
|
|
189 int err;
|
|
190 ngx_cond_t *cv;
|
|
191
|
|
192 if (!(cv = ngx_alloc(sizeof(ngx_cond_t), log))) {
|
|
193 return NULL;
|
|
194 }
|
|
195
|
|
196 cv->log = log;
|
|
197
|
|
198 err = pthread_cond_init(&cv->cond, NULL);
|
|
199
|
|
200 if (err != 0) {
|
|
201 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
|
202 "pthread_cond_init() failed");
|
|
203 return NULL;
|
|
204 }
|
|
205
|
|
206 return cv;
|
|
207 }
|
|
208
|
|
209
|
|
210 void ngx_cond_destroy(ngx_cond_t *cv)
|
|
211 {
|
|
212 int err;
|
|
213
|
|
214 err = pthread_cond_destroy(&cv->cond);
|
|
215
|
|
216 if (err != 0) {
|
|
217 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
10
|
218 "pthread_cond_destroy(%p) failed", cv);
|
0
|
219 }
|
|
220
|
|
221 ngx_free(cv);
|
|
222 }
|
|
223
|
|
224
|
|
225 ngx_int_t ngx_cond_wait(ngx_cond_t *cv, ngx_mutex_t *m)
|
|
226 {
|
|
227 int err;
|
|
228
|
10
|
229 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p wait", cv);
|
0
|
230
|
|
231 err = pthread_cond_wait(&cv->cond, &m->mutex);
|
|
232
|
|
233 if (err != 0) {
|
|
234 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
10
|
235 "pthread_cond_wait(%p) failed", cv);
|
0
|
236 return NGX_ERROR;
|
|
237 }
|
|
238
|
10
|
239 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is waked up", cv);
|
0
|
240
|
10
|
241 ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
|
0
|
242
|
|
243 return NGX_OK;
|
|
244 }
|
|
245
|
|
246
|
|
247 ngx_int_t ngx_cond_signal(ngx_cond_t *cv)
|
|
248 {
|
|
249 int err;
|
|
250
|
10
|
251 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p to signal", cv);
|
0
|
252
|
|
253 err = pthread_cond_signal(&cv->cond);
|
|
254
|
|
255 if (err != 0) {
|
|
256 ngx_log_error(NGX_LOG_ALERT, cv->log, err,
|
10
|
257 "pthread_cond_signal(%p) failed", cv);
|
0
|
258 return NGX_ERROR;
|
|
259 }
|
|
260
|
10
|
261 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is signaled", cv);
|
0
|
262
|
|
263 return NGX_OK;
|
|
264 }
|