]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libgomp/config/linux/lock.c
1 /* Copyright (C) 2005, 2008 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU OpenMP Library (libgomp).
6 Libgomp is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
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 Lesser General Public License for
16 You should have received a copy of the GNU Lesser General Public License
17 along with libgomp; see the file COPYING.LIB. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 MA 02110-1301, USA. */
21 /* As a special exception, if you link this library with other files, some
22 of which are compiled with GCC, to produce an executable, this library
23 does not by itself cause the resulting executable to be covered by the
24 GNU General Public License. This exception does not however invalidate
25 any other reasons why the executable file might be covered by the GNU
26 General Public License. */
28 /* This is a Linux specific implementation of the public OpenMP locking
29 primitives. This implementation uses atomic instructions and the futex
34 #include <sys/syscall.h>
38 /* The internal gomp_mutex_t and the external non-recursive omp_lock_t
39 have the same form. Re-use it. */
42 gomp_init_lock_30 (omp_lock_t
*lock
)
44 gomp_mutex_init (lock
);
48 gomp_destroy_lock_30 (omp_lock_t
*lock
)
50 gomp_mutex_destroy (lock
);
54 gomp_set_lock_30 (omp_lock_t
*lock
)
56 gomp_mutex_lock (lock
);
60 gomp_unset_lock_30 (omp_lock_t
*lock
)
62 gomp_mutex_unlock (lock
);
66 gomp_test_lock_30 (omp_lock_t
*lock
)
68 return __sync_bool_compare_and_swap (lock
, 0, 1);
72 gomp_init_nest_lock_30 (omp_nest_lock_t
*lock
)
74 memset (lock
, '\0', sizeof (*lock
));
78 gomp_destroy_nest_lock_30 (omp_nest_lock_t
*lock
)
83 gomp_set_nest_lock_30 (omp_nest_lock_t
*lock
)
85 void *me
= gomp_icv (true);
87 if (lock
->owner
!= me
)
89 gomp_mutex_lock (&lock
->lock
);
97 gomp_unset_nest_lock_30 (omp_nest_lock_t
*lock
)
99 if (--lock
->count
== 0)
102 gomp_mutex_unlock (&lock
->lock
);
107 gomp_test_nest_lock_30 (omp_nest_lock_t
*lock
)
109 void *me
= gomp_icv (true);
111 if (lock
->owner
== me
)
112 return ++lock
->count
;
114 if (__sync_bool_compare_and_swap (&lock
->lock
, 0, 1))
124 #ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
125 /* gomp_mutex_* can be safely locked in one thread and
126 unlocked in another thread, so the OpenMP 2.5 and OpenMP 3.0
127 non-nested locks can be the same. */
128 strong_alias (gomp_init_lock_30
, gomp_init_lock_25
)
129 strong_alias (gomp_destroy_lock_30
, gomp_destroy_lock_25
)
130 strong_alias (gomp_set_lock_30
, gomp_set_lock_25
)
131 strong_alias (gomp_unset_lock_30
, gomp_unset_lock_25
)
132 strong_alias (gomp_test_lock_30
, gomp_test_lock_25
)
134 /* The external recursive omp_nest_lock_25_t form requires additional work. */
136 /* We need an integer to uniquely identify this thread. Most generally
137 this is the thread's TID, which ideally we'd get this straight from
138 the TLS block where glibc keeps it. Unfortunately, we can't get at
141 If we don't support (or have disabled) TLS, one function call is as
142 good (or bad) as any other. Use the syscall all the time.
144 On an ILP32 system (defined here as not LP64), we can make do with
145 any thread-local pointer. Ideally we'd use the TLS base address,
146 since that requires the least amount of arithmetic, but that's not
147 always available directly. Make do with the gomp_thread pointer
150 # if !defined (HAVE_TLS)
151 static inline int gomp_tid (void)
153 return syscall (SYS_gettid
);
155 # elif !defined(__LP64__)
156 static inline int gomp_tid (void)
158 return (int) gomp_thread ();
161 static __thread
int tid_cache
;
162 static inline int gomp_tid (void)
165 if (__builtin_expect (tid
== 0, 0))
166 tid_cache
= tid
= syscall (SYS_gettid
);
173 gomp_init_nest_lock_25 (omp_nest_lock_25_t
*lock
)
175 memset (lock
, 0, sizeof (lock
));
179 gomp_destroy_nest_lock_25 (omp_nest_lock_25_t
*lock
)
184 gomp_set_nest_lock_25 (omp_nest_lock_25_t
*lock
)
186 int otid
, tid
= gomp_tid ();
190 otid
= __sync_val_compare_and_swap (&lock
->owner
, 0, tid
);
202 do_wait (&lock
->owner
, otid
);
207 gomp_unset_nest_lock_25 (omp_nest_lock_25_t
*lock
)
209 /* ??? Validate that we own the lock here. */
211 if (--lock
->count
== 0)
213 __sync_lock_release (&lock
->owner
);
214 futex_wake (&lock
->owner
, 1);
219 gomp_test_nest_lock_25 (omp_nest_lock_25_t
*lock
)
221 int otid
, tid
= gomp_tid ();
223 otid
= __sync_val_compare_and_swap (&lock
->owner
, 0, tid
);
230 return ++lock
->count
;
235 omp_lock_symver (omp_init_lock
)
236 omp_lock_symver (omp_destroy_lock
)
237 omp_lock_symver (omp_set_lock
)
238 omp_lock_symver (omp_unset_lock
)
239 omp_lock_symver (omp_test_lock
)
240 omp_lock_symver (omp_init_nest_lock
)
241 omp_lock_symver (omp_destroy_nest_lock
)
242 omp_lock_symver (omp_set_nest_lock
)
243 omp_lock_symver (omp_unset_nest_lock
)
244 omp_lock_symver (omp_test_nest_lock
)
248 ialias (omp_init_lock
)
249 ialias (omp_init_nest_lock
)
250 ialias (omp_destroy_lock
)
251 ialias (omp_destroy_nest_lock
)
252 ialias (omp_set_lock
)
253 ialias (omp_set_nest_lock
)
254 ialias (omp_unset_lock
)
255 ialias (omp_unset_nest_lock
)
256 ialias (omp_test_lock
)
257 ialias (omp_test_nest_lock
)