Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_shmtx.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 
11 
12 #if (NGX_HAVE_ATOMIC_OPS)
13 
14 
15 static void ngx_shmtx_wakeup(ngx_shmtx_t *mtx);
16 
17 
19 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
20 {
21  mtx->lock = &addr->lock;
22 
23  if (mtx->spin == (ngx_uint_t) -1) {
24  return NGX_OK;
25  }
26 
27  mtx->spin = 2048;
28 
29 #if (NGX_HAVE_POSIX_SEM)
30 
31  mtx->wait = &addr->wait;
32 
33  if (sem_init(&mtx->sem, 1, 0) == -1) {
35  "sem_init() failed");
36  } else {
37  mtx->semaphore = 1;
38  }
39 
40 #endif
41 
42  return NGX_OK;
43 }
44 
45 
46 void
48 {
49 #if (NGX_HAVE_POSIX_SEM)
50 
51  if (mtx->semaphore) {
52  if (sem_destroy(&mtx->sem) == -1) {
54  "sem_destroy() failed");
55  }
56  }
57 
58 #endif
59 }
60 
61 
64 {
65  return (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid));
66 }
67 
68 
69 void
71 {
72  ngx_uint_t i, n;
73 
74  ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock");
75 
76  for ( ;; ) {
77 
78  if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
79  return;
80  }
81 
82  if (ngx_ncpu > 1) {
83 
84  for (n = 1; n < mtx->spin; n <<= 1) {
85 
86  for (i = 0; i < n; i++) {
87  ngx_cpu_pause();
88  }
89 
90  if (*mtx->lock == 0
91  && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))
92  {
93  return;
94  }
95  }
96  }
97 
98 #if (NGX_HAVE_POSIX_SEM)
99 
100  if (mtx->semaphore) {
101  (void) ngx_atomic_fetch_add(mtx->wait, 1);
102 
103  if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
104  return;
105  }
106 
108  "shmtx wait %uA", *mtx->wait);
109 
110  while (sem_wait(&mtx->sem) == -1) {
111  ngx_err_t err;
112 
113  err = ngx_errno;
114 
115  if (err != NGX_EINTR) {
117  "sem_wait() failed while waiting on shmtx");
118  break;
119  }
120  }
121 
123  "shmtx awoke");
124 
125  continue;
126  }
127 
128 #endif
129 
130  ngx_sched_yield();
131  }
132 }
133 
134 
135 void
137 {
138  if (mtx->spin != (ngx_uint_t) -1) {
139  ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock");
140  }
141 
142  if (ngx_atomic_cmp_set(mtx->lock, ngx_pid, 0)) {
143  ngx_shmtx_wakeup(mtx);
144  }
145 }
146 
147 
150 {
152  "shmtx forced unlock");
153 
154  if (ngx_atomic_cmp_set(mtx->lock, pid, 0)) {
155  ngx_shmtx_wakeup(mtx);
156  return 1;
157  }
158 
159  return 0;
160 }
161 
162 
163 static void
164 ngx_shmtx_wakeup(ngx_shmtx_t *mtx)
165 {
166 #if (NGX_HAVE_POSIX_SEM)
167  ngx_atomic_uint_t wait;
168 
169  if (!mtx->semaphore) {
170  return;
171  }
172 
173  for ( ;; ) {
174 
175  wait = *mtx->wait;
176 
177  if (wait == 0) {
178  return;
179  }
180 
181  if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) {
182  break;
183  }
184  }
185 
187  "shmtx wake %uA", wait);
188 
189  if (sem_post(&mtx->sem) == -1) {
191  "sem_post() failed while wake shmtx");
192  }
193 
194 #endif
195 }
196 
197 
198 #else
199 
200 
201 ngx_int_t
202 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
203 {
204  if (mtx->name) {
205 
206  if (ngx_strcmp(name, mtx->name) == 0) {
207  mtx->name = name;
208  return NGX_OK;
209  }
210 
211  ngx_shmtx_destroy(mtx);
212  }
213 
216 
217  if (mtx->fd == NGX_INVALID_FILE) {
219  ngx_open_file_n " \"%s\" failed", name);
220  return NGX_ERROR;
221  }
222 
223  if (ngx_delete_file(name) == NGX_FILE_ERROR) {
225  ngx_delete_file_n " \"%s\" failed", name);
226  }
227 
228  mtx->name = name;
229 
230  return NGX_OK;
231 }
232 
233 
234 void
236 {
237  if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) {
239  ngx_close_file_n " \"%s\" failed", mtx->name);
240  }
241 }
242 
243 
246 {
247  ngx_err_t err;
248 
249  err = ngx_trylock_fd(mtx->fd);
250 
251  if (err == 0) {
252  return 1;
253  }
254 
255  if (err == NGX_EAGAIN) {
256  return 0;
257  }
258 
259 #if __osf__ /* Tru64 UNIX */
260 
261  if (err == NGX_EACCESS) {
262  return 0;
263  }
264 
265 #endif
266 
267  ngx_log_abort(err, ngx_trylock_fd_n " %s failed", mtx->name);
268 
269  return 0;
270 }
271 
272 
273 void
275 {
276  ngx_err_t err;
277 
278  err = ngx_lock_fd(mtx->fd);
279 
280  if (err == 0) {
281  return;
282  }
283 
284  ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name);
285 }
286 
287 
288 void
290 {
291  ngx_err_t err;
292 
293  err = ngx_unlock_fd(mtx->fd);
294 
295  if (err == 0) {
296  return;
297  }
298 
299  ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
300 }
301 
302 
305 {
306  return 0;
307 }
308 
309 #endif