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 #ifndef GOMP_BARRIER_H 00031 #define GOMP_BARRIER_H 1 00032 00033 #include <pthread.h> 00034 00035 typedef struct 00036 { 00037 gomp_mutex_t mutex1; 00038 #ifndef HAVE_SYNC_BUILTINS 00039 gomp_mutex_t mutex2; 00040 #endif 00041 gomp_sem_t sem1; 00042 gomp_sem_t sem2; 00043 unsigned total; 00044 unsigned arrived; 00045 unsigned generation; 00046 } gomp_barrier_t; 00047 typedef unsigned int gomp_barrier_state_t; 00048 00049 extern void gomp_barrier_init (gomp_barrier_t *, unsigned); 00050 extern void gomp_barrier_reinit (gomp_barrier_t *, unsigned); 00051 extern void gomp_barrier_destroy (gomp_barrier_t *); 00052 00053 extern void gomp_barrier_wait (gomp_barrier_t *); 00054 extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t); 00055 extern void gomp_team_barrier_wait (gomp_barrier_t *); 00056 extern void gomp_team_barrier_wait_end (gomp_barrier_t *, 00057 gomp_barrier_state_t); 00058 extern void gomp_team_barrier_wake (gomp_barrier_t *, int); 00059 00060 static inline gomp_barrier_state_t 00061 gomp_barrier_wait_start (gomp_barrier_t *bar) 00062 { 00063 unsigned int ret; 00064 gomp_mutex_lock (&bar->mutex1); 00065 ret = bar->generation & ~3; 00066 ret += ++bar->arrived == bar->total; 00067 return ret; 00068 } 00069 00070 static inline bool 00071 gomp_barrier_last_thread (gomp_barrier_state_t state) 00072 { 00073 return state & 1; 00074 } 00075 00076 static inline void 00077 gomp_barrier_wait_last (gomp_barrier_t *bar) 00078 { 00079 gomp_barrier_wait (bar); 00080 } 00081 00082 /* All the inlines below must be called with team->task_lock 00083 held. */ 00084 00085 static inline void 00086 gomp_team_barrier_set_task_pending (gomp_barrier_t *bar) 00087 { 00088 bar->generation |= 1; 00089 } 00090 00091 static inline void 00092 gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar) 00093 { 00094 bar->generation &= ~1; 00095 } 00096 00097 static inline void 00098 gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar) 00099 { 00100 bar->generation |= 2; 00101 } 00102 00103 static inline bool 00104 gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar) 00105 { 00106 return (bar->generation & 2) != 0; 00107 } 00108 00109 static inline void 00110 gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state) 00111 { 00112 bar->generation = (state & ~3) + 4; 00113 } 00114 00115 #endif /* GOMP_BARRIER_H */