config/posix/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 the default implementation of a barrier synchronization mechanism
00026    for libgomp.  This type is private to the library.  Note that we rely on
00027    being able to adjust the barrier count while threads are blocked, so the
00028    POSIX pthread_barrier_t won't work.  */
00029 
00030 #include "libgomp.h"
00031 
00032 
00033 void
00034 gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
00035 {
00036   gomp_mutex_init (&bar->mutex1);
00037 #ifndef HAVE_SYNC_BUILTINS
00038   gomp_mutex_init (&bar->mutex2);
00039 #endif
00040   gomp_sem_init (&bar->sem1, 0);
00041   gomp_sem_init (&bar->sem2, 0);
00042   bar->total = count;
00043   bar->arrived = 0;
00044   bar->generation = 0;
00045 }
00046 
00047 void
00048 gomp_barrier_destroy (gomp_barrier_t *bar)
00049 {
00050   /* Before destroying, make sure all threads have left the barrier.  */
00051   gomp_mutex_lock (&bar->mutex1);
00052   gomp_mutex_unlock (&bar->mutex1);
00053 
00054   gomp_mutex_destroy (&bar->mutex1);
00055 #ifndef HAVE_SYNC_BUILTINS
00056   gomp_mutex_destroy (&bar->mutex2);
00057 #endif
00058   gomp_sem_destroy (&bar->sem1);
00059   gomp_sem_destroy (&bar->sem2);
00060 }
00061 
00062 void
00063 gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
00064 {
00065   gomp_mutex_lock (&bar->mutex1);
00066   bar->total = count;
00067   gomp_mutex_unlock (&bar->mutex1);
00068 }
00069 
00070 void
00071 gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
00072 {
00073   unsigned int n;
00074 
00075   if (state & 1)
00076     {
00077       n = --bar->arrived;
00078       if (n > 0)
00079     {
00080       do
00081         gomp_sem_post (&bar->sem1);
00082       while (--n != 0);
00083       gomp_sem_wait (&bar->sem2);
00084     }
00085       gomp_mutex_unlock (&bar->mutex1);
00086     }
00087   else
00088     {
00089       gomp_mutex_unlock (&bar->mutex1);
00090       gomp_sem_wait (&bar->sem1);
00091 
00092 #ifdef HAVE_SYNC_BUILTINS
00093       n = __sync_add_and_fetch (&bar->arrived, -1);
00094 #else
00095       gomp_mutex_lock (&bar->mutex2);
00096       n = --bar->arrived;
00097       gomp_mutex_unlock (&bar->mutex2);
00098 #endif
00099 
00100       if (n == 0)
00101     gomp_sem_post (&bar->sem2);
00102     }
00103 }
00104 
00105 void
00106 gomp_barrier_wait (gomp_barrier_t *barrier)
00107 {
00108   gomp_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier));
00109 }
00110 
00111 void
00112 gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
00113 {
00114   unsigned int n;
00115 
00116   if (state & 1)
00117     {
00118       n = --bar->arrived;
00119       struct gomp_thread *thr = gomp_thread ();
00120       struct gomp_team *team = thr->ts.team;
00121 
00122       if (team->task_count)
00123     {
00124       gomp_barrier_handle_tasks (state);
00125       if (n > 0)
00126         gomp_sem_wait (&bar->sem2);
00127       gomp_mutex_unlock (&bar->mutex1);
00128       return;
00129     }
00130 
00131       bar->generation = state + 3;
00132       if (n > 0)
00133     {
00134       do
00135         gomp_sem_post (&bar->sem1);
00136       while (--n != 0);
00137       gomp_sem_wait (&bar->sem2);
00138     }
00139       gomp_mutex_unlock (&bar->mutex1);
00140     }
00141   else
00142     {
00143       gomp_mutex_unlock (&bar->mutex1);
00144       do
00145     {
00146       gomp_sem_wait (&bar->sem1);
00147       if (bar->generation & 1)
00148         gomp_barrier_handle_tasks (state);
00149     }
00150       while (bar->generation != state + 4);
00151 
00152 #ifdef HAVE_SYNC_BUILTINS
00153       n = __sync_add_and_fetch (&bar->arrived, -1);
00154 #else
00155       gomp_mutex_lock (&bar->mutex2);
00156       n = --bar->arrived;
00157       gomp_mutex_unlock (&bar->mutex2);
00158 #endif
00159 
00160       if (n == 0)
00161     gomp_sem_post (&bar->sem2);
00162     }
00163 }
00164 
00165 void
00166 gomp_team_barrier_wait (gomp_barrier_t *barrier)
00167 {
00168   gomp_team_barrier_wait_end (barrier, gomp_barrier_wait_start (barrier));
00169 }
00170 
00171 void
00172 gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
00173 {
00174   if (count == 0)
00175     count = bar->total - 1;
00176   while (count-- > 0)
00177     gomp_sem_post (&bar->sem1);
00178 }

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