3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
12 #if (NGX_HAVE_ATOMIC_OPS)
15 static void ngx_shmtx_wakeup(ngx_shmtx_t
*mtx
);
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) {
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
,
47 ngx_shmtx_destroy(ngx_shmtx_t
*mtx
)
49 #if (NGX_HAVE_POSIX_SEM)
52 if (sem_destroy(&mtx
->sem
) == -1) {
53 ngx_log_error(NGX_LOG_ALERT
, ngx_cycle
->log
, ngx_errno
,
54 "sem_destroy() failed");
63 ngx_shmtx_trylock(ngx_shmtx_t
*mtx
)
65 return (*mtx
->lock
== 0 && ngx_atomic_cmp_set(mtx
->lock
, 0, ngx_pid
));
70 ngx_shmtx_lock(ngx_shmtx_t
*mtx
)
74 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, ngx_cycle
->log
, 0, "shmtx lock");
78 if (*mtx
->lock
== 0 && ngx_atomic_cmp_set(mtx
->lock
, 0, ngx_pid
)) {
84 for (n
= 1; n
< mtx
->spin
; n
<<= 1) {
86 for (i
= 0; i
< n
; i
++) {
91 && ngx_atomic_cmp_set(mtx
->lock
, 0, ngx_pid
))
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
)) {
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) {
115 if (err
!= NGX_EINTR
) {
116 ngx_log_error(NGX_LOG_ALERT
, ngx_cycle
->log
, err
,
117 "sem_wait() failed while waiting on shmtx");
122 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, ngx_cycle
->log
, 0,
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
);
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
);
164 ngx_shmtx_wakeup(ngx_shmtx_t
*mtx
)
166 #if (NGX_HAVE_POSIX_SEM)
167 ngx_atomic_uint_t wait
;
169 if (!mtx
->semaphore
) {
181 if (ngx_atomic_cmp_set(mtx
->wait
, wait
, wait
- 1)) {
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");
202 ngx_shmtx_create(ngx_shmtx_t
*mtx
, ngx_shmtx_sh_t
*addr
, u_char
*name
)
206 if (ngx_strcmp(name
, mtx
->name
) == 0) {
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
);
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
);
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
);
245 ngx_shmtx_trylock(ngx_shmtx_t
*mtx
)
249 err
= ngx_trylock_fd(mtx
->fd
);
255 if (err
== NGX_EAGAIN
) {
259 #if __osf__ /* Tru64 UNIX */
261 if (err
== NGX_EACCESS
) {
267 ngx_log_abort(err
, ngx_trylock_fd_n
" %s failed", mtx
->name
);
274 ngx_shmtx_lock(ngx_shmtx_t
*mtx
)
278 err
= ngx_lock_fd(mtx
->fd
);
284 ngx_log_abort(err
, ngx_lock_fd_n
" %s failed", mtx
->name
);
289 ngx_shmtx_unlock(ngx_shmtx_t
*mtx
)
293 err
= ngx_unlock_fd(mtx
->fd
);
299 ngx_log_abort(err
, ngx_unlock_fd_n
" %s failed", mtx
->name
);
304 ngx_shmtx_force_unlock(ngx_shmtx_t
*mtx
, ngx_pid_t pid
)