| /* | |
| * Copyright (C) Ruslan Ermilov | |
| * Copyright (C) Nginx, Inc. | |
| */ | |
| #include <ngx_config.h> | |
| #include <ngx_core.h> | |
| #if (NGX_HAVE_ATOMIC_OPS) | |
| #define NGX_RWLOCK_SPIN 2048 | |
| #define NGX_RWLOCK_WLOCK ((ngx_atomic_uint_t) -1) | |
| void | |
| ngx_rwlock_wlock(ngx_atomic_t *lock) | |
| { | |
| ngx_uint_t i, n; | |
| for ( ;; ) { | |
| if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK)) { | |
| return; | |
| } | |
| if (ngx_ncpu > 1) { | |
| for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) { | |
| for (i = 0; i < n; i++) { | |
| ngx_cpu_pause(); | |
| } | |
| if (*lock == 0 | |
| && ngx_atomic_cmp_set(lock, 0, NGX_RWLOCK_WLOCK)) | |
| { | |
| return; | |
| } | |
| } | |
| } | |
| ngx_sched_yield(); | |
| } | |
| } | |
| void | |
| ngx_rwlock_rlock(ngx_atomic_t *lock) | |
| { | |
| ngx_uint_t i, n; | |
| ngx_atomic_uint_t readers; | |
| for ( ;; ) { | |
| readers = *lock; | |
| if (readers != NGX_RWLOCK_WLOCK | |
| && ngx_atomic_cmp_set(lock, readers, readers + 1)) | |
| { | |
| return; | |
| } | |
| if (ngx_ncpu > 1) { | |
| for (n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) { | |
| for (i = 0; i < n; i++) { | |
| ngx_cpu_pause(); | |
| } | |
| readers = *lock; | |
| if (readers != NGX_RWLOCK_WLOCK | |
| && ngx_atomic_cmp_set(lock, readers, readers + 1)) | |
| { | |
| return; | |
| } | |
| } | |
| } | |
| ngx_sched_yield(); | |
| } | |
| } | |
| void | |
| ngx_rwlock_unlock(ngx_atomic_t *lock) | |
| { | |
| ngx_atomic_uint_t readers; | |
| readers = *lock; | |
| if (readers == NGX_RWLOCK_WLOCK) { | |
| *lock = 0; | |
| return; | |
| } | |
| for ( ;; ) { | |
| if (ngx_atomic_cmp_set(lock, readers, readers - 1)) { | |
| return; | |
| } | |
| readers = *lock; | |
| } | |
| } | |
| #else | |
| #if (NGX_HTTP_UPSTREAM_ZONE || NGX_STREAM_UPSTREAM_ZONE) | |
| #error ngx_atomic_cmp_set() is not defined! | |
| #endif | |
| #endif |