1309260Scognet/* 2309260Scognet * Copyright 2010-2015 Samy Al Bahra. 3309260Scognet * All rights reserved. 4309260Scognet * 5309260Scognet * Redistribution and use in source and binary forms, with or without 6309260Scognet * modification, are permitted provided that the following conditions 7309260Scognet * are met: 8309260Scognet * 1. Redistributions of source code must retain the above copyright 9309260Scognet * notice, this list of conditions and the following disclaimer. 10309260Scognet * 2. Redistributions in binary form must reproduce the above copyright 11309260Scognet * notice, this list of conditions and the following disclaimer in the 12309260Scognet * documentation and/or other materials provided with the distribution. 13309260Scognet * 14309260Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15309260Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16309260Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17309260Scognet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18309260Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19309260Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20309260Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21309260Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22309260Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23309260Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24309260Scognet * SUCH DAMAGE. 25309260Scognet */ 26309260Scognet 27309260Scognet#ifndef CK_SPINLOCK_CAS_H 28309260Scognet#define CK_SPINLOCK_CAS_H 29309260Scognet 30309260Scognet#include <ck_backoff.h> 31309260Scognet#include <ck_cc.h> 32309260Scognet#include <ck_elide.h> 33309260Scognet#include <ck_pr.h> 34309260Scognet#include <ck_stdbool.h> 35309260Scognet 36309260Scognet#ifndef CK_F_SPINLOCK_CAS 37309260Scognet#define CK_F_SPINLOCK_CAS 38309260Scognet/* 39309260Scognet * This is a simple CACAS (TATAS) spinlock implementation. 40309260Scognet */ 41309260Scognetstruct ck_spinlock_cas { 42309260Scognet unsigned int value; 43309260Scognet}; 44309260Scognettypedef struct ck_spinlock_cas ck_spinlock_cas_t; 45309260Scognet 46309260Scognet#define CK_SPINLOCK_CAS_INITIALIZER {false} 47309260Scognet 48309260ScognetCK_CC_INLINE static void 49309260Scognetck_spinlock_cas_init(struct ck_spinlock_cas *lock) 50309260Scognet{ 51309260Scognet 52309260Scognet lock->value = false; 53309260Scognet ck_pr_barrier(); 54309260Scognet return; 55309260Scognet} 56309260Scognet 57309260ScognetCK_CC_INLINE static bool 58309260Scognetck_spinlock_cas_trylock(struct ck_spinlock_cas *lock) 59309260Scognet{ 60309260Scognet unsigned int value; 61309260Scognet 62309260Scognet value = ck_pr_fas_uint(&lock->value, true); 63309260Scognet ck_pr_fence_lock(); 64309260Scognet return !value; 65309260Scognet} 66309260Scognet 67309260ScognetCK_CC_INLINE static bool 68309260Scognetck_spinlock_cas_locked(struct ck_spinlock_cas *lock) 69309260Scognet{ 70309260Scognet bool r = ck_pr_load_uint(&lock->value); 71309260Scognet 72309260Scognet ck_pr_fence_acquire(); 73309260Scognet return r; 74309260Scognet} 75309260Scognet 76309260ScognetCK_CC_INLINE static void 77309260Scognetck_spinlock_cas_lock(struct ck_spinlock_cas *lock) 78309260Scognet{ 79309260Scognet 80309260Scognet while (ck_pr_cas_uint(&lock->value, false, true) == false) { 81309260Scognet while (ck_pr_load_uint(&lock->value) == true) 82309260Scognet ck_pr_stall(); 83309260Scognet } 84309260Scognet 85309260Scognet ck_pr_fence_lock(); 86309260Scognet return; 87309260Scognet} 88309260Scognet 89309260ScognetCK_CC_INLINE static void 90309260Scognetck_spinlock_cas_lock_eb(struct ck_spinlock_cas *lock) 91309260Scognet{ 92309260Scognet ck_backoff_t backoff = CK_BACKOFF_INITIALIZER; 93309260Scognet 94309260Scognet while (ck_pr_cas_uint(&lock->value, false, true) == false) 95309260Scognet ck_backoff_eb(&backoff); 96309260Scognet 97309260Scognet ck_pr_fence_lock(); 98309260Scognet return; 99309260Scognet} 100309260Scognet 101309260ScognetCK_CC_INLINE static void 102309260Scognetck_spinlock_cas_unlock(struct ck_spinlock_cas *lock) 103309260Scognet{ 104309260Scognet 105309260Scognet /* Set lock state to unlocked. */ 106309260Scognet ck_pr_fence_unlock(); 107309260Scognet ck_pr_store_uint(&lock->value, false); 108309260Scognet return; 109309260Scognet} 110309260Scognet 111309260ScognetCK_ELIDE_PROTOTYPE(ck_spinlock_cas, ck_spinlock_cas_t, 112309260Scognet ck_spinlock_cas_locked, ck_spinlock_cas_lock, 113309260Scognet ck_spinlock_cas_locked, ck_spinlock_cas_unlock) 114309260Scognet 115309260ScognetCK_ELIDE_TRYLOCK_PROTOTYPE(ck_spinlock_cas, ck_spinlock_cas_t, 116309260Scognet ck_spinlock_cas_locked, ck_spinlock_cas_trylock) 117309260Scognet 118309260Scognet#endif /* CK_F_SPINLOCK_CAS */ 119309260Scognet#endif /* CK_SPINLOCK_CAS_H */ 120