upstream nginx-0.7.31
[nginx.git] / nginx / src / os / unix / ngx_pthread_thread.c
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
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)
21 {
22     int  err;
23
24     if (nthreads >= max_threads) {
25         ngx_log_error(NGX_LOG_CRIT, log, 0,
26                       "no more than %ui threads can be created", max_threads);
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,
38                    "thread is created: " NGX_TID_T_FMT, *tid);
39
40     nthreads++;
41
42     return err;
43 }
44
45
46 ngx_int_t
47 ngx_init_threads(int n, size_t size, ngx_cycle_t *cycle)
48 {
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
75 ngx_mutex_t *
76 ngx_mutex_init(ngx_log_t *log, ngx_uint_t flags)
77 {
78     int           err;
79     ngx_mutex_t  *m;
80
81     m = ngx_alloc(sizeof(ngx_mutex_t), log);
82     if (m == NULL) {
83         return NULL;
84     }
85
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
100 void
101 ngx_mutex_destroy(ngx_mutex_t *m)
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,
109                       "pthread_mutex_destroy(%p) failed", m);
110     }
111
112     ngx_free(m);
113 }
114
115
116 void
117 ngx_mutex_lock(ngx_mutex_t *m)
118 {
119     int  err;
120
121     if (!ngx_threaded) {
122         return;
123     }
124
125     ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "lock mutex %p", m);
126
127     err = pthread_mutex_lock(&m->mutex);
128
129     if (err != 0) {
130         ngx_log_error(NGX_LOG_ALERT, m->log, err,
131                       "pthread_mutex_lock(%p) failed", m);
132         ngx_abort();
133     }
134
135     ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
136
137     return;
138 }
139
140
141 ngx_int_t
142 ngx_mutex_trylock(ngx_mutex_t *m)
143 {
144     int  err;
145
146     if (!ngx_threaded) {
147         return NGX_OK;
148     }
149
150     ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "try lock mutex %p", m);
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,
160                       "pthread_mutex_trylock(%p) failed", m);
161         ngx_abort();
162     }
163
164     ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
165
166     return NGX_OK;
167 }
168
169
170 void
171 ngx_mutex_unlock(ngx_mutex_t *m)
172 {
173     int  err;
174
175     if (!ngx_threaded) {
176         return;
177     }
178
179     ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "unlock mutex %p", m);
180
181     err = pthread_mutex_unlock(&m->mutex);
182
183     if (err != 0) {
184         ngx_log_error(NGX_LOG_ALERT, m->log, err,
185                       "pthread_mutex_unlock(%p) failed", m);
186         ngx_abort();
187     }
188
189     ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is unlocked", m);
190
191     return;
192 }
193
194
195 ngx_cond_t *
196 ngx_cond_init(ngx_log_t *log)
197 {
198     int          err;
199     ngx_cond_t  *cv;
200
201     cv = ngx_alloc(sizeof(ngx_cond_t), log);
202     if (cv == NULL) {
203         return NULL;
204     }
205
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
220 void
221 ngx_cond_destroy(ngx_cond_t *cv)
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,
229                       "pthread_cond_destroy(%p) failed", cv);
230     }
231
232     ngx_free(cv);
233 }
234
235
236 ngx_int_t
237 ngx_cond_wait(ngx_cond_t *cv, ngx_mutex_t *m)
238 {
239     int  err;
240
241     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p wait", cv);
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,
247                       "pthread_cond_wait(%p) failed", cv);
248         return NGX_ERROR;
249     }
250
251     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is waked up", cv);
252
253     ngx_log_debug1(NGX_LOG_DEBUG_MUTEX, m->log, 0, "mutex %p is locked", m);
254
255     return NGX_OK;
256 }
257
258
259 ngx_int_t
260 ngx_cond_signal(ngx_cond_t *cv)
261 {
262     int  err;
263
264     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p to signal", cv);
265
266     err = pthread_cond_signal(&cv->cond);
267
268     if (err != 0) {
269         ngx_log_error(NGX_LOG_ALERT, cv->log, err,
270                       "pthread_cond_signal(%p) failed", cv);
271         return NGX_ERROR;
272     }
273
274     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->log, 0, "cv %p is signaled", cv);
275
276     return NGX_OK;
277 }