Mercurial > hg > nginx
comparison src/core/ngx_shmtx.c @ 3909:0daede16d68b
use POSIX semaphores in shmtx instead of sched_yield()
number of spinlock spins are increased twice
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 10 May 2011 11:39:13 +0000 |
parents | 01884449985f |
children | 3f6040cd731e 4919fb357a5d |
comparison
equal
deleted
inserted
replaced
3908:8258eb4c9d25 | 3909:0daede16d68b |
---|---|
14 ngx_int_t | 14 ngx_int_t |
15 ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name) | 15 ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name) |
16 { | 16 { |
17 mtx->lock = addr; | 17 mtx->lock = addr; |
18 | 18 |
19 if (mtx->spin == (ngx_uint_t) -1) { | |
20 return NGX_OK; | |
21 } | |
22 | |
23 mtx->spin = 2048; | |
24 | |
25 #if (NGX_HAVE_POSIX_SEM) | |
26 | |
27 if (sem_init(&mtx->sem, 1, 0) == -1) { | |
28 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, | |
29 "sem_init() failed"); | |
30 } else { | |
31 mtx->semaphore = 1; | |
32 } | |
33 | |
34 #endif | |
35 | |
19 return NGX_OK; | 36 return NGX_OK; |
20 } | 37 } |
38 | |
39 | |
40 void | |
41 ngx_shmtx_destory(ngx_shmtx_t *mtx) | |
42 { | |
43 #if (NGX_HAVE_POSIX_SEM) | |
44 | |
45 if (mtx->semaphore) { | |
46 if (sem_destroy(&mtx->sem) == -1) { | |
47 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, | |
48 "sem_destroy() failed"); | |
49 } | |
50 } | |
51 | |
52 #endif | |
53 } | |
54 | |
55 | |
56 ngx_uint_t | |
57 ngx_shmtx_trylock(ngx_shmtx_t *mtx) | |
58 { | |
59 ngx_atomic_uint_t val; | |
60 | |
61 val = *mtx->lock; | |
62 | |
63 return ((val & 0x80000000) == 0 | |
64 && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000)); | |
65 } | |
66 | |
67 | |
68 void | |
69 ngx_shmtx_lock(ngx_shmtx_t *mtx) | |
70 { | |
71 ngx_uint_t i, n; | |
72 ngx_atomic_uint_t val; | |
73 | |
74 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock"); | |
75 | |
76 for ( ;; ) { | |
77 | |
78 val = *mtx->lock; | |
79 | |
80 if ((val & 0x80000000) == 0 | |
81 && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000)) | |
82 { | |
83 return; | |
84 } | |
85 | |
86 if (ngx_ncpu > 1) { | |
87 | |
88 for (n = 1; n < mtx->spin; n <<= 1) { | |
89 | |
90 for (i = 0; i < n; i++) { | |
91 ngx_cpu_pause(); | |
92 } | |
93 | |
94 val = *mtx->lock; | |
95 | |
96 if ((val & 0x80000000) == 0 | |
97 && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000)) | |
98 { | |
99 return; | |
100 } | |
101 } | |
102 } | |
103 | |
104 #if (NGX_HAVE_POSIX_SEM) | |
105 | |
106 if (mtx->semaphore) { | |
107 val = *mtx->lock; | |
108 | |
109 if ((val & 0x80000000) | |
110 && ngx_atomic_cmp_set(mtx->lock, val, val + 1)) | |
111 { | |
112 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, | |
113 "shmtx wait %XA", val); | |
114 | |
115 while (sem_wait(&mtx->sem) == -1) { | |
116 ngx_err_t err; | |
117 | |
118 err = ngx_errno; | |
119 | |
120 if (err != NGX_EINTR) { | |
121 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, | |
122 "sem_wait() failed while waiting on shmtx"); | |
123 break; | |
124 } | |
125 } | |
126 | |
127 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, | |
128 "shmtx awoke"); | |
129 } | |
130 | |
131 continue; | |
132 } | |
133 | |
134 #endif | |
135 | |
136 ngx_sched_yield(); | |
137 } | |
138 } | |
139 | |
140 | |
141 void | |
142 ngx_shmtx_unlock(ngx_shmtx_t *mtx) | |
143 { | |
144 ngx_atomic_uint_t val, old, wait; | |
145 | |
146 if (mtx->spin != (ngx_uint_t) -1) { | |
147 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock"); | |
148 } | |
149 | |
150 for ( ;; ) { | |
151 | |
152 old = *mtx->lock; | |
153 wait = old & 0x7fffffff; | |
154 val = wait ? wait - 1 : 0; | |
155 | |
156 if (ngx_atomic_cmp_set(mtx->lock, old, val)) { | |
157 break; | |
158 } | |
159 } | |
160 | |
161 #if (NGX_HAVE_POSIX_SEM) | |
162 | |
163 if (wait == 0 || !mtx->semaphore) { | |
164 return; | |
165 } | |
166 | |
167 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, | |
168 "shmtx wake %XA", old); | |
169 | |
170 if (sem_post(&mtx->sem) == -1) { | |
171 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, | |
172 "sem_post() failed while wake shmtx"); | |
173 } | |
174 | |
175 #endif | |
176 } | |
177 | |
21 | 178 |
22 #else | 179 #else |
23 | 180 |
24 | 181 |
25 ngx_int_t | 182 ngx_int_t |
63 ngx_close_file_n " \"%s\" failed", mtx->name); | 220 ngx_close_file_n " \"%s\" failed", mtx->name); |
64 } | 221 } |
65 } | 222 } |
66 | 223 |
67 | 224 |
68 #endif | 225 ngx_uint_t |
226 ngx_shmtx_trylock(ngx_shmtx_t *mtx) | |
227 { | |
228 ngx_err_t err; | |
229 | |
230 err = ngx_trylock_fd(mtx->fd); | |
231 | |
232 if (err == 0) { | |
233 return 1; | |
234 } | |
235 | |
236 if (err == NGX_EAGAIN) { | |
237 return 0; | |
238 } | |
239 | |
240 #if __osf__ /* Tru64 UNIX */ | |
241 | |
242 if (err == NGX_EACCESS) { | |
243 return 0; | |
244 } | |
245 | |
246 #endif | |
247 | |
248 ngx_log_abort(err, ngx_trylock_fd_n " %s failed", mtx->name); | |
249 | |
250 return 0; | |
251 } | |
252 | |
253 | |
254 void | |
255 ngx_shmtx_lock(ngx_shmtx_t *mtx) | |
256 { | |
257 ngx_err_t err; | |
258 | |
259 err = ngx_lock_fd(mtx->fd); | |
260 | |
261 if (err == 0) { | |
262 return; | |
263 } | |
264 | |
265 ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name); | |
266 } | |
267 | |
268 | |
269 void | |
270 ngx_shmtx_unlock(ngx_shmtx_t *mtx) | |
271 { | |
272 ngx_err_t err; | |
273 | |
274 err = ngx_unlock_fd(mtx->fd); | |
275 | |
276 if (err == 0) { | |
277 return; | |
278 } | |
279 | |
280 ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name); | |
281 } | |
282 | |
283 #endif |