Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / core / ngx_shmtx.c
bloba62999f33937b63f4504d2adcd4a84dcf0b5bdbe
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
12 #if (NGX_HAVE_ATOMIC_OPS)
15 static void ngx_shmtx_wakeup(ngx_shmtx_t *mtx);
18 ngx_int_t
19 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
21 mtx->lock = &addr->lock;
23 if (mtx->spin == (ngx_uint_t) -1) {
24 return NGX_OK;
27 mtx->spin = 2048;
29 #if (NGX_HAVE_POSIX_SEM)
31 mtx->wait = &addr->wait;
33 if (sem_init(&mtx->sem, 1, 0) == -1) {
34 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
35 "sem_init() failed");
36 } else {
37 mtx->semaphore = 1;
40 #endif
42 return NGX_OK;
46 void
47 ngx_shmtx_destroy(ngx_shmtx_t *mtx)
49 #if (NGX_HAVE_POSIX_SEM)
51 if (mtx->semaphore) {
52 if (sem_destroy(&mtx->sem) == -1) {
53 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
54 "sem_destroy() failed");
58 #endif
62 ngx_uint_t
63 ngx_shmtx_trylock(ngx_shmtx_t *mtx)
65 return (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid));
69 void
70 ngx_shmtx_lock(ngx_shmtx_t *mtx)
72 ngx_uint_t i, n;
74 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock");
76 for ( ;; ) {
78 if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
79 return;
82 if (ngx_ncpu > 1) {
84 for (n = 1; n < mtx->spin; n <<= 1) {
86 for (i = 0; i < n; i++) {
87 ngx_cpu_pause();
90 if (*mtx->lock == 0
91 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))
93 return;
98 #if (NGX_HAVE_POSIX_SEM)
100 if (mtx->semaphore) {
101 (void) ngx_atomic_fetch_add(mtx->wait, 1);
103 if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
104 return;
107 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
108 "shmtx wait %uA", *mtx->wait);
110 while (sem_wait(&mtx->sem) == -1) {
111 ngx_err_t err;
113 err = ngx_errno;
115 if (err != NGX_EINTR) {
116 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
117 "sem_wait() failed while waiting on shmtx");
118 break;
122 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
123 "shmtx awoke");
125 continue;
128 #endif
130 ngx_sched_yield();
135 void
136 ngx_shmtx_unlock(ngx_shmtx_t *mtx)
138 if (mtx->spin != (ngx_uint_t) -1) {
139 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock");
142 if (ngx_atomic_cmp_set(mtx->lock, ngx_pid, 0)) {
143 ngx_shmtx_wakeup(mtx);
148 ngx_uint_t
149 ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
151 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
152 "shmtx forced unlock");
154 if (ngx_atomic_cmp_set(mtx->lock, pid, 0)) {
155 ngx_shmtx_wakeup(mtx);
156 return 1;
159 return 0;
163 static void
164 ngx_shmtx_wakeup(ngx_shmtx_t *mtx)
166 #if (NGX_HAVE_POSIX_SEM)
167 ngx_atomic_uint_t wait;
169 if (!mtx->semaphore) {
170 return;
173 for ( ;; ) {
175 wait = *mtx->wait;
177 if (wait == 0) {
178 return;
181 if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) {
182 break;
186 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
187 "shmtx wake %uA", wait);
189 if (sem_post(&mtx->sem) == -1) {
190 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
191 "sem_post() failed while wake shmtx");
194 #endif
198 #else
201 ngx_int_t
202 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
204 if (mtx->name) {
206 if (ngx_strcmp(name, mtx->name) == 0) {
207 mtx->name = name;
208 return NGX_OK;
211 ngx_shmtx_destroy(mtx);
214 mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN,
215 NGX_FILE_DEFAULT_ACCESS);
217 if (mtx->fd == NGX_INVALID_FILE) {
218 ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,
219 ngx_open_file_n " \"%s\" failed", name);
220 return NGX_ERROR;
223 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
224 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
225 ngx_delete_file_n " \"%s\" failed", name);
228 mtx->name = name;
230 return NGX_OK;
234 void
235 ngx_shmtx_destroy(ngx_shmtx_t *mtx)
237 if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) {
238 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
239 ngx_close_file_n " \"%s\" failed", mtx->name);
244 ngx_uint_t
245 ngx_shmtx_trylock(ngx_shmtx_t *mtx)
247 ngx_err_t err;
249 err = ngx_trylock_fd(mtx->fd);
251 if (err == 0) {
252 return 1;
255 if (err == NGX_EAGAIN) {
256 return 0;
259 #if __osf__ /* Tru64 UNIX */
261 if (err == NGX_EACCESS) {
262 return 0;
265 #endif
267 ngx_log_abort(err, ngx_trylock_fd_n " %s failed", mtx->name);
269 return 0;
273 void
274 ngx_shmtx_lock(ngx_shmtx_t *mtx)
276 ngx_err_t err;
278 err = ngx_lock_fd(mtx->fd);
280 if (err == 0) {
281 return;
284 ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name);
288 void
289 ngx_shmtx_unlock(ngx_shmtx_t *mtx)
291 ngx_err_t err;
293 err = ngx_unlock_fd(mtx->fd);
295 if (err == 0) {
296 return;
299 ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
303 ngx_uint_t
304 ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
306 return 0;
309 #endif