Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 
0011 
0012 #if (NGX_HAVE_ATOMIC_OPS)
0013 
0014 
0015 static void ngx_shmtx_wakeup(ngx_shmtx_t *mtx);
0016 
0017 
0018 ngx_int_t
0019 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
0020 {
0021     mtx->lock = &addr->lock;
0022 
0023     if (mtx->spin == (ngx_uint_t) -1) {
0024         return NGX_OK;
0025     }
0026 
0027     mtx->spin = 2048;
0028 
0029 #if (NGX_HAVE_POSIX_SEM)
0030 
0031     mtx->wait = &addr->wait;
0032 
0033     if (sem_init(&mtx->sem, 1, 0) == -1) {
0034         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
0035                       "sem_init() failed");
0036     } else {
0037         mtx->semaphore = 1;
0038     }
0039 
0040 #endif
0041 
0042     return NGX_OK;
0043 }
0044 
0045 
0046 void
0047 ngx_shmtx_destroy(ngx_shmtx_t *mtx)
0048 {
0049 #if (NGX_HAVE_POSIX_SEM)
0050 
0051     if (mtx->semaphore) {
0052         if (sem_destroy(&mtx->sem) == -1) {
0053             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
0054                           "sem_destroy() failed");
0055         }
0056     }
0057 
0058 #endif
0059 }
0060 
0061 
0062 ngx_uint_t
0063 ngx_shmtx_trylock(ngx_shmtx_t *mtx)
0064 {
0065     return (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid));
0066 }
0067 
0068 
0069 void
0070 ngx_shmtx_lock(ngx_shmtx_t *mtx)
0071 {
0072     ngx_uint_t         i, n;
0073 
0074     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock");
0075 
0076     for ( ;; ) {
0077 
0078         if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
0079             return;
0080         }
0081 
0082         if (ngx_ncpu > 1) {
0083 
0084             for (n = 1; n < mtx->spin; n <<= 1) {
0085 
0086                 for (i = 0; i < n; i++) {
0087                     ngx_cpu_pause();
0088                 }
0089 
0090                 if (*mtx->lock == 0
0091                     && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))
0092                 {
0093                     return;
0094                 }
0095             }
0096         }
0097 
0098 #if (NGX_HAVE_POSIX_SEM)
0099 
0100         if (mtx->semaphore) {
0101             (void) ngx_atomic_fetch_add(mtx->wait, 1);
0102 
0103             if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) {
0104                 (void) ngx_atomic_fetch_add(mtx->wait, -1);
0105                 return;
0106             }
0107 
0108             ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
0109                            "shmtx wait %uA", *mtx->wait);
0110 
0111             while (sem_wait(&mtx->sem) == -1) {
0112                 ngx_err_t  err;
0113 
0114                 err = ngx_errno;
0115 
0116                 if (err != NGX_EINTR) {
0117                     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
0118                                   "sem_wait() failed while waiting on shmtx");
0119                     break;
0120                 }
0121             }
0122 
0123             ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
0124                            "shmtx awoke");
0125 
0126             continue;
0127         }
0128 
0129 #endif
0130 
0131         ngx_sched_yield();
0132     }
0133 }
0134 
0135 
0136 void
0137 ngx_shmtx_unlock(ngx_shmtx_t *mtx)
0138 {
0139     if (mtx->spin != (ngx_uint_t) -1) {
0140         ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock");
0141     }
0142 
0143     if (ngx_atomic_cmp_set(mtx->lock, ngx_pid, 0)) {
0144         ngx_shmtx_wakeup(mtx);
0145     }
0146 }
0147 
0148 
0149 ngx_uint_t
0150 ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
0151 {
0152     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
0153                    "shmtx forced unlock");
0154 
0155     if (ngx_atomic_cmp_set(mtx->lock, pid, 0)) {
0156         ngx_shmtx_wakeup(mtx);
0157         return 1;
0158     }
0159 
0160     return 0;
0161 }
0162 
0163 
0164 static void
0165 ngx_shmtx_wakeup(ngx_shmtx_t *mtx)
0166 {
0167 #if (NGX_HAVE_POSIX_SEM)
0168     ngx_atomic_uint_t  wait;
0169 
0170     if (!mtx->semaphore) {
0171         return;
0172     }
0173 
0174     for ( ;; ) {
0175 
0176         wait = *mtx->wait;
0177 
0178         if ((ngx_atomic_int_t) wait <= 0) {
0179             return;
0180         }
0181 
0182         if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) {
0183             break;
0184         }
0185     }
0186 
0187     ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
0188                    "shmtx wake %uA", wait);
0189 
0190     if (sem_post(&mtx->sem) == -1) {
0191         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
0192                       "sem_post() failed while wake shmtx");
0193     }
0194 
0195 #endif
0196 }
0197 
0198 
0199 #else
0200 
0201 
0202 ngx_int_t
0203 ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
0204 {
0205     if (mtx->name) {
0206 
0207         if (ngx_strcmp(name, mtx->name) == 0) {
0208             mtx->name = name;
0209             return NGX_OK;
0210         }
0211 
0212         ngx_shmtx_destroy(mtx);
0213     }
0214 
0215     mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN,
0216                             NGX_FILE_DEFAULT_ACCESS);
0217 
0218     if (mtx->fd == NGX_INVALID_FILE) {
0219         ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,
0220                       ngx_open_file_n " \"%s\" failed", name);
0221         return NGX_ERROR;
0222     }
0223 
0224     if (ngx_delete_file(name) == NGX_FILE_ERROR) {
0225         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
0226                       ngx_delete_file_n " \"%s\" failed", name);
0227     }
0228 
0229     mtx->name = name;
0230 
0231     return NGX_OK;
0232 }
0233 
0234 
0235 void
0236 ngx_shmtx_destroy(ngx_shmtx_t *mtx)
0237 {
0238     if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) {
0239         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
0240                       ngx_close_file_n " \"%s\" failed", mtx->name);
0241     }
0242 }
0243 
0244 
0245 ngx_uint_t
0246 ngx_shmtx_trylock(ngx_shmtx_t *mtx)
0247 {
0248     ngx_err_t  err;
0249 
0250     err = ngx_trylock_fd(mtx->fd);
0251 
0252     if (err == 0) {
0253         return 1;
0254     }
0255 
0256     if (err == NGX_EAGAIN) {
0257         return 0;
0258     }
0259 
0260 #if __osf__ /* Tru64 UNIX */
0261 
0262     if (err == NGX_EACCES) {
0263         return 0;
0264     }
0265 
0266 #endif
0267 
0268     ngx_log_abort(err, ngx_trylock_fd_n " %s failed", mtx->name);
0269 
0270     return 0;
0271 }
0272 
0273 
0274 void
0275 ngx_shmtx_lock(ngx_shmtx_t *mtx)
0276 {
0277     ngx_err_t  err;
0278 
0279     err = ngx_lock_fd(mtx->fd);
0280 
0281     if (err == 0) {
0282         return;
0283     }
0284 
0285     ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name);
0286 }
0287 
0288 
0289 void
0290 ngx_shmtx_unlock(ngx_shmtx_t *mtx)
0291 {
0292     ngx_err_t  err;
0293 
0294     err = ngx_unlock_fd(mtx->fd);
0295 
0296     if (err == 0) {
0297         return;
0298     }
0299 
0300     ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
0301 }
0302 
0303 
0304 ngx_uint_t
0305 ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)
0306 {
0307     return 0;
0308 }
0309 
0310 #endif