src/core/ngx_rwlock.c - nginx source code

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Ruslan Ermilov
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. #if (NGX_HAVE_ATOMIC_OPS)


  8. #define NGX_RWLOCK_SPIN   2048
  9. #define NGX_RWLOCK_WLOCK  ((ngx_atomic_uint_t) -1)


  10. void
  11. ngx_rwlock_wlock(ngx_atomic_t *lock)
  12. {
  13.     ngx_uint_t  i, n;

  14.     for ( ;; ) {

  15.         if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK)) {
  16.             return;
  17.         }

  18.         if (ngx_ncpu > 1) {

  19.             for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) {

  20.                 for (i = 0; i < n; i++) {
  21.                     ngx_cpu_pause();
  22.                 }

  23.                 if (*lock == 0
  24.                     && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK))
  25.                 {
  26.                     return;
  27.                 }
  28.             }
  29.         }

  30.         ngx_sched_yield();
  31.     }
  32. }


  33. void
  34. ngx_rwlock_rlock(ngx_atomic_t *lock)
  35. {
  36.     ngx_uint_t         i, n;
  37.     ngx_atomic_uint_t  readers;

  38.     for ( ;; ) {
  39.         readers = *lock;

  40.         if (readers != NGX_RWLOCK_WLOCK
  41.             && ngx_atomic_cmp_set(lock, readers, readers + 1))
  42.         {
  43.             return;
  44.         }

  45.         if (ngx_ncpu > 1) {

  46.             for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) {

  47.                 for (i = 0; i < n; i++) {
  48.                     ngx_cpu_pause();
  49.                 }

  50.                 readers = *lock;

  51.                 if (readers != NGX_RWLOCK_WLOCK
  52.                     && ngx_atomic_cmp_set(lock, readers, readers + 1))
  53.                 {
  54.                     return;
  55.                 }
  56.             }
  57.         }

  58.         ngx_sched_yield();
  59.     }
  60. }


  61. void
  62. ngx_rwlock_unlock(ngx_atomic_t *lock)
  63. {
  64.     if (*lock == NGX_RWLOCK_WLOCK) {
  65.         (void) ngx_atomic_cmp_set(lock, NGX_RWLOCK_WLOCK, 0);
  66.     } else {
  67.         (void) ngx_atomic_fetch_add(lock, -1);
  68.     }
  69. }


  70. void
  71. ngx_rwlock_downgrade(ngx_atomic_t *lock)
  72. {
  73.     if (*lock == NGX_RWLOCK_WLOCK) {
  74.         *lock = 1;
  75.     }
  76. }


  77. #else

  78. #if (NGX_HTTP_UPSTREAM_ZONE || NGX_STREAM_UPSTREAM_ZONE)

  79. #error ngx_atomic_cmp_set() is not defined!

  80. #endif

  81. #endif