00001 /* Copyright (C) 2005, 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 CRITICAL construct. */ 00026 00027 #include "libgomp.h" 00028 #include <stdlib.h> 00029 00030 00031 static gomp_mutex_t default_lock; 00032 00033 void 00034 GOMP_critical_start (void) 00035 { 00036 gomp_mutex_lock (&default_lock); 00037 } 00038 00039 void 00040 GOMP_critical_end (void) 00041 { 00042 gomp_mutex_unlock (&default_lock); 00043 } 00044 00045 #ifndef HAVE_SYNC_BUILTINS 00046 static gomp_mutex_t create_lock_lock; 00047 #endif 00048 00049 void 00050 GOMP_critical_name_start (void **pptr) 00051 { 00052 gomp_mutex_t *plock; 00053 00054 /* If a mutex fits within the space for a pointer, and is zero initialized, 00055 then use the pointer space directly. */ 00056 if (GOMP_MUTEX_INIT_0 00057 && sizeof (gomp_mutex_t) <= sizeof (void *) 00058 && __alignof (gomp_mutex_t) <= sizeof (void *)) 00059 plock = (gomp_mutex_t *)pptr; 00060 00061 /* Otherwise we have to be prepared to malloc storage. */ 00062 else 00063 { 00064 plock = *pptr; 00065 00066 if (plock == NULL) 00067 { 00068 #ifdef HAVE_SYNC_BUILTINS 00069 gomp_mutex_t *nlock = gomp_malloc (sizeof (gomp_mutex_t)); 00070 gomp_mutex_init (nlock); 00071 00072 plock = __sync_val_compare_and_swap (pptr, NULL, nlock); 00073 if (plock != NULL) 00074 { 00075 gomp_mutex_destroy (nlock); 00076 free (nlock); 00077 } 00078 else 00079 plock = nlock; 00080 #else 00081 gomp_mutex_lock (&create_lock_lock); 00082 plock = *pptr; 00083 if (plock == NULL) 00084 { 00085 plock = gomp_malloc (sizeof (gomp_mutex_t)); 00086 gomp_mutex_init (plock); 00087 __sync_synchronize (); 00088 *pptr = plock; 00089 } 00090 gomp_mutex_unlock (&create_lock_lock); 00091 #endif 00092 } 00093 } 00094 00095 gomp_mutex_lock (plock); 00096 } 00097 00098 void 00099 GOMP_critical_name_end (void **pptr) 00100 { 00101 gomp_mutex_t *plock; 00102 00103 /* If a mutex fits within the space for a pointer, and is zero initialized, 00104 then use the pointer space directly. */ 00105 if (GOMP_MUTEX_INIT_0 00106 && sizeof (gomp_mutex_t) <= sizeof (void *) 00107 && __alignof (gomp_mutex_t) <= sizeof (void *)) 00108 plock = (gomp_mutex_t *)pptr; 00109 else 00110 plock = *pptr; 00111 00112 gomp_mutex_unlock (plock); 00113 } 00114 00115 /* This mutex is used when atomic operations don't exist for the target 00116 in the mode requested. The result is not globally atomic, but works so 00117 long as all parallel references are within #pragma omp atomic directives. 00118 According to responses received from omp@openmp.org, appears to be within 00119 spec. Which makes sense, since that's how several other compilers 00120 handle this situation as well. */ 00121 00122 static gomp_mutex_t atomic_lock; 00123 00124 void 00125 GOMP_atomic_start (void) 00126 { 00127 gomp_mutex_lock (&atomic_lock); 00128 } 00129 00130 void 00131 GOMP_atomic_end (void) 00132 { 00133 gomp_mutex_unlock (&atomic_lock); 00134 } 00135 00136 #if !GOMP_MUTEX_INIT_0 00137 static void __attribute__((constructor)) 00138 initialize_critical (void) 00139 { 00140 gomp_mutex_init (&default_lock); 00141 gomp_mutex_init (&atomic_lock); 00142 #ifndef HAVE_SYNC_BUILTINS 00143 gomp_mutex_init (&create_lock_lock); 00144 #endif 00145 } 00146 #endif