config/linux/bar.c

Go to the documentation of this file.
00001 /* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
00002    Contributed by Richard Henderson <rth@redhat.com>.
00003 
00004    This file is part of the GNU OpenMP Library (libgomp).
00005 
00006    Libgomp is free software; you can redistribute it and/or modify it
00007    under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3, or (at your option)
00009    any later version.
00010 
00011    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
00012    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00014    more details.
00015 
00016    Under Section 7 of GPL version 3, you are granted additional
00017    permissions described in the GCC Runtime Library Exception, version
00018    3.1, as published by the Free Software Foundation.
00019 
00020    You should have received a copy of the GNU General Public License and
00021    a copy of the GCC Runtime Library Exception along with this program;
00022    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023    <http://www.gnu.org/licenses/>.  */
00024 
00025 /* This is a Linux specific implementation of a barrier synchronization
00026    mechanism for libgomp.  This type is private to the library.  This 
00027    implementation uses atomic instructions and the futex syscall.  */
00028 
00029 #include <limits.h>
00030 #include "wait.h"
00031 
00032 
00033 void
00034 gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
00035 {
00036   if (__builtin_expect ((state & 1) != 0, 0))
00037     {
00038       /* Next time we'll be awaiting TOTAL threads again.  */
00039       bar->awaited = bar->total;
00040       atomic_write_barrier ();
00041       bar->generation += 4;
00042       futex_wake ((int *) &bar->generation, INT_MAX);
00043     }
00044   else
00045     {
00046       unsigned int generation = state;
00047 
00048       do
00049     do_wait ((int *) &bar->generation, generation);
00050       while (bar->generation == generation);
00051     }
00052 }
00053 
00054 void
00055 gomp_barrier_wait (gomp_barrier_t *bar)
00056 {
00057   gomp_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
00058 }
00059 
00060 /* Like gomp_barrier_wait, except that if the encountering thread
00061    is not the last one to hit the barrier, it returns immediately.
00062    The intended usage is that a thread which intends to gomp_barrier_destroy
00063    this barrier calls gomp_barrier_wait, while all other threads
00064    call gomp_barrier_wait_last.  When gomp_barrier_wait returns,
00065    the barrier can be safely destroyed.  */
00066 
00067 void
00068 gomp_barrier_wait_last (gomp_barrier_t *bar)
00069 {
00070   gomp_barrier_state_t state = gomp_barrier_wait_start (bar);
00071   if (state & 1)
00072     gomp_barrier_wait_end (bar, state);
00073 }
00074 
00075 void
00076 gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
00077 {
00078   futex_wake ((int *) &bar->generation, count == 0 ? INT_MAX : count);
00079 }
00080 
00081 void
00082 gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
00083 {
00084   unsigned int generation;
00085 
00086   if (__builtin_expect ((state & 1) != 0, 0))
00087     {
00088       /* Next time we'll be awaiting TOTAL threads again.  */
00089       struct gomp_thread *thr = gomp_thread ();
00090       struct gomp_team *team = thr->ts.team;
00091       bar->awaited = bar->total;
00092       atomic_write_barrier ();
00093       if (__builtin_expect (team->task_count, 0))
00094     {
00095       gomp_barrier_handle_tasks (state);
00096       state &= ~1;
00097     }
00098       else
00099     {
00100       bar->generation = state + 3;
00101       futex_wake ((int *) &bar->generation, INT_MAX);
00102       return;
00103     }
00104     }
00105 
00106   generation = state;
00107   do
00108     {
00109       do_wait ((int *) &bar->generation, generation);
00110       if (__builtin_expect (bar->generation & 1, 0))
00111     gomp_barrier_handle_tasks (state);
00112       if ((bar->generation & 2))
00113     generation |= 2;
00114     }
00115   while (bar->generation != state + 4);
00116 }
00117 
00118 void
00119 gomp_team_barrier_wait (gomp_barrier_t *bar)
00120 {
00121   gomp_team_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
00122 }

Generated on Fri Apr 5 05:38:09 2013 for Libgomp by  doxygen 1.4.7