Path: blob/main/sys/contrib/ck/src/ck_barrier_dissemination.c
48266 views
/*1* Copyright 2011-2015 Samy Al Bahra.2* Copyright 2011 David Joseph.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#include <ck_barrier.h>28#include <ck_cc.h>29#include <ck_pr.h>30#include <ck_spinlock.h>3132#include "ck_internal.h"3334void35ck_barrier_dissemination_init(struct ck_barrier_dissemination *barrier,36struct ck_barrier_dissemination_flag **barrier_internal,37unsigned int nthr)38{39unsigned int i, j, k, size, offset;40bool p = nthr & (nthr - 1);4142barrier->nthr = nthr;43barrier->size = size = ck_internal_log(ck_internal_power_2(nthr));44ck_pr_store_uint(&barrier->tid, 0);4546for (i = 0; i < nthr; ++i) {47barrier[i].flags[0] = barrier_internal[i];48barrier[i].flags[1] = barrier_internal[i] + size;49}5051for (i = 0; i < nthr; ++i) {52for (k = 0, offset = 1; k < size; ++k, offset <<= 1) {53/*54* Determine the thread's partner, j, for the current round, k.55* Partners are chosen such that by the completion of the barrier,56* every thread has been directly (having one of its flag set) or57* indirectly (having one of its partners's flags set) signaled58* by every other thread in the barrier.59*/60if (p == false)61j = (i + offset) & (nthr - 1);62else63j = (i + offset) % nthr;6465/* Set the thread's partner for round k. */66barrier[i].flags[0][k].pflag = &barrier[j].flags[0][k].tflag;67barrier[i].flags[1][k].pflag = &barrier[j].flags[1][k].tflag;6869/* Set the thread's flags to false. */70barrier[i].flags[0][k].tflag = barrier[i].flags[1][k].tflag = 0;71}72}7374return;75}7677void78ck_barrier_dissemination_subscribe(struct ck_barrier_dissemination *barrier,79struct ck_barrier_dissemination_state *state)80{8182state->parity = 0;83state->sense = ~0;84state->tid = ck_pr_faa_uint(&barrier->tid, 1);85return;86}8788unsigned int89ck_barrier_dissemination_size(unsigned int nthr)90{9192return (ck_internal_log(ck_internal_power_2(nthr)) << 1);93}9495void96ck_barrier_dissemination(struct ck_barrier_dissemination *barrier,97struct ck_barrier_dissemination_state *state)98{99unsigned int i;100unsigned int size = barrier->size;101102for (i = 0; i < size; ++i) {103unsigned int *pflag, *tflag;104105pflag = barrier[state->tid].flags[state->parity][i].pflag;106tflag = &barrier[state->tid].flags[state->parity][i].tflag;107108/* Unblock current partner. */109ck_pr_store_uint(pflag, state->sense);110111/* Wait until some other thread unblocks this one. */112while (ck_pr_load_uint(tflag) != state->sense)113ck_pr_stall();114}115116/*117* Dissemination barriers use two sets of flags to prevent race conditions118* between successive calls to the barrier. Parity indicates which set will119* be used for the next barrier. They also use a sense reversal technique120* to avoid re-initialization of the flags for every two calls to the barrier.121*/122if (state->parity == 1)123state->sense = ~state->sense;124125state->parity = 1 - state->parity;126127ck_pr_fence_acquire();128return;129}130131132