]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgomp/config/linux/lock.c
re PR fortran/64522 (Free-form source code: -Wline-truncation is no longer enabled...
[thirdparty/gcc.git] / libgomp / config / linux / lock.c
CommitLineData
5624e564 1/* Copyright (C) 2005-2015 Free Software Foundation, Inc.
953ff289
DN
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
748086b7
JJ
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.
953ff289
DN
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
748086b7 13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
953ff289
DN
14 more details.
15
748086b7
JJ
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.
953ff289 19
748086b7
JJ
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/>. */
953ff289
DN
24
25/* This is a Linux specific implementation of the public OpenMP locking
26 primitives. This implementation uses atomic instructions and the futex
27 syscall. */
28
953ff289
DN
29#include <string.h>
30#include <unistd.h>
31#include <sys/syscall.h>
a68ab351 32#include "wait.h"
953ff289
DN
33
34
35/* The internal gomp_mutex_t and the external non-recursive omp_lock_t
36 have the same form. Re-use it. */
37
38void
a68ab351 39gomp_init_lock_30 (omp_lock_t *lock)
953ff289
DN
40{
41 gomp_mutex_init (lock);
42}
43
44void
a68ab351 45gomp_destroy_lock_30 (omp_lock_t *lock)
953ff289
DN
46{
47 gomp_mutex_destroy (lock);
48}
49
50void
a68ab351 51gomp_set_lock_30 (omp_lock_t *lock)
953ff289
DN
52{
53 gomp_mutex_lock (lock);
54}
55
56void
a68ab351 57gomp_unset_lock_30 (omp_lock_t *lock)
953ff289
DN
58{
59 gomp_mutex_unlock (lock);
60}
61
62int
a68ab351 63gomp_test_lock_30 (omp_lock_t *lock)
953ff289 64{
45608a43
AM
65 int oldval = 0;
66
67 return __atomic_compare_exchange_n (lock, &oldval, 1, false,
68 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED);
953ff289
DN
69}
70
a68ab351
JJ
71void
72gomp_init_nest_lock_30 (omp_nest_lock_t *lock)
73{
74 memset (lock, '\0', sizeof (*lock));
75}
76
77void
78gomp_destroy_nest_lock_30 (omp_nest_lock_t *lock)
79{
80}
81
82void
83gomp_set_nest_lock_30 (omp_nest_lock_t *lock)
84{
85 void *me = gomp_icv (true);
86
87 if (lock->owner != me)
88 {
89 gomp_mutex_lock (&lock->lock);
90 lock->owner = me;
91 }
92
93 lock->count++;
94}
95
96void
97gomp_unset_nest_lock_30 (omp_nest_lock_t *lock)
98{
99 if (--lock->count == 0)
100 {
101 lock->owner = NULL;
102 gomp_mutex_unlock (&lock->lock);
103 }
104}
105
106int
107gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
108{
109 void *me = gomp_icv (true);
45608a43 110 int oldval;
a68ab351
JJ
111
112 if (lock->owner == me)
113 return ++lock->count;
114
45608a43
AM
115 oldval = 0;
116 if (__atomic_compare_exchange_n (&lock->lock, &oldval, 1, false,
117 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
a68ab351
JJ
118 {
119 lock->owner = me;
120 lock->count = 1;
121 return 1;
122 }
123
124 return 0;
125}
126
127#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
128/* gomp_mutex_* can be safely locked in one thread and
129 unlocked in another thread, so the OpenMP 2.5 and OpenMP 3.0
130 non-nested locks can be the same. */
131strong_alias (gomp_init_lock_30, gomp_init_lock_25)
132strong_alias (gomp_destroy_lock_30, gomp_destroy_lock_25)
133strong_alias (gomp_set_lock_30, gomp_set_lock_25)
134strong_alias (gomp_unset_lock_30, gomp_unset_lock_25)
135strong_alias (gomp_test_lock_30, gomp_test_lock_25)
136
137/* The external recursive omp_nest_lock_25_t form requires additional work. */
953ff289
DN
138
139/* We need an integer to uniquely identify this thread. Most generally
140 this is the thread's TID, which ideally we'd get this straight from
141 the TLS block where glibc keeps it. Unfortunately, we can't get at
142 that directly.
143
144 If we don't support (or have disabled) TLS, one function call is as
145 good (or bad) as any other. Use the syscall all the time.
146
147 On an ILP32 system (defined here as not LP64), we can make do with
148 any thread-local pointer. Ideally we'd use the TLS base address,
149 since that requires the least amount of arithmetic, but that's not
150 always available directly. Make do with the gomp_thread pointer
151 since it's handy. */
152
a68ab351 153# if !defined (HAVE_TLS)
953ff289
DN
154static inline int gomp_tid (void)
155{
156 return syscall (SYS_gettid);
157}
a68ab351 158# elif !defined(__LP64__)
953ff289
DN
159static inline int gomp_tid (void)
160{
161 return (int) gomp_thread ();
162}
a68ab351 163# else
953ff289
DN
164static __thread int tid_cache;
165static inline int gomp_tid (void)
166{
167 int tid = tid_cache;
168 if (__builtin_expect (tid == 0, 0))
169 tid_cache = tid = syscall (SYS_gettid);
170 return tid;
171}
a68ab351 172# endif
953ff289
DN
173
174
175void
a68ab351 176gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289 177{
43fa5db5 178 memset (lock, 0, sizeof (*lock));
953ff289
DN
179}
180
181void
a68ab351 182gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
183{
184}
185
186void
a68ab351 187gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
188{
189 int otid, tid = gomp_tid ();
190
191 while (1)
192 {
45608a43
AM
193 otid = 0;
194 if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
195 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
953ff289
DN
196 {
197 lock->count = 1;
198 return;
199 }
200 if (otid == tid)
201 {
202 lock->count++;
203 return;
204 }
205
a68ab351 206 do_wait (&lock->owner, otid);
953ff289
DN
207 }
208}
209
210void
a68ab351 211gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
212{
213 /* ??? Validate that we own the lock here. */
214
215 if (--lock->count == 0)
216 {
45608a43 217 __atomic_store_n (&lock->owner, 0, MEMMODEL_RELEASE);
953ff289
DN
218 futex_wake (&lock->owner, 1);
219 }
220}
221
222int
a68ab351 223gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
224{
225 int otid, tid = gomp_tid ();
226
45608a43
AM
227 otid = 0;
228 if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
229 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
953ff289
DN
230 {
231 lock->count = 1;
232 return 1;
233 }
234 if (otid == tid)
235 return ++lock->count;
236
237 return 0;
238}
239
a68ab351
JJ
240omp_lock_symver (omp_init_lock)
241omp_lock_symver (omp_destroy_lock)
242omp_lock_symver (omp_set_lock)
243omp_lock_symver (omp_unset_lock)
244omp_lock_symver (omp_test_lock)
245omp_lock_symver (omp_init_nest_lock)
246omp_lock_symver (omp_destroy_nest_lock)
247omp_lock_symver (omp_set_nest_lock)
248omp_lock_symver (omp_unset_nest_lock)
249omp_lock_symver (omp_test_nest_lock)
250
251#else
252
953ff289
DN
253ialias (omp_init_lock)
254ialias (omp_init_nest_lock)
255ialias (omp_destroy_lock)
256ialias (omp_destroy_nest_lock)
257ialias (omp_set_lock)
258ialias (omp_set_nest_lock)
259ialias (omp_unset_lock)
260ialias (omp_unset_nest_lock)
261ialias (omp_test_lock)
262ialias (omp_test_nest_lock)
a68ab351
JJ
263
264#endif