critical.c

Go to the documentation of this file.
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

Generated on Fri Apr 5 05:38:09 2013 for Libgomp by  doxygen 1.4.7