aboutsummaryrefslogtreecommitdiff
path: root/src/core/ngx_shmtx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ngx_shmtx.c')
-rw-r--r--src/core/ngx_shmtx.c113
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