Path: blob/main/sys/contrib/ck/include/ck_pflock.h
48254 views
/*1* Copyright 2013 John Wittrock.2* Copyright 2013-2015 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_PFLOCK_H28#define CK_PFLOCK_H2930/*31* This is an implementation of phase-fair locks derived from the work32* described in:33* Brandenburg, B. and Anderson, J. 2010. Spin-Based34* Reader-Writer Synchronization for Multiprocessor Real-Time Systems35*/3637#include <ck_cc.h>38#include <ck_pr.h>3940struct ck_pflock {41uint32_t rin;42uint32_t rout;43uint32_t win;44uint32_t wout;45};46typedef struct ck_pflock ck_pflock_t;4748#define CK_PFLOCK_LSB 0xFFFFFFF049#define CK_PFLOCK_RINC 0x100 /* Reader increment value. */50#define CK_PFLOCK_WBITS 0x3 /* Writer bits in reader. */51#define CK_PFLOCK_PRES 0x2 /* Writer present bit. */52#define CK_PFLOCK_PHID 0x1 /* Phase ID bit. */5354#define CK_PFLOCK_INITIALIZER {0, 0, 0, 0}5556CK_CC_INLINE static void57ck_pflock_init(struct ck_pflock *pf)58{5960pf->rin = 0;61pf->rout = 0;62pf->win = 0;63pf->wout = 0;64ck_pr_barrier();6566return;67}6869CK_CC_INLINE static void70ck_pflock_write_unlock(ck_pflock_t *pf)71{7273ck_pr_fence_unlock();7475/* Migrate from write phase to read phase. */76ck_pr_and_32(&pf->rin, CK_PFLOCK_LSB);7778/* Allow other writers to continue. */79ck_pr_faa_32(&pf->wout, 1);80return;81}8283CK_CC_INLINE static void84ck_pflock_write_lock(ck_pflock_t *pf)85{86uint32_t ticket;8788/* Acquire ownership of write-phase. */89ticket = ck_pr_faa_32(&pf->win, 1);90while (ck_pr_load_32(&pf->wout) != ticket)91ck_pr_stall();9293/*94* Acquire ticket on read-side in order to allow them95* to flush. Indicates to any incoming reader that a96* write-phase is pending.97*/98ticket = ck_pr_faa_32(&pf->rin,99(ticket & CK_PFLOCK_PHID) | CK_PFLOCK_PRES);100101/* Wait for any pending readers to flush. */102while (ck_pr_load_32(&pf->rout) != ticket)103ck_pr_stall();104105ck_pr_fence_lock();106return;107}108109CK_CC_INLINE static void110ck_pflock_read_unlock(ck_pflock_t *pf)111{112113ck_pr_fence_unlock();114ck_pr_faa_32(&pf->rout, CK_PFLOCK_RINC);115return;116}117118CK_CC_INLINE static void119ck_pflock_read_lock(ck_pflock_t *pf)120{121uint32_t w;122123/*124* If no writer is present, then the operation has completed125* successfully.126*/127w = ck_pr_faa_32(&pf->rin, CK_PFLOCK_RINC) & CK_PFLOCK_WBITS;128if (w == 0)129goto leave;130131/* Wait for current write phase to complete. */132while ((ck_pr_load_32(&pf->rin) & CK_PFLOCK_WBITS) == w)133ck_pr_stall();134135leave:136/* Acquire semantics with respect to readers. */137ck_pr_fence_lock();138return;139}140141#endif /* CK_PFLOCK_H */142143144