0
|
1 /* Copyright (C) 2005, 2009 Free Software Foundation, Inc.
|
|
2 Contributed by Richard Henderson <rth@redhat.com>.
|
|
3
|
|
4 This file is part of the GNU OpenMP Library (libgomp).
|
|
5
|
|
6 Libgomp is free software; you can redistribute it and/or modify it
|
|
7 under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 3, or (at your option)
|
|
9 any later version.
|
|
10
|
|
11 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
14 more details.
|
|
15
|
|
16 Under Section 7 of GPL version 3, you are granted additional
|
|
17 permissions described in the GCC Runtime Library Exception, version
|
|
18 3.1, as published by the Free Software Foundation.
|
|
19
|
|
20 You should have received a copy of the GNU General Public License and
|
|
21 a copy of the GCC Runtime Library Exception along with this program;
|
|
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
23 <http://www.gnu.org/licenses/>. */
|
|
24
|
|
25 /* This file handles the CRITICAL construct. */
|
|
26
|
|
27 #include "libgomp.h"
|
|
28 #include <stdlib.h>
|
|
29
|
|
30
|
|
31 static gomp_mutex_t default_lock;
|
|
32
|
|
33 void
|
|
34 GOMP_critical_start (void)
|
|
35 {
|
|
36 gomp_mutex_lock (&default_lock);
|
|
37 }
|
|
38
|
|
39 void
|
|
40 GOMP_critical_end (void)
|
|
41 {
|
|
42 gomp_mutex_unlock (&default_lock);
|
|
43 }
|
|
44
|
|
45 #ifndef HAVE_SYNC_BUILTINS
|
|
46 static gomp_mutex_t create_lock_lock;
|
|
47 #endif
|
|
48
|
|
49 void
|
|
50 GOMP_critical_name_start (void **pptr)
|
|
51 {
|
|
52 gomp_mutex_t *plock;
|
|
53
|
|
54 /* If a mutex fits within the space for a pointer, and is zero initialized,
|
|
55 then use the pointer space directly. */
|
|
56 if (GOMP_MUTEX_INIT_0
|
|
57 && sizeof (gomp_mutex_t) <= sizeof (void *)
|
|
58 && __alignof (gomp_mutex_t) <= sizeof (void *))
|
|
59 plock = (gomp_mutex_t *)pptr;
|
|
60
|
|
61 /* Otherwise we have to be prepared to malloc storage. */
|
|
62 else
|
|
63 {
|
|
64 plock = *pptr;
|
|
65
|
|
66 if (plock == NULL)
|
|
67 {
|
|
68 #ifdef HAVE_SYNC_BUILTINS
|
|
69 gomp_mutex_t *nlock = gomp_malloc (sizeof (gomp_mutex_t));
|
|
70 gomp_mutex_init (nlock);
|
|
71
|
|
72 plock = __sync_val_compare_and_swap (pptr, NULL, nlock);
|
|
73 if (plock != NULL)
|
|
74 {
|
|
75 gomp_mutex_destroy (nlock);
|
|
76 free (nlock);
|
|
77 }
|
|
78 else
|
|
79 plock = nlock;
|
|
80 #else
|
|
81 gomp_mutex_lock (&create_lock_lock);
|
|
82 plock = *pptr;
|
|
83 if (plock == NULL)
|
|
84 {
|
|
85 plock = gomp_malloc (sizeof (gomp_mutex_t));
|
|
86 gomp_mutex_init (plock);
|
|
87 __sync_synchronize ();
|
|
88 *pptr = plock;
|
|
89 }
|
|
90 gomp_mutex_unlock (&create_lock_lock);
|
|
91 #endif
|
|
92 }
|
|
93 }
|
|
94
|
|
95 gomp_mutex_lock (plock);
|
|
96 }
|
|
97
|
|
98 void
|
|
99 GOMP_critical_name_end (void **pptr)
|
|
100 {
|
|
101 gomp_mutex_t *plock;
|
|
102
|
|
103 /* If a mutex fits within the space for a pointer, and is zero initialized,
|
|
104 then use the pointer space directly. */
|
|
105 if (GOMP_MUTEX_INIT_0
|
|
106 && sizeof (gomp_mutex_t) <= sizeof (void *)
|
|
107 && __alignof (gomp_mutex_t) <= sizeof (void *))
|
|
108 plock = (gomp_mutex_t *)pptr;
|
|
109 else
|
|
110 plock = *pptr;
|
|
111
|
|
112 gomp_mutex_unlock (plock);
|
|
113 }
|
|
114
|
|
115 /* This mutex is used when atomic operations don't exist for the target
|
|
116 in the mode requested. The result is not globally atomic, but works so
|
|
117 long as all parallel references are within #pragma omp atomic directives.
|
|
118 According to responses received from omp@openmp.org, appears to be within
|
|
119 spec. Which makes sense, since that's how several other compilers
|
|
120 handle this situation as well. */
|
|
121
|
|
122 static gomp_mutex_t atomic_lock;
|
|
123
|
|
124 void
|
|
125 GOMP_atomic_start (void)
|
|
126 {
|
|
127 gomp_mutex_lock (&atomic_lock);
|
|
128 }
|
|
129
|
|
130 void
|
|
131 GOMP_atomic_end (void)
|
|
132 {
|
|
133 gomp_mutex_unlock (&atomic_lock);
|
|
134 }
|
|
135
|
|
136 #if !GOMP_MUTEX_INIT_0
|
|
137 static void __attribute__((constructor))
|
|
138 initialize_critical (void)
|
|
139 {
|
|
140 gomp_mutex_init (&default_lock);
|
|
141 gomp_mutex_init (&atomic_lock);
|
|
142 #ifndef HAVE_SYNC_BUILTINS
|
|
143 gomp_mutex_init (&create_lock_lock);
|
|
144 #endif
|
|
145 }
|
|
146 #endif
|