akaros/tools/compilers/gcc-glibc/gcc-4.9.2-akaros/libgomp/config/akaros/bar.h
<<
>>
Prefs
   1/* Copyright (C) 2005-2014 Free Software Foundation, Inc.
   2   Contributed by Richard Henderson <rth@redhat.com>.
   3
   4   This file is part of the GNU OpenMP Library (libgomp).
   5
   6   Libgomp is free software; you can redistribute it and/or modify it
   7   under the terms of the GNU General Public License as published by
   8   the Free Software Foundation; either version 3, or (at your option)
   9   any later version.
  10
  11   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
  12   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14   more details.
  15
  16   Under Section 7 of GPL version 3, you are granted additional
  17   permissions described in the GCC Runtime Library Exception, version
  18   3.1, as published by the Free Software Foundation.
  19
  20   You should have received a copy of the GNU General Public License and
  21   a copy of the GCC Runtime Library Exception along with this program;
  22   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23   <http://www.gnu.org/licenses/>.  */
  24
  25/* This is a Linux specific implementation of a barrier synchronization
  26   mechanism for libgomp.  This type is private to the library.  This 
  27   implementation uses atomic instructions and the futex syscall.  */
  28
  29#ifndef GOMP_BARRIER_H
  30#define GOMP_BARRIER_H 1
  31
  32#include "mutex.h"
  33
  34typedef struct
  35{
  36  /* Make sure total/generation is in a mostly read cacheline, while
  37     awaited in a separate cacheline.  */
  38  unsigned total __attribute__((aligned (64)));
  39  unsigned generation;
  40  unsigned awaited __attribute__((aligned (64)));
  41  unsigned awaited_final;
  42} gomp_barrier_t;
  43
  44typedef unsigned int gomp_barrier_state_t;
  45
  46/* The generation field contains a counter in the high bits, with a few
  47   low bits dedicated to flags.  Note that TASK_PENDING and WAS_LAST can
  48   share space because WAS_LAST is never stored back to generation.  */
  49#define BAR_TASK_PENDING        1
  50#define BAR_WAS_LAST            1
  51#define BAR_WAITING_FOR_TASK    2
  52#define BAR_CANCELLED           4
  53#define BAR_INCR                8
  54
  55static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
  56{
  57  bar->total = count;
  58  bar->awaited = count;
  59  bar->awaited_final = count;
  60  bar->generation = 0;
  61}
  62
  63static inline void gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
  64{
  65  __atomic_add_fetch (&bar->awaited, count - bar->total, MEMMODEL_ACQ_REL);
  66  bar->total = count;
  67}
  68
  69static inline void gomp_barrier_destroy (gomp_barrier_t *bar)
  70{
  71}
  72
  73extern void gomp_barrier_wait (gomp_barrier_t *);
  74extern void gomp_barrier_wait_last (gomp_barrier_t *);
  75extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t);
  76extern void gomp_team_barrier_wait (gomp_barrier_t *);
  77extern void gomp_team_barrier_wait_final (gomp_barrier_t *);
  78extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
  79                                        gomp_barrier_state_t);
  80extern bool gomp_team_barrier_wait_cancel (gomp_barrier_t *);
  81extern bool gomp_team_barrier_wait_cancel_end (gomp_barrier_t *,
  82                                               gomp_barrier_state_t);
  83extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
  84struct gomp_team;
  85extern void gomp_team_barrier_cancel (struct gomp_team *);
  86
  87static inline gomp_barrier_state_t
  88gomp_barrier_wait_start (gomp_barrier_t *bar)
  89{
  90  unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
  91  ret &= -BAR_INCR | BAR_CANCELLED;
  92  /* A memory barrier is needed before exiting from the various forms
  93     of gomp_barrier_wait, to satisfy OpenMP API version 3.1 section
  94     2.8.6 flush Construct, which says there is an implicit flush during
  95     a barrier region.  This is a convenient place to add the barrier,
  96     so we use MEMMODEL_ACQ_REL here rather than MEMMODEL_ACQUIRE.  */
  97  if (__atomic_add_fetch (&bar->awaited, -1, MEMMODEL_ACQ_REL) == 0)
  98    ret |= BAR_WAS_LAST;
  99  return ret;
 100}
 101
 102static inline gomp_barrier_state_t
 103gomp_barrier_wait_cancel_start (gomp_barrier_t *bar)
 104{
 105  return gomp_barrier_wait_start (bar);
 106}
 107
 108/* This is like gomp_barrier_wait_start, except it decrements
 109   bar->awaited_final rather than bar->awaited and should be used
 110   for the gomp_team_end barrier only.  */
 111static inline gomp_barrier_state_t
 112gomp_barrier_wait_final_start (gomp_barrier_t *bar)
 113{
 114  unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
 115  ret &= -BAR_INCR | BAR_CANCELLED;
 116  /* See above gomp_barrier_wait_start comment.  */
 117  if (__atomic_add_fetch (&bar->awaited_final, -1, MEMMODEL_ACQ_REL) == 0)
 118    ret |= BAR_WAS_LAST;
 119  return ret;
 120}
 121
 122static inline bool
 123gomp_barrier_last_thread (gomp_barrier_state_t state)
 124{
 125  return state & BAR_WAS_LAST;
 126}
 127
 128/* All the inlines below must be called with team->task_lock
 129   held.  */
 130
 131static inline void
 132gomp_team_barrier_set_task_pending (gomp_barrier_t *bar)
 133{
 134  bar->generation |= BAR_TASK_PENDING;
 135}
 136
 137static inline void
 138gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
 139{
 140  bar->generation &= ~BAR_TASK_PENDING;
 141}
 142
 143static inline void
 144gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
 145{
 146  bar->generation |= BAR_WAITING_FOR_TASK;
 147}
 148
 149static inline bool
 150gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
 151{
 152  return (bar->generation & BAR_WAITING_FOR_TASK) != 0;
 153}
 154
 155static inline bool
 156gomp_team_barrier_cancelled (gomp_barrier_t *bar)
 157{
 158  return __builtin_expect ((bar->generation & BAR_CANCELLED) != 0, 0);
 159}
 160
 161static inline void
 162gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
 163{
 164  bar->generation = (state & -BAR_INCR) + BAR_INCR;
 165}
 166
 167#endif /* GOMP_BARRIER_H */
 168