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 file handles the SINGLE construct. */ 00026 00027 #include "libgomp.h" 00028 00029 00030 /* This routine is called when first encountering a SINGLE construct that 00031 doesn't have a COPYPRIVATE clause. Returns true if this is the thread 00032 that should execute the clause. */ 00033 00034 bool 00035 GOMP_single_start (void) 00036 { 00037 #ifdef HAVE_SYNC_BUILTINS 00038 struct gomp_thread *thr = gomp_thread (); 00039 struct gomp_team *team = thr->ts.team; 00040 unsigned long single_count; 00041 00042 if (__builtin_expect (team == NULL, 0)) 00043 return true; 00044 00045 single_count = thr->ts.single_count++; 00046 return __sync_bool_compare_and_swap (&team->single_count, single_count, 00047 single_count + 1L); 00048 #else 00049 bool ret = gomp_work_share_start (false); 00050 if (ret) 00051 gomp_work_share_init_done (); 00052 gomp_work_share_end_nowait (); 00053 return ret; 00054 #endif 00055 } 00056 00057 /* This routine is called when first encountering a SINGLE construct that 00058 does have a COPYPRIVATE clause. Returns NULL if this is the thread 00059 that should execute the clause; otherwise the return value is pointer 00060 given to GOMP_single_copy_end by the thread that did execute the clause. */ 00061 00062 void * 00063 GOMP_single_copy_start (void) 00064 { 00065 struct gomp_thread *thr = gomp_thread (); 00066 00067 bool first; 00068 void *ret; 00069 00070 first = gomp_work_share_start (false); 00071 00072 if (first) 00073 { 00074 gomp_work_share_init_done (); 00075 ret = NULL; 00076 } 00077 else 00078 { 00079 gomp_team_barrier_wait (&thr->ts.team->barrier); 00080 00081 ret = thr->ts.work_share->copyprivate; 00082 gomp_work_share_end_nowait (); 00083 } 00084 00085 return ret; 00086 } 00087 00088 /* This routine is called when the thread that entered a SINGLE construct 00089 with a COPYPRIVATE clause gets to the end of the construct. */ 00090 00091 void 00092 GOMP_single_copy_end (void *data) 00093 { 00094 struct gomp_thread *thr = gomp_thread (); 00095 struct gomp_team *team = thr->ts.team; 00096 00097 if (team != NULL) 00098 { 00099 thr->ts.work_share->copyprivate = data; 00100 gomp_team_barrier_wait (&team->barrier); 00101 } 00102 00103 gomp_work_share_end_nowait (); 00104 }