1234353Sdim/* 2198090Srdivacky * Copyright 2010-2015 Samy Al Bahra. 3198090Srdivacky * All rights reserved. 4198090Srdivacky * 5198090Srdivacky * Redistribution and use in source and binary forms, with or without 6198090Srdivacky * modification, are permitted provided that the following conditions 7198090Srdivacky * are met: 8198090Srdivacky * 1. Redistributions of source code must retain the above copyright 9198090Srdivacky * notice, this list of conditions and the following disclaimer. 10198090Srdivacky * 2. Redistributions in binary form must reproduce the above copyright 11198090Srdivacky * notice, this list of conditions and the following disclaimer in the 12198090Srdivacky * documentation and/or other materials provided with the distribution. 13249423Sdim * 14249423Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15249423Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16198090Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17198090Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18234353Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19198090Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20198090Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21276479Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22276479Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23210299Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24210299Sed * SUCH DAMAGE. 25198090Srdivacky */ 26198090Srdivacky 27210299Sed#ifndef CK_SPINLOCK_FAS_H 28210299Sed#define CK_SPINLOCK_FAS_H 29198090Srdivacky 30212904Sdim#include <ck_backoff.h> 31198090Srdivacky#include <ck_cc.h> 32261991Sdim#include <ck_elide.h> 33198090Srdivacky#include <ck_pr.h> 34210299Sed#include <ck_stdbool.h> 35198090Srdivacky 36198090Srdivacky#ifndef CK_F_SPINLOCK_FAS 37276479Sdim#define CK_F_SPINLOCK_FAS 38198090Srdivacky 39276479Sdimstruct ck_spinlock_fas { 40198090Srdivacky unsigned int value; 41198090Srdivacky}; 42198090Srdivackytypedef struct ck_spinlock_fas ck_spinlock_fas_t; 43198090Srdivacky 44210299Sed#define CK_SPINLOCK_FAS_INITIALIZER {false} 45210299Sed 46210299SedCK_CC_INLINE static void 47210299Sedck_spinlock_fas_init(struct ck_spinlock_fas *lock) 48210299Sed{ 49198090Srdivacky 50198090Srdivacky lock->value = false; 51198090Srdivacky ck_pr_barrier(); 52198090Srdivacky return; 53210299Sed} 54210299Sed 55210299SedCK_CC_INLINE static bool 56210299Sedck_spinlock_fas_trylock(struct ck_spinlock_fas *lock) 57210299Sed{ 58210299Sed bool value; 59210299Sed 60210299Sed value = ck_pr_fas_uint(&lock->value, true); 61210299Sed ck_pr_fence_lock(); 62210299Sed 63210299Sed return !value; 64210299Sed} 65210299Sed 66210299SedCK_CC_INLINE static bool 67210299Sedck_spinlock_fas_locked(struct ck_spinlock_fas *lock) 68210299Sed{ 69210299Sed bool r; 70210299Sed 71210299Sed r = ck_pr_load_uint(&lock->value); 72210299Sed ck_pr_fence_acquire(); 73210299Sed return r; 74210299Sed} 75210299Sed 76210299SedCK_CC_INLINE static void 77210299Sedck_spinlock_fas_lock(struct ck_spinlock_fas *lock) 78261991Sdim{ 79261991Sdim 80210299Sed while (CK_CC_UNLIKELY(ck_pr_fas_uint(&lock->value, true) == true)) { 81210299Sed do { 82210299Sed ck_pr_stall(); 83210299Sed } while (ck_pr_load_uint(&lock->value) == true); 84210299Sed } 85261991Sdim 86261991Sdim ck_pr_fence_lock(); 87210299Sed return; 88210299Sed} 89210299Sed 90210299SedCK_CC_INLINE static void 91198090Srdivackyck_spinlock_fas_lock_eb(struct ck_spinlock_fas *lock) 92198090Srdivacky{ 93288943Sdim ck_backoff_t backoff = CK_BACKOFF_INITIALIZER; 94288943Sdim 95288943Sdim while (ck_pr_fas_uint(&lock->value, true) == true) 96288943Sdim ck_backoff_eb(&backoff); 97288943Sdim 98288943Sdim ck_pr_fence_lock(); 99288943Sdim return; 100288943Sdim} 101288943Sdim 102288943SdimCK_CC_INLINE static void 103288943Sdimck_spinlock_fas_unlock(struct ck_spinlock_fas *lock) 104288943Sdim{ 105288943Sdim 106212904Sdim ck_pr_fence_unlock(); 107212904Sdim ck_pr_store_uint(&lock->value, false); 108212904Sdim return; 109212904Sdim} 110212904Sdim 111212904SdimCK_ELIDE_PROTOTYPE(ck_spinlock_fas, ck_spinlock_fas_t, 112212904Sdim ck_spinlock_fas_locked, ck_spinlock_fas_lock, 113212904Sdim ck_spinlock_fas_locked, ck_spinlock_fas_unlock) 114212904Sdim 115212904SdimCK_ELIDE_TRYLOCK_PROTOTYPE(ck_spinlock_fas, ck_spinlock_fas_t, 116212904Sdim ck_spinlock_fas_locked, ck_spinlock_fas_trylock) 117212904Sdim 118210299Sed#endif /* CK_F_SPINLOCK_FAS */ 119210299Sed#endif /* CK_SPINLOCK_FAS_H */ 120210299Sed