Path: blob/main/sys/contrib/ck/include/ck_rwlock.h
48254 views
/*1* Copyright 2011-2015 Samy Al Bahra.2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#ifndef CK_RWLOCK_H27#define CK_RWLOCK_H2829#include <ck_elide.h>30#include <ck_pr.h>31#include <ck_stdbool.h>32#include <ck_stddef.h>3334struct ck_rwlock {35unsigned int writer;36unsigned int n_readers;37};38typedef struct ck_rwlock ck_rwlock_t;3940#define CK_RWLOCK_INITIALIZER {0, 0}4142CK_CC_INLINE static void43ck_rwlock_init(struct ck_rwlock *rw)44{4546rw->writer = 0;47rw->n_readers = 0;48ck_pr_barrier();49return;50}5152CK_CC_INLINE static void53ck_rwlock_write_unlock(ck_rwlock_t *rw)54{5556ck_pr_fence_unlock();57ck_pr_store_uint(&rw->writer, 0);58return;59}6061CK_CC_INLINE static bool62ck_rwlock_locked_writer(ck_rwlock_t *rw)63{64bool r;6566r = ck_pr_load_uint(&rw->writer);67ck_pr_fence_acquire();68return r;69}7071CK_CC_INLINE static void72ck_rwlock_write_downgrade(ck_rwlock_t *rw)73{7475ck_pr_inc_uint(&rw->n_readers);76ck_rwlock_write_unlock(rw);77return;78}7980CK_CC_INLINE static bool81ck_rwlock_locked(ck_rwlock_t *rw)82{83bool l;8485l = ck_pr_load_uint(&rw->n_readers) |86ck_pr_load_uint(&rw->writer);87ck_pr_fence_acquire();88return l;89}9091CK_CC_INLINE static bool92ck_rwlock_write_trylock(ck_rwlock_t *rw)93{9495if (ck_pr_fas_uint(&rw->writer, 1) != 0)96return false;9798ck_pr_fence_atomic_load();99100if (ck_pr_load_uint(&rw->n_readers) != 0) {101ck_rwlock_write_unlock(rw);102return false;103}104105ck_pr_fence_lock();106return true;107}108109CK_ELIDE_TRYLOCK_PROTOTYPE(ck_rwlock_write, ck_rwlock_t,110ck_rwlock_locked, ck_rwlock_write_trylock)111112CK_CC_INLINE static void113ck_rwlock_write_lock(ck_rwlock_t *rw)114{115116while (ck_pr_fas_uint(&rw->writer, 1) != 0)117ck_pr_stall();118119ck_pr_fence_atomic_load();120121while (ck_pr_load_uint(&rw->n_readers) != 0)122ck_pr_stall();123124ck_pr_fence_lock();125return;126}127128CK_ELIDE_PROTOTYPE(ck_rwlock_write, ck_rwlock_t,129ck_rwlock_locked, ck_rwlock_write_lock,130ck_rwlock_locked_writer, ck_rwlock_write_unlock)131132CK_CC_INLINE static bool133ck_rwlock_read_trylock(ck_rwlock_t *rw)134{135136if (ck_pr_load_uint(&rw->writer) != 0)137return false;138139ck_pr_inc_uint(&rw->n_readers);140141/*142* Serialize with respect to concurrent write143* lock operation.144*/145ck_pr_fence_atomic_load();146147if (ck_pr_load_uint(&rw->writer) == 0) {148ck_pr_fence_lock();149return true;150}151152ck_pr_dec_uint(&rw->n_readers);153return false;154}155156CK_ELIDE_TRYLOCK_PROTOTYPE(ck_rwlock_read, ck_rwlock_t,157ck_rwlock_locked_writer, ck_rwlock_read_trylock)158159CK_CC_INLINE static void160ck_rwlock_read_lock(ck_rwlock_t *rw)161{162163for (;;) {164while (ck_pr_load_uint(&rw->writer) != 0)165ck_pr_stall();166167ck_pr_inc_uint(&rw->n_readers);168169/*170* Serialize with respect to concurrent write171* lock operation.172*/173ck_pr_fence_atomic_load();174175if (ck_pr_load_uint(&rw->writer) == 0)176break;177178ck_pr_dec_uint(&rw->n_readers);179}180181/* Acquire semantics are necessary. */182ck_pr_fence_load();183return;184}185186CK_CC_INLINE static bool187ck_rwlock_locked_reader(ck_rwlock_t *rw)188{189190ck_pr_fence_load();191return ck_pr_load_uint(&rw->n_readers);192}193194CK_CC_INLINE static void195ck_rwlock_read_unlock(ck_rwlock_t *rw)196{197198ck_pr_fence_load_atomic();199ck_pr_dec_uint(&rw->n_readers);200return;201}202203CK_ELIDE_PROTOTYPE(ck_rwlock_read, ck_rwlock_t,204ck_rwlock_locked_writer, ck_rwlock_read_lock,205ck_rwlock_locked_reader, ck_rwlock_read_unlock)206207/*208* Recursive writer reader-writer lock implementation.209*/210struct ck_rwlock_recursive {211struct ck_rwlock rw;212unsigned int wc;213};214typedef struct ck_rwlock_recursive ck_rwlock_recursive_t;215216#define CK_RWLOCK_RECURSIVE_INITIALIZER {CK_RWLOCK_INITIALIZER, 0}217218CK_CC_INLINE static void219ck_rwlock_recursive_write_lock(ck_rwlock_recursive_t *rw, unsigned int tid)220{221unsigned int o;222223o = ck_pr_load_uint(&rw->rw.writer);224if (o == tid)225goto leave;226227while (ck_pr_cas_uint(&rw->rw.writer, 0, tid) == false)228ck_pr_stall();229230ck_pr_fence_atomic_load();231232while (ck_pr_load_uint(&rw->rw.n_readers) != 0)233ck_pr_stall();234235ck_pr_fence_lock();236leave:237rw->wc++;238return;239}240241CK_CC_INLINE static bool242ck_rwlock_recursive_write_trylock(ck_rwlock_recursive_t *rw, unsigned int tid)243{244unsigned int o;245246o = ck_pr_load_uint(&rw->rw.writer);247if (o == tid)248goto leave;249250if (ck_pr_cas_uint(&rw->rw.writer, 0, tid) == false)251return false;252253ck_pr_fence_atomic_load();254255if (ck_pr_load_uint(&rw->rw.n_readers) != 0) {256ck_pr_store_uint(&rw->rw.writer, 0);257return false;258}259260ck_pr_fence_lock();261leave:262rw->wc++;263return true;264}265266CK_CC_INLINE static void267ck_rwlock_recursive_write_unlock(ck_rwlock_recursive_t *rw)268{269270if (--rw->wc == 0) {271ck_pr_fence_unlock();272ck_pr_store_uint(&rw->rw.writer, 0);273}274275return;276}277278CK_CC_INLINE static void279ck_rwlock_recursive_read_lock(ck_rwlock_recursive_t *rw)280{281282ck_rwlock_read_lock(&rw->rw);283return;284}285286CK_CC_INLINE static bool287ck_rwlock_recursive_read_trylock(ck_rwlock_recursive_t *rw)288{289290return ck_rwlock_read_trylock(&rw->rw);291}292293CK_CC_INLINE static void294ck_rwlock_recursive_read_unlock(ck_rwlock_recursive_t *rw)295{296297ck_rwlock_read_unlock(&rw->rw);298return;299}300301#endif /* CK_RWLOCK_H */302303304