diff options
Diffstat (limited to 'src/core/ngx_shmtx.c')
-rw-r--r-- | src/core/ngx_shmtx.c | 113 |
1 files changed, 69 insertions, 44 deletions
diff --git a/src/core/ngx_shmtx.c b/src/core/ngx_shmtx.c index 3b429c4f9..5a9242dfe 100644 --- a/src/core/ngx_shmtx.c +++ b/src/core/ngx_shmtx.c @@ -11,10 +11,13 @@ #if (NGX_HAVE_ATOMIC_OPS) +static void ngx_shmtx_wakeup(ngx_shmtx_t *mtx); + + ngx_int_t -ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name) +ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name) { - mtx->lock = addr; + mtx->lock = &addr->lock; if (mtx->spin == (ngx_uint_t) -1) { return NGX_OK; @@ -24,6 +27,8 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name) #if (NGX_HAVE_POSIX_SEM) + mtx->wait = &addr->wait; + if (sem_init(&mtx->sem, 1, 0) == -1) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, "sem_init() failed"); @@ -56,12 +61,7 @@ ngx_shmtx_destory(ngx_shmtx_t *mtx) ngx_uint_t ngx_shmtx_trylock(ngx_shmtx_t *mtx) { - ngx_atomic_uint_t val; - - val = *mtx->lock; - - return ((val & 0x80000000) == 0 - && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000)); + return (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)); } @@ -69,17 +69,12 @@ void ngx_shmtx_lock(ngx_shmtx_t *mtx) { ngx_uint_t i, n; - ngx_atomic_uint_t val; ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock"); for ( ;; ) { - val = *mtx->lock; - - if ((val & 0x80000000) == 0 - && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000)) - { + if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { return; } @@ -91,10 +86,8 @@ ngx_shmtx_lock(ngx_shmtx_t *mtx) ngx_cpu_pause(); } - val = *mtx->lock; - - if ((val & 0x80000000) == 0 - && ngx_atomic_cmp_set(mtx->lock, val, val | 0x80000000)) + if (*mtx->lock == 0 + && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { return; } @@ -104,24 +97,24 @@ ngx_shmtx_lock(ngx_shmtx_t *mtx) #if (NGX_HAVE_POSIX_SEM) if (mtx->semaphore) { - val = *mtx->lock; + ngx_atomic_fetch_add(mtx->wait, 1); - if ((val & 0x80000000) - && ngx_atomic_cmp_set(mtx->lock, val, val + 1)) - { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "shmtx wait %XA", val); + if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { + return; + } - while (sem_wait(&mtx->sem) == -1) { - ngx_err_t err; + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, + "shmtx wait %uA", *mtx->wait); - err = ngx_errno; + while (sem_wait(&mtx->sem) == -1) { + ngx_err_t err; - if (err != NGX_EINTR) { - ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, - "sem_wait() failed while waiting on shmtx"); - break; - } + err = ngx_errno; + + if (err != NGX_EINTR) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, + "sem_wait() failed while waiting on shmtx"); + break; } ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, @@ -141,31 +134,56 @@ ngx_shmtx_lock(ngx_shmtx_t *mtx) void ngx_shmtx_unlock(ngx_shmtx_t *mtx) { - ngx_atomic_uint_t val, old, wait; - if (mtx->spin != (ngx_uint_t) -1) { ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx unlock"); } - for ( ;; ) { + if (ngx_atomic_cmp_set(mtx->lock, ngx_pid, 0)) { + ngx_shmtx_wakeup(mtx); + } +} - old = *mtx->lock; - wait = old & 0x7fffffff; - val = wait ? wait - 1 : 0; - if (ngx_atomic_cmp_set(mtx->lock, old, val)) { - break; - } +ngx_uint_t +ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid) +{ + ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, + "shmtx forced unlock"); + + if (ngx_atomic_cmp_set(mtx->lock, pid, 0)) { + ngx_shmtx_wakeup(mtx); + return 1; } + return 0; +} + + +static void +ngx_shmtx_wakeup(ngx_shmtx_t *mtx) +{ #if (NGX_HAVE_POSIX_SEM) + ngx_atomic_uint_t wait; - if (wait == 0 || !mtx->semaphore) { + if (!mtx->semaphore) { return; } + for ( ;; ) { + + wait = *mtx->wait; + + if (wait == 0) { + return; + } + + if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)) { + break; + } + } + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "shmtx wake %XA", old); + "shmtx wake %uA", wait); if (sem_post(&mtx->sem) == -1) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, @@ -180,7 +198,7 @@ ngx_shmtx_unlock(ngx_shmtx_t *mtx) ngx_int_t -ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name) +ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name) { if (mtx->name) { @@ -280,4 +298,11 @@ ngx_shmtx_unlock(ngx_shmtx_t *mtx) ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name); } + +void +ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid) +{ + /* void */ +} + #endif |