Path: blob/main/sys/contrib/ck/include/spinlock/dec.h
48375 views
/*1* Copyright 2010-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_SPINLOCK_DEC_H27#define CK_SPINLOCK_DEC_H2829#include <ck_backoff.h>30#include <ck_cc.h>31#include <ck_elide.h>32#include <ck_pr.h>33#include <ck_stdbool.h>3435#ifndef CK_F_SPINLOCK_DEC36#define CK_F_SPINLOCK_DEC37/*38* This is similar to the CACAS lock but makes use of an atomic decrement39* operation to check if the lock value was decremented to 0 from 1. The40* idea is that a decrement operation is cheaper than a compare-and-swap.41*/42struct ck_spinlock_dec {43unsigned int value;44};45typedef struct ck_spinlock_dec ck_spinlock_dec_t;4647#define CK_SPINLOCK_DEC_INITIALIZER {1}4849CK_CC_INLINE static void50ck_spinlock_dec_init(struct ck_spinlock_dec *lock)51{5253lock->value = 1;54ck_pr_barrier();55return;56}5758CK_CC_INLINE static bool59ck_spinlock_dec_trylock(struct ck_spinlock_dec *lock)60{61unsigned int value;6263value = ck_pr_fas_uint(&lock->value, 0);64ck_pr_fence_lock();65return value == 1;66}6768CK_CC_INLINE static bool69ck_spinlock_dec_locked(struct ck_spinlock_dec *lock)70{71bool r;7273r = ck_pr_load_uint(&lock->value) != 1;74ck_pr_fence_acquire();75return r;76}7778CK_CC_INLINE static void79ck_spinlock_dec_lock(struct ck_spinlock_dec *lock)80{81bool r;8283for (;;) {84/*85* Only one thread is guaranteed to decrement lock to 0.86* Overflow must be protected against. No more than87* UINT_MAX lock requests can happen while the lock is held.88*/89ck_pr_dec_uint_zero(&lock->value, &r);90if (r == true)91break;9293/* Load value without generating write cycles. */94while (ck_pr_load_uint(&lock->value) != 1)95ck_pr_stall();96}9798ck_pr_fence_lock();99return;100}101102CK_CC_INLINE static void103ck_spinlock_dec_lock_eb(struct ck_spinlock_dec *lock)104{105ck_backoff_t backoff = CK_BACKOFF_INITIALIZER;106bool r;107108for (;;) {109ck_pr_dec_uint_zero(&lock->value, &r);110if (r == true)111break;112113while (ck_pr_load_uint(&lock->value) != 1)114ck_backoff_eb(&backoff);115}116117ck_pr_fence_lock();118return;119}120121CK_CC_INLINE static void122ck_spinlock_dec_unlock(struct ck_spinlock_dec *lock)123{124125ck_pr_fence_unlock();126127/*128* Unconditionally set lock value to 1 so someone can decrement lock129* to 0.130*/131ck_pr_store_uint(&lock->value, 1);132return;133}134135CK_ELIDE_PROTOTYPE(ck_spinlock_dec, ck_spinlock_dec_t,136ck_spinlock_dec_locked, ck_spinlock_dec_lock,137ck_spinlock_dec_locked, ck_spinlock_dec_unlock)138139CK_ELIDE_TRYLOCK_PROTOTYPE(ck_spinlock_dec, ck_spinlock_dec_t,140ck_spinlock_dec_locked, ck_spinlock_dec_trylock)141142#endif /* CK_F_SPINLOCK_DEC */143#endif /* CK_SPINLOCK_DEC_H */144145146