00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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 }