1*1fb62fb0SOlivier Houchard /* 2*1fb62fb0SOlivier Houchard * Copyright 2013-2015 Samy Al Bahra. 3*1fb62fb0SOlivier Houchard * Copyright 2013 Brendon Scheinman. 4*1fb62fb0SOlivier Houchard * All rights reserved. 5*1fb62fb0SOlivier Houchard * 6*1fb62fb0SOlivier Houchard * Redistribution and use in source and binary forms, with or without 7*1fb62fb0SOlivier Houchard * modification, are permitted provided that the following conditions 8*1fb62fb0SOlivier Houchard * are met: 9*1fb62fb0SOlivier Houchard * 1. Redistributions of source code must retain the above copyright 10*1fb62fb0SOlivier Houchard * notice, this list of conditions and the following disclaimer. 11*1fb62fb0SOlivier Houchard * 2. Redistributions in binary form must reproduce the above copyright 12*1fb62fb0SOlivier Houchard * notice, this list of conditions and the following disclaimer in the 13*1fb62fb0SOlivier Houchard * documentation and/or other materials provided with the distribution. 14*1fb62fb0SOlivier Houchard * 15*1fb62fb0SOlivier Houchard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*1fb62fb0SOlivier Houchard * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*1fb62fb0SOlivier Houchard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*1fb62fb0SOlivier Houchard * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*1fb62fb0SOlivier Houchard * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*1fb62fb0SOlivier Houchard * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*1fb62fb0SOlivier Houchard * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*1fb62fb0SOlivier Houchard * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*1fb62fb0SOlivier Houchard * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*1fb62fb0SOlivier Houchard * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*1fb62fb0SOlivier Houchard * SUCH DAMAGE. 26*1fb62fb0SOlivier Houchard */ 27*1fb62fb0SOlivier Houchard 28*1fb62fb0SOlivier Houchard #ifndef CK_RWCOHORT_H 29*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_H 30*1fb62fb0SOlivier Houchard 31*1fb62fb0SOlivier Houchard /* 32*1fb62fb0SOlivier Houchard * This is an implementation of NUMA-aware reader-writer locks as described in: 33*1fb62fb0SOlivier Houchard * Calciu, I.; Dice, D.; Lev, Y.; Luchangco, V.; Marathe, V.; and Shavit, N. 2014. 34*1fb62fb0SOlivier Houchard * NUMA-Aware Reader-Writer Locks 35*1fb62fb0SOlivier Houchard */ 36*1fb62fb0SOlivier Houchard 37*1fb62fb0SOlivier Houchard #include <ck_cc.h> 38*1fb62fb0SOlivier Houchard #include <ck_pr.h> 39*1fb62fb0SOlivier Houchard #include <ck_stddef.h> 40*1fb62fb0SOlivier Houchard #include <ck_cohort.h> 41*1fb62fb0SOlivier Houchard 42*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_NAME(N) ck_rwcohort_wp_##N 43*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_INSTANCE(N) struct CK_RWCOHORT_WP_NAME(N) 44*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_INIT(N, RW, WL) ck_rwcohort_wp_##N##_init(RW, WL) 45*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_READ_LOCK(N, RW, C, GC, LC) \ 46*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_read_lock(RW, C, GC, LC) 47*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_READ_UNLOCK(N, RW, C, GC, LC) \ 48*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_read_unlock(RW) 49*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_WRITE_LOCK(N, RW, C, GC, LC) \ 50*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_write_lock(RW, C, GC, LC) 51*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_WRITE_UNLOCK(N, RW, C, GC, LC) \ 52*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_write_unlock(RW, C, GC, LC) 53*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_DEFAULT_WAIT_LIMIT 1000 54*1fb62fb0SOlivier Houchard 55*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_PROTOTYPE(N) \ 56*1fb62fb0SOlivier Houchard CK_RWCOHORT_WP_INSTANCE(N) { \ 57*1fb62fb0SOlivier Houchard unsigned int read_counter; \ 58*1fb62fb0SOlivier Houchard unsigned int write_barrier; \ 59*1fb62fb0SOlivier Houchard unsigned int wait_limit; \ 60*1fb62fb0SOlivier Houchard }; \ 61*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 62*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_init(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ 63*1fb62fb0SOlivier Houchard unsigned int wait_limit) \ 64*1fb62fb0SOlivier Houchard { \ 65*1fb62fb0SOlivier Houchard \ 66*1fb62fb0SOlivier Houchard rw_cohort->read_counter = 0; \ 67*1fb62fb0SOlivier Houchard rw_cohort->write_barrier = 0; \ 68*1fb62fb0SOlivier Houchard rw_cohort->wait_limit = wait_limit; \ 69*1fb62fb0SOlivier Houchard ck_pr_barrier(); \ 70*1fb62fb0SOlivier Houchard return; \ 71*1fb62fb0SOlivier Houchard } \ 72*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 73*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_write_lock(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ 74*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ 75*1fb62fb0SOlivier Houchard void *local_context) \ 76*1fb62fb0SOlivier Houchard { \ 77*1fb62fb0SOlivier Houchard \ 78*1fb62fb0SOlivier Houchard while (ck_pr_load_uint(&rw_cohort->write_barrier) > 0) \ 79*1fb62fb0SOlivier Houchard ck_pr_stall(); \ 80*1fb62fb0SOlivier Houchard \ 81*1fb62fb0SOlivier Houchard CK_COHORT_LOCK(N, cohort, global_context, local_context); \ 82*1fb62fb0SOlivier Houchard \ 83*1fb62fb0SOlivier Houchard while (ck_pr_load_uint(&rw_cohort->read_counter) > 0) \ 84*1fb62fb0SOlivier Houchard ck_pr_stall(); \ 85*1fb62fb0SOlivier Houchard \ 86*1fb62fb0SOlivier Houchard return; \ 87*1fb62fb0SOlivier Houchard } \ 88*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 89*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_write_unlock(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ 90*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ 91*1fb62fb0SOlivier Houchard void *local_context) \ 92*1fb62fb0SOlivier Houchard { \ 93*1fb62fb0SOlivier Houchard \ 94*1fb62fb0SOlivier Houchard (void)rw_cohort; \ 95*1fb62fb0SOlivier Houchard CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ 96*1fb62fb0SOlivier Houchard return; \ 97*1fb62fb0SOlivier Houchard } \ 98*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 99*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_read_lock(CK_RWCOHORT_WP_INSTANCE(N) *rw_cohort, \ 100*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ 101*1fb62fb0SOlivier Houchard void *local_context) \ 102*1fb62fb0SOlivier Houchard { \ 103*1fb62fb0SOlivier Houchard unsigned int wait_count = 0; \ 104*1fb62fb0SOlivier Houchard bool raised = false; \ 105*1fb62fb0SOlivier Houchard \ 106*1fb62fb0SOlivier Houchard for (;;) { \ 107*1fb62fb0SOlivier Houchard ck_pr_inc_uint(&rw_cohort->read_counter); \ 108*1fb62fb0SOlivier Houchard ck_pr_fence_atomic_load(); \ 109*1fb62fb0SOlivier Houchard if (CK_COHORT_LOCKED(N, cohort, global_context, \ 110*1fb62fb0SOlivier Houchard local_context) == false) \ 111*1fb62fb0SOlivier Houchard break; \ 112*1fb62fb0SOlivier Houchard \ 113*1fb62fb0SOlivier Houchard ck_pr_dec_uint(&rw_cohort->read_counter); \ 114*1fb62fb0SOlivier Houchard while (CK_COHORT_LOCKED(N, cohort, global_context, \ 115*1fb62fb0SOlivier Houchard local_context) == true) { \ 116*1fb62fb0SOlivier Houchard ck_pr_stall(); \ 117*1fb62fb0SOlivier Houchard if (++wait_count > rw_cohort->wait_limit && \ 118*1fb62fb0SOlivier Houchard raised == false) { \ 119*1fb62fb0SOlivier Houchard ck_pr_inc_uint(&rw_cohort->write_barrier); \ 120*1fb62fb0SOlivier Houchard raised = true; \ 121*1fb62fb0SOlivier Houchard } \ 122*1fb62fb0SOlivier Houchard } \ 123*1fb62fb0SOlivier Houchard } \ 124*1fb62fb0SOlivier Houchard \ 125*1fb62fb0SOlivier Houchard if (raised == true) \ 126*1fb62fb0SOlivier Houchard ck_pr_dec_uint(&rw_cohort->write_barrier); \ 127*1fb62fb0SOlivier Houchard \ 128*1fb62fb0SOlivier Houchard ck_pr_fence_load(); \ 129*1fb62fb0SOlivier Houchard return; \ 130*1fb62fb0SOlivier Houchard } \ 131*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 132*1fb62fb0SOlivier Houchard ck_rwcohort_wp_##N##_read_unlock(CK_RWCOHORT_WP_INSTANCE(N) *cohort) \ 133*1fb62fb0SOlivier Houchard { \ 134*1fb62fb0SOlivier Houchard \ 135*1fb62fb0SOlivier Houchard ck_pr_fence_load_atomic(); \ 136*1fb62fb0SOlivier Houchard ck_pr_dec_uint(&cohort->read_counter); \ 137*1fb62fb0SOlivier Houchard return; \ 138*1fb62fb0SOlivier Houchard } 139*1fb62fb0SOlivier Houchard 140*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_WP_INITIALIZER { \ 141*1fb62fb0SOlivier Houchard .read_counter = 0, \ 142*1fb62fb0SOlivier Houchard .write_barrier = 0, \ 143*1fb62fb0SOlivier Houchard .wait_limit = 0 \ 144*1fb62fb0SOlivier Houchard } 145*1fb62fb0SOlivier Houchard 146*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_NAME(N) ck_rwcohort_rp_##N 147*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_INSTANCE(N) struct CK_RWCOHORT_RP_NAME(N) 148*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_INIT(N, RW, WL) ck_rwcohort_rp_##N##_init(RW, WL) 149*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_READ_LOCK(N, RW, C, GC, LC) \ 150*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_read_lock(RW, C, GC, LC) 151*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_READ_UNLOCK(N, RW, C, GC, LC) \ 152*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_read_unlock(RW) 153*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_WRITE_LOCK(N, RW, C, GC, LC) \ 154*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_write_lock(RW, C, GC, LC) 155*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_WRITE_UNLOCK(N, RW, C, GC, LC) \ 156*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_write_unlock(RW, C, GC, LC) 157*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_DEFAULT_WAIT_LIMIT 1000 158*1fb62fb0SOlivier Houchard 159*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_PROTOTYPE(N) \ 160*1fb62fb0SOlivier Houchard CK_RWCOHORT_RP_INSTANCE(N) { \ 161*1fb62fb0SOlivier Houchard unsigned int read_counter; \ 162*1fb62fb0SOlivier Houchard unsigned int read_barrier; \ 163*1fb62fb0SOlivier Houchard unsigned int wait_limit; \ 164*1fb62fb0SOlivier Houchard }; \ 165*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 166*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_init(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ 167*1fb62fb0SOlivier Houchard unsigned int wait_limit) \ 168*1fb62fb0SOlivier Houchard { \ 169*1fb62fb0SOlivier Houchard \ 170*1fb62fb0SOlivier Houchard rw_cohort->read_counter = 0; \ 171*1fb62fb0SOlivier Houchard rw_cohort->read_barrier = 0; \ 172*1fb62fb0SOlivier Houchard rw_cohort->wait_limit = wait_limit; \ 173*1fb62fb0SOlivier Houchard ck_pr_barrier(); \ 174*1fb62fb0SOlivier Houchard return; \ 175*1fb62fb0SOlivier Houchard } \ 176*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 177*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_write_lock(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ 178*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ 179*1fb62fb0SOlivier Houchard void *local_context) \ 180*1fb62fb0SOlivier Houchard { \ 181*1fb62fb0SOlivier Houchard unsigned int wait_count = 0; \ 182*1fb62fb0SOlivier Houchard bool raised = false; \ 183*1fb62fb0SOlivier Houchard \ 184*1fb62fb0SOlivier Houchard for (;;) { \ 185*1fb62fb0SOlivier Houchard CK_COHORT_LOCK(N, cohort, global_context, local_context); \ 186*1fb62fb0SOlivier Houchard if (ck_pr_load_uint(&rw_cohort->read_counter) == 0) \ 187*1fb62fb0SOlivier Houchard break; \ 188*1fb62fb0SOlivier Houchard \ 189*1fb62fb0SOlivier Houchard CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ 190*1fb62fb0SOlivier Houchard while (ck_pr_load_uint(&rw_cohort->read_counter) > 0) { \ 191*1fb62fb0SOlivier Houchard ck_pr_stall(); \ 192*1fb62fb0SOlivier Houchard if (++wait_count > rw_cohort->wait_limit && \ 193*1fb62fb0SOlivier Houchard raised == false) { \ 194*1fb62fb0SOlivier Houchard ck_pr_inc_uint(&rw_cohort->read_barrier); \ 195*1fb62fb0SOlivier Houchard raised = true; \ 196*1fb62fb0SOlivier Houchard } \ 197*1fb62fb0SOlivier Houchard } \ 198*1fb62fb0SOlivier Houchard } \ 199*1fb62fb0SOlivier Houchard \ 200*1fb62fb0SOlivier Houchard if (raised == true) \ 201*1fb62fb0SOlivier Houchard ck_pr_dec_uint(&rw_cohort->read_barrier); \ 202*1fb62fb0SOlivier Houchard \ 203*1fb62fb0SOlivier Houchard return; \ 204*1fb62fb0SOlivier Houchard } \ 205*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 206*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_write_unlock(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ 207*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, void *local_context) \ 208*1fb62fb0SOlivier Houchard { \ 209*1fb62fb0SOlivier Houchard \ 210*1fb62fb0SOlivier Houchard (void)rw_cohort; \ 211*1fb62fb0SOlivier Houchard CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ 212*1fb62fb0SOlivier Houchard return; \ 213*1fb62fb0SOlivier Houchard } \ 214*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 215*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_read_lock(CK_RWCOHORT_RP_INSTANCE(N) *rw_cohort, \ 216*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ 217*1fb62fb0SOlivier Houchard void *local_context) \ 218*1fb62fb0SOlivier Houchard { \ 219*1fb62fb0SOlivier Houchard \ 220*1fb62fb0SOlivier Houchard while (ck_pr_load_uint(&rw_cohort->read_barrier) > 0) \ 221*1fb62fb0SOlivier Houchard ck_pr_stall(); \ 222*1fb62fb0SOlivier Houchard \ 223*1fb62fb0SOlivier Houchard ck_pr_inc_uint(&rw_cohort->read_counter); \ 224*1fb62fb0SOlivier Houchard ck_pr_fence_atomic_load(); \ 225*1fb62fb0SOlivier Houchard \ 226*1fb62fb0SOlivier Houchard while (CK_COHORT_LOCKED(N, cohort, global_context, \ 227*1fb62fb0SOlivier Houchard local_context) == true) \ 228*1fb62fb0SOlivier Houchard ck_pr_stall(); \ 229*1fb62fb0SOlivier Houchard \ 230*1fb62fb0SOlivier Houchard return; \ 231*1fb62fb0SOlivier Houchard } \ 232*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 233*1fb62fb0SOlivier Houchard ck_rwcohort_rp_##N##_read_unlock(CK_RWCOHORT_RP_INSTANCE(N) *cohort) \ 234*1fb62fb0SOlivier Houchard { \ 235*1fb62fb0SOlivier Houchard \ 236*1fb62fb0SOlivier Houchard ck_pr_fence_load_atomic(); \ 237*1fb62fb0SOlivier Houchard ck_pr_dec_uint(&cohort->read_counter); \ 238*1fb62fb0SOlivier Houchard return; \ 239*1fb62fb0SOlivier Houchard } 240*1fb62fb0SOlivier Houchard 241*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_RP_INITIALIZER { \ 242*1fb62fb0SOlivier Houchard .read_counter = 0, \ 243*1fb62fb0SOlivier Houchard .read_barrier = 0, \ 244*1fb62fb0SOlivier Houchard .wait_limit = 0 \ 245*1fb62fb0SOlivier Houchard } 246*1fb62fb0SOlivier Houchard 247*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_NAME(N) ck_rwcohort_neutral_##N 248*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_INSTANCE(N) struct CK_RWCOHORT_NEUTRAL_NAME(N) 249*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_INIT(N, RW) ck_rwcohort_neutral_##N##_init(RW) 250*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_READ_LOCK(N, RW, C, GC, LC) \ 251*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_read_lock(RW, C, GC, LC) 252*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_READ_UNLOCK(N, RW, C, GC, LC) \ 253*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_read_unlock(RW) 254*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_WRITE_LOCK(N, RW, C, GC, LC) \ 255*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_write_lock(RW, C, GC, LC) 256*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_WRITE_UNLOCK(N, RW, C, GC, LC) \ 257*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_write_unlock(RW, C, GC, LC) 258*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_DEFAULT_WAIT_LIMIT 1000 259*1fb62fb0SOlivier Houchard 260*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_PROTOTYPE(N) \ 261*1fb62fb0SOlivier Houchard CK_RWCOHORT_NEUTRAL_INSTANCE(N) { \ 262*1fb62fb0SOlivier Houchard unsigned int read_counter; \ 263*1fb62fb0SOlivier Houchard }; \ 264*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 265*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_init(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort) \ 266*1fb62fb0SOlivier Houchard { \ 267*1fb62fb0SOlivier Houchard \ 268*1fb62fb0SOlivier Houchard rw_cohort->read_counter = 0; \ 269*1fb62fb0SOlivier Houchard ck_pr_barrier(); \ 270*1fb62fb0SOlivier Houchard return; \ 271*1fb62fb0SOlivier Houchard } \ 272*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 273*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_write_lock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort,\ 274*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ 275*1fb62fb0SOlivier Houchard void *local_context) \ 276*1fb62fb0SOlivier Houchard { \ 277*1fb62fb0SOlivier Houchard \ 278*1fb62fb0SOlivier Houchard CK_COHORT_LOCK(N, cohort, global_context, local_context); \ 279*1fb62fb0SOlivier Houchard while (ck_pr_load_uint(&rw_cohort->read_counter) > 0) { \ 280*1fb62fb0SOlivier Houchard ck_pr_stall(); \ 281*1fb62fb0SOlivier Houchard } \ 282*1fb62fb0SOlivier Houchard return; \ 283*1fb62fb0SOlivier Houchard } \ 284*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 285*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_write_unlock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort,\ 286*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, void *local_context) \ 287*1fb62fb0SOlivier Houchard { \ 288*1fb62fb0SOlivier Houchard \ 289*1fb62fb0SOlivier Houchard (void)rw_cohort; \ 290*1fb62fb0SOlivier Houchard CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ 291*1fb62fb0SOlivier Houchard return; \ 292*1fb62fb0SOlivier Houchard } \ 293*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 294*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_read_lock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *rw_cohort, \ 295*1fb62fb0SOlivier Houchard CK_COHORT_INSTANCE(N) *cohort, void *global_context, \ 296*1fb62fb0SOlivier Houchard void *local_context) \ 297*1fb62fb0SOlivier Houchard { \ 298*1fb62fb0SOlivier Houchard \ 299*1fb62fb0SOlivier Houchard CK_COHORT_LOCK(N, cohort, global_context, local_context); \ 300*1fb62fb0SOlivier Houchard ck_pr_inc_uint(&rw_cohort->read_counter); \ 301*1fb62fb0SOlivier Houchard CK_COHORT_UNLOCK(N, cohort, global_context, local_context); \ 302*1fb62fb0SOlivier Houchard return; \ 303*1fb62fb0SOlivier Houchard } \ 304*1fb62fb0SOlivier Houchard CK_CC_INLINE static void \ 305*1fb62fb0SOlivier Houchard ck_rwcohort_neutral_##N##_read_unlock(CK_RWCOHORT_NEUTRAL_INSTANCE(N) *cohort) \ 306*1fb62fb0SOlivier Houchard { \ 307*1fb62fb0SOlivier Houchard \ 308*1fb62fb0SOlivier Houchard ck_pr_fence_load_atomic(); \ 309*1fb62fb0SOlivier Houchard ck_pr_dec_uint(&cohort->read_counter); \ 310*1fb62fb0SOlivier Houchard return; \ 311*1fb62fb0SOlivier Houchard } 312*1fb62fb0SOlivier Houchard 313*1fb62fb0SOlivier Houchard #define CK_RWCOHORT_NEUTRAL_INITIALIZER { \ 314*1fb62fb0SOlivier Houchard .read_counter = 0, \ 315*1fb62fb0SOlivier Houchard } 316*1fb62fb0SOlivier Houchard 317*1fb62fb0SOlivier Houchard #endif /* CK_RWCOHORT_H */ 318