1*1fb62fb0SOlivier Houchard /* 2*1fb62fb0SOlivier Houchard * Copyright 2011-2015 Samy Al Bahra. 3*1fb62fb0SOlivier Houchard * Copyright 2011 David Joseph. 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 #include <ck_barrier.h> 29*1fb62fb0SOlivier Houchard #include <ck_cc.h> 30*1fb62fb0SOlivier Houchard #include <ck_pr.h> 31*1fb62fb0SOlivier Houchard #include <ck_stdbool.h> 32*1fb62fb0SOlivier Houchard 33*1fb62fb0SOlivier Houchard void 34*1fb62fb0SOlivier Houchard ck_barrier_mcs_init(struct ck_barrier_mcs *barrier, unsigned int nthr) 35*1fb62fb0SOlivier Houchard { 36*1fb62fb0SOlivier Houchard unsigned int i, j; 37*1fb62fb0SOlivier Houchard 38*1fb62fb0SOlivier Houchard ck_pr_store_uint(&barrier->tid, 0); 39*1fb62fb0SOlivier Houchard 40*1fb62fb0SOlivier Houchard for (i = 0; i < nthr; ++i) { 41*1fb62fb0SOlivier Houchard for (j = 0; j < 4; ++j) { 42*1fb62fb0SOlivier Houchard /* 43*1fb62fb0SOlivier Houchard * If there are still threads that don't have parents, 44*1fb62fb0SOlivier Houchard * add it as a child. 45*1fb62fb0SOlivier Houchard */ 46*1fb62fb0SOlivier Houchard barrier[i].havechild[j] = ((i << 2) + j < nthr - 1) ? ~0 : 0; 47*1fb62fb0SOlivier Houchard 48*1fb62fb0SOlivier Houchard /* 49*1fb62fb0SOlivier Houchard * childnotready is initialized to havechild to ensure 50*1fb62fb0SOlivier Houchard * a thread does not wait for a child that does not exist. 51*1fb62fb0SOlivier Houchard */ 52*1fb62fb0SOlivier Houchard barrier[i].childnotready[j] = barrier[i].havechild[j]; 53*1fb62fb0SOlivier Houchard } 54*1fb62fb0SOlivier Houchard 55*1fb62fb0SOlivier Houchard /* The root thread does not have a parent. */ 56*1fb62fb0SOlivier Houchard barrier[i].parent = (i == 0) ? 57*1fb62fb0SOlivier Houchard &barrier[i].dummy : 58*1fb62fb0SOlivier Houchard &barrier[(i - 1) >> 2].childnotready[(i - 1) & 3]; 59*1fb62fb0SOlivier Houchard 60*1fb62fb0SOlivier Houchard /* Leaf threads do not have any children. */ 61*1fb62fb0SOlivier Houchard barrier[i].children[0] = ((i << 1) + 1 >= nthr) ? 62*1fb62fb0SOlivier Houchard &barrier[i].dummy : 63*1fb62fb0SOlivier Houchard &barrier[(i << 1) + 1].parentsense; 64*1fb62fb0SOlivier Houchard 65*1fb62fb0SOlivier Houchard barrier[i].children[1] = ((i << 1) + 2 >= nthr) ? 66*1fb62fb0SOlivier Houchard &barrier[i].dummy : 67*1fb62fb0SOlivier Houchard &barrier[(i << 1) + 2].parentsense; 68*1fb62fb0SOlivier Houchard 69*1fb62fb0SOlivier Houchard barrier[i].parentsense = 0; 70*1fb62fb0SOlivier Houchard } 71*1fb62fb0SOlivier Houchard 72*1fb62fb0SOlivier Houchard return; 73*1fb62fb0SOlivier Houchard } 74*1fb62fb0SOlivier Houchard 75*1fb62fb0SOlivier Houchard void 76*1fb62fb0SOlivier Houchard ck_barrier_mcs_subscribe(struct ck_barrier_mcs *barrier, struct ck_barrier_mcs_state *state) 77*1fb62fb0SOlivier Houchard { 78*1fb62fb0SOlivier Houchard 79*1fb62fb0SOlivier Houchard state->sense = ~0; 80*1fb62fb0SOlivier Houchard state->vpid = ck_pr_faa_uint(&barrier->tid, 1); 81*1fb62fb0SOlivier Houchard return; 82*1fb62fb0SOlivier Houchard } 83*1fb62fb0SOlivier Houchard 84*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool 85*1fb62fb0SOlivier Houchard ck_barrier_mcs_check_children(unsigned int *childnotready) 86*1fb62fb0SOlivier Houchard { 87*1fb62fb0SOlivier Houchard 88*1fb62fb0SOlivier Houchard if (ck_pr_load_uint(&childnotready[0]) != 0) 89*1fb62fb0SOlivier Houchard return false; 90*1fb62fb0SOlivier Houchard if (ck_pr_load_uint(&childnotready[1]) != 0) 91*1fb62fb0SOlivier Houchard return false; 92*1fb62fb0SOlivier Houchard if (ck_pr_load_uint(&childnotready[2]) != 0) 93*1fb62fb0SOlivier Houchard return false; 94*1fb62fb0SOlivier Houchard if (ck_pr_load_uint(&childnotready[3]) != 0) 95*1fb62fb0SOlivier Houchard return false; 96*1fb62fb0SOlivier Houchard 97*1fb62fb0SOlivier Houchard return true; 98*1fb62fb0SOlivier Houchard } 99*1fb62fb0SOlivier Houchard 100*1fb62fb0SOlivier Houchard CK_CC_INLINE static void 101*1fb62fb0SOlivier Houchard ck_barrier_mcs_reinitialize_children(struct ck_barrier_mcs *node) 102*1fb62fb0SOlivier Houchard { 103*1fb62fb0SOlivier Houchard 104*1fb62fb0SOlivier Houchard ck_pr_store_uint(&node->childnotready[0], node->havechild[0]); 105*1fb62fb0SOlivier Houchard ck_pr_store_uint(&node->childnotready[1], node->havechild[1]); 106*1fb62fb0SOlivier Houchard ck_pr_store_uint(&node->childnotready[2], node->havechild[2]); 107*1fb62fb0SOlivier Houchard ck_pr_store_uint(&node->childnotready[3], node->havechild[3]); 108*1fb62fb0SOlivier Houchard return; 109*1fb62fb0SOlivier Houchard } 110*1fb62fb0SOlivier Houchard 111*1fb62fb0SOlivier Houchard void 112*1fb62fb0SOlivier Houchard ck_barrier_mcs(struct ck_barrier_mcs *barrier, 113*1fb62fb0SOlivier Houchard struct ck_barrier_mcs_state *state) 114*1fb62fb0SOlivier Houchard { 115*1fb62fb0SOlivier Houchard 116*1fb62fb0SOlivier Houchard /* 117*1fb62fb0SOlivier Houchard * Wait until all children have reached the barrier and are done waiting 118*1fb62fb0SOlivier Houchard * for their children. 119*1fb62fb0SOlivier Houchard */ 120*1fb62fb0SOlivier Houchard while (ck_barrier_mcs_check_children(barrier[state->vpid].childnotready) == false) 121*1fb62fb0SOlivier Houchard ck_pr_stall(); 122*1fb62fb0SOlivier Houchard 123*1fb62fb0SOlivier Houchard /* Reinitialize for next barrier. */ 124*1fb62fb0SOlivier Houchard ck_barrier_mcs_reinitialize_children(&barrier[state->vpid]); 125*1fb62fb0SOlivier Houchard 126*1fb62fb0SOlivier Houchard /* Inform parent thread and its children have arrived at the barrier. */ 127*1fb62fb0SOlivier Houchard ck_pr_store_uint(barrier[state->vpid].parent, 0); 128*1fb62fb0SOlivier Houchard 129*1fb62fb0SOlivier Houchard /* Wait until parent indicates all threads have arrived at the barrier. */ 130*1fb62fb0SOlivier Houchard if (state->vpid != 0) { 131*1fb62fb0SOlivier Houchard while (ck_pr_load_uint(&barrier[state->vpid].parentsense) != state->sense) 132*1fb62fb0SOlivier Houchard ck_pr_stall(); 133*1fb62fb0SOlivier Houchard } 134*1fb62fb0SOlivier Houchard 135*1fb62fb0SOlivier Houchard /* Inform children of successful barrier. */ 136*1fb62fb0SOlivier Houchard ck_pr_store_uint(barrier[state->vpid].children[0], state->sense); 137*1fb62fb0SOlivier Houchard ck_pr_store_uint(barrier[state->vpid].children[1], state->sense); 138*1fb62fb0SOlivier Houchard state->sense = ~state->sense; 139*1fb62fb0SOlivier Houchard ck_pr_fence_memory(); 140*1fb62fb0SOlivier Houchard return; 141*1fb62fb0SOlivier Houchard } 142