Path: blob/main/sys/contrib/ck/include/ck_swlock.h
48254 views
/*1* Copyright 2014 Jaidev Sridhar.2* Copyright 2014 Samy Al Bahra.3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#ifndef CK_SWLOCK_H28#define CK_SWLOCK_H2930#include <ck_elide.h>31#include <ck_limits.h>32#include <ck_pr.h>33#include <ck_stdbool.h>34#include <ck_stddef.h>3536struct ck_swlock {37uint32_t value;38};39typedef struct ck_swlock ck_swlock_t;4041#define CK_SWLOCK_INITIALIZER {0}42#define CK_SWLOCK_WRITER_BIT (1UL << 31)43#define CK_SWLOCK_LATCH_BIT (1UL << 30)44#define CK_SWLOCK_WRITER_MASK (CK_SWLOCK_LATCH_BIT | CK_SWLOCK_WRITER_BIT)45#define CK_SWLOCK_READER_MASK (UINT32_MAX ^ CK_SWLOCK_WRITER_MASK)4647CK_CC_INLINE static void48ck_swlock_init(struct ck_swlock *rw)49{5051rw->value = 0;52ck_pr_barrier();53return;54}5556CK_CC_INLINE static void57ck_swlock_write_unlock(ck_swlock_t *rw)58{5960ck_pr_fence_unlock();61ck_pr_and_32(&rw->value, CK_SWLOCK_READER_MASK);62return;63}6465CK_CC_INLINE static bool66ck_swlock_locked_writer(ck_swlock_t *rw)67{68bool r;6970r = ck_pr_load_32(&rw->value) & CK_SWLOCK_WRITER_BIT;71ck_pr_fence_acquire();72return r;73}7475CK_CC_INLINE static void76ck_swlock_write_downgrade(ck_swlock_t *rw)77{7879ck_pr_inc_32(&rw->value);80ck_swlock_write_unlock(rw);81return;82}8384CK_CC_INLINE static bool85ck_swlock_locked(ck_swlock_t *rw)86{87bool r;8889r = ck_pr_load_32(&rw->value);90ck_pr_fence_acquire();91return r;92}9394CK_CC_INLINE static bool95ck_swlock_write_trylock(ck_swlock_t *rw)96{97bool r;9899r = ck_pr_cas_32(&rw->value, 0, CK_SWLOCK_WRITER_BIT);100ck_pr_fence_lock();101return r;102}103104CK_ELIDE_TRYLOCK_PROTOTYPE(ck_swlock_write, ck_swlock_t,105ck_swlock_locked, ck_swlock_write_trylock)106107CK_CC_INLINE static void108ck_swlock_write_lock(ck_swlock_t *rw)109{110111ck_pr_or_32(&rw->value, CK_SWLOCK_WRITER_BIT);112while (ck_pr_load_32(&rw->value) & CK_SWLOCK_READER_MASK)113ck_pr_stall();114115ck_pr_fence_lock();116return;117}118119CK_CC_INLINE static void120ck_swlock_write_latch(ck_swlock_t *rw)121{122123/* Publish intent to acquire lock. */124ck_pr_or_32(&rw->value, CK_SWLOCK_WRITER_BIT);125126/* Stall until readers have seen the writer and cleared. */127while (ck_pr_cas_32(&rw->value, CK_SWLOCK_WRITER_BIT,128CK_SWLOCK_WRITER_MASK) == false) {129do {130ck_pr_stall();131} while (ck_pr_load_32(&rw->value) != CK_SWLOCK_WRITER_BIT);132}133134ck_pr_fence_lock();135return;136}137138CK_CC_INLINE static void139ck_swlock_write_unlatch(ck_swlock_t *rw)140{141142ck_pr_fence_unlock();143ck_pr_store_32(&rw->value, 0);144return;145}146147CK_ELIDE_PROTOTYPE(ck_swlock_write, ck_swlock_t,148ck_swlock_locked, ck_swlock_write_lock,149ck_swlock_locked_writer, ck_swlock_write_unlock)150151CK_ELIDE_TRYLOCK_PROTOTYPE(ck_swlock_read, ck_swlock_t,152ck_swlock_locked_writer, ck_swlock_read_trylock)153154CK_CC_INLINE static bool155ck_swlock_read_trylock(ck_swlock_t *rw)156{157uint32_t l = ck_pr_load_32(&rw->value);158159if (l & CK_SWLOCK_WRITER_BIT)160return false;161162l = ck_pr_faa_32(&rw->value, 1) & CK_SWLOCK_WRITER_MASK;163if (l == CK_SWLOCK_WRITER_BIT)164ck_pr_dec_32(&rw->value);165166ck_pr_fence_lock();167return l == 0;168}169170CK_CC_INLINE static void171ck_swlock_read_lock(ck_swlock_t *rw)172{173uint32_t l;174175for (;;) {176while (ck_pr_load_32(&rw->value) & CK_SWLOCK_WRITER_BIT)177ck_pr_stall();178179l = ck_pr_faa_32(&rw->value, 1) & CK_SWLOCK_WRITER_MASK;180if (l == 0)181break;182183/*184* If the latch bit has not been set, then the writer would185* have observed the reader and will wait to completion of186* read-side critical section.187*/188if (l == CK_SWLOCK_WRITER_BIT)189ck_pr_dec_32(&rw->value);190}191192ck_pr_fence_lock();193return;194}195196CK_CC_INLINE static bool197ck_swlock_locked_reader(ck_swlock_t *rw)198{199200ck_pr_fence_load();201return ck_pr_load_32(&rw->value) & CK_SWLOCK_READER_MASK;202}203204CK_CC_INLINE static void205ck_swlock_read_unlock(ck_swlock_t *rw)206{207208ck_pr_fence_unlock();209ck_pr_dec_32(&rw->value);210return;211}212213CK_ELIDE_PROTOTYPE(ck_swlock_read, ck_swlock_t,214ck_swlock_locked_writer, ck_swlock_read_lock,215ck_swlock_locked_reader, ck_swlock_read_unlock)216217#endif /* CK_SWLOCK_H */218219220