From 3fc23e2542d89712e6104331e95c648fc52a9b35 Mon Sep 17 00:00:00 2001 From: Ruslan Ermilov Date: Sat, 21 Mar 2015 14:05:08 +0300 Subject: Core: read/write locks. --- src/core/ngx_core.h | 1 + src/core/ngx_rwlock.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ngx_rwlock.h | 21 ++++++++++ 3 files changed, 134 insertions(+) create mode 100644 src/core/ngx_rwlock.c create mode 100644 src/core/ngx_rwlock.h (limited to 'src/core') diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index bc1d43f98..e8031ef60 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -68,6 +68,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c); #endif #include #include +#include #include #include #include diff --git a/src/core/ngx_rwlock.c b/src/core/ngx_rwlock.c new file mode 100644 index 000000000..066c67de8 --- /dev/null +++ b/src/core/ngx_rwlock.c @@ -0,0 +1,112 @@ + +/* + * Copyright (C) Ruslan Ermilov + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#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; + } +} + + +#endif diff --git a/src/core/ngx_rwlock.h b/src/core/ngx_rwlock.h new file mode 100644 index 000000000..8b16eca20 --- /dev/null +++ b/src/core/ngx_rwlock.h @@ -0,0 +1,21 @@ + +/* + * Copyright (C) Ruslan Ermilov + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_RWLOCK_H_INCLUDED_ +#define _NGX_RWLOCK_H_INCLUDED_ + + +#include +#include + + +void ngx_rwlock_wlock(ngx_atomic_t *lock); +void ngx_rwlock_rlock(ngx_atomic_t *lock); +void ngx_rwlock_unlock(ngx_atomic_t *lock); + + +#endif /* _NGX_RWLOCK_H_INCLUDED_ */ -- cgit