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 #ifndef GOMP_BARRIER_H 00030 #define GOMP_BARRIER_H 1 00031 00032 #include "mutex.h" 00033 00034 typedef struct 00035 { 00036 /* Make sure total/generation is in a mostly read cacheline, while 00037 awaited in a separate cacheline. */ 00038 unsigned total __attribute__((aligned (64))); 00039 unsigned generation; 00040 unsigned awaited __attribute__((aligned (64))); 00041 } gomp_barrier_t; 00042 typedef unsigned int gomp_barrier_state_t; 00043 00044 static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count) 00045 { 00046 bar->total = count; 00047 bar->awaited = count; 00048 bar->generation = 0; 00049 } 00050 00051 static inline void gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count) 00052 { 00053 __sync_fetch_and_add (&bar->awaited, count - bar->total); 00054 bar->total = count; 00055 } 00056 00057 static inline void gomp_barrier_destroy (gomp_barrier_t *bar) 00058 { 00059 } 00060 00061 extern void gomp_barrier_wait (gomp_barrier_t *); 00062 extern void gomp_barrier_wait_last (gomp_barrier_t *); 00063 extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t); 00064 extern void gomp_team_barrier_wait (gomp_barrier_t *); 00065 extern void gomp_team_barrier_wait_end (gomp_barrier_t *, 00066 gomp_barrier_state_t); 00067 extern void gomp_team_barrier_wake (gomp_barrier_t *, int); 00068 00069 static inline gomp_barrier_state_t 00070 gomp_barrier_wait_start (gomp_barrier_t *bar) 00071 { 00072 unsigned int ret = bar->generation & ~3; 00073 /* Do we need any barrier here or is __sync_add_and_fetch acting 00074 as the needed LoadLoad barrier already? */ 00075 ret += __sync_add_and_fetch (&bar->awaited, -1) == 0; 00076 return ret; 00077 } 00078 00079 static inline bool 00080 gomp_barrier_last_thread (gomp_barrier_state_t state) 00081 { 00082 return state & 1; 00083 } 00084 00085 /* All the inlines below must be called with team->task_lock 00086 held. */ 00087 00088 static inline void 00089 gomp_team_barrier_set_task_pending (gomp_barrier_t *bar) 00090 { 00091 bar->generation |= 1; 00092 } 00093 00094 static inline void 00095 gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar) 00096 { 00097 bar->generation &= ~1; 00098 } 00099 00100 static inline void 00101 gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar) 00102 { 00103 bar->generation |= 2; 00104 } 00105 00106 static inline bool 00107 gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar) 00108 { 00109 return (bar->generation & 2) != 0; 00110 } 00111 00112 static inline void 00113 gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state) 00114 { 00115 bar->generation = (state & ~3) + 4; 00116 } 00117 00118 #endif /* GOMP_BARRIER_H */