]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgomp/config/linux/lock.c
Update copyright years.
[thirdparty/gcc.git] / libgomp / config / linux / lock.c
CommitLineData
fbd26352 1/* Copyright (C) 2005-2019 Free Software Foundation, Inc.
1e8e9920 2 Contributed by Richard Henderson <rth@redhat.com>.
3
c35c9a62 4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
1e8e9920 6
7 Libgomp is free software; you can redistribute it and/or modify it
6bc9506f 8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
1e8e9920 11
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
6bc9506f 14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1e8e9920 15 more details.
16
6bc9506f 17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
1e8e9920 20
6bc9506f 21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
1e8e9920 25
26/* This is a Linux specific implementation of the public OpenMP locking
27 primitives. This implementation uses atomic instructions and the futex
28 syscall. */
29
1e8e9920 30#include <string.h>
31#include <unistd.h>
32#include <sys/syscall.h>
fd6481cf 33#include "wait.h"
1e8e9920 34
44a69dfd 35/* Reuse the generic implementation in terms of gomp_mutex_t. */
36#include "../../lock.c"
fd6481cf 37
38#ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
39/* gomp_mutex_* can be safely locked in one thread and
40 unlocked in another thread, so the OpenMP 2.5 and OpenMP 3.0
41 non-nested locks can be the same. */
42strong_alias (gomp_init_lock_30, gomp_init_lock_25)
43strong_alias (gomp_destroy_lock_30, gomp_destroy_lock_25)
44strong_alias (gomp_set_lock_30, gomp_set_lock_25)
45strong_alias (gomp_unset_lock_30, gomp_unset_lock_25)
46strong_alias (gomp_test_lock_30, gomp_test_lock_25)
47
48/* The external recursive omp_nest_lock_25_t form requires additional work. */
1e8e9920 49
50/* We need an integer to uniquely identify this thread. Most generally
51 this is the thread's TID, which ideally we'd get this straight from
52 the TLS block where glibc keeps it. Unfortunately, we can't get at
53 that directly.
54
55 If we don't support (or have disabled) TLS, one function call is as
56 good (or bad) as any other. Use the syscall all the time.
57
58 On an ILP32 system (defined here as not LP64), we can make do with
59 any thread-local pointer. Ideally we'd use the TLS base address,
60 since that requires the least amount of arithmetic, but that's not
61 always available directly. Make do with the gomp_thread pointer
62 since it's handy. */
63
fd6481cf 64# if !defined (HAVE_TLS)
1e8e9920 65static inline int gomp_tid (void)
66{
67 return syscall (SYS_gettid);
68}
fd6481cf 69# elif !defined(__LP64__)
1e8e9920 70static inline int gomp_tid (void)
71{
72 return (int) gomp_thread ();
73}
fd6481cf 74# else
1e8e9920 75static __thread int tid_cache;
76static inline int gomp_tid (void)
77{
78 int tid = tid_cache;
79 if (__builtin_expect (tid == 0, 0))
80 tid_cache = tid = syscall (SYS_gettid);
81 return tid;
82}
fd6481cf 83# endif
1e8e9920 84
85
86void
fd6481cf 87gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
1e8e9920 88{
b0eb3deb 89 memset (lock, 0, sizeof (*lock));
1e8e9920 90}
91
92void
fd6481cf 93gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
1e8e9920 94{
95}
96
97void
fd6481cf 98gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
1e8e9920 99{
100 int otid, tid = gomp_tid ();
101
102 while (1)
103 {
9736f4d2 104 otid = 0;
105 if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
106 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
1e8e9920 107 {
108 lock->count = 1;
109 return;
110 }
111 if (otid == tid)
112 {
113 lock->count++;
114 return;
115 }
116
fd6481cf 117 do_wait (&lock->owner, otid);
1e8e9920 118 }
119}
120
121void
fd6481cf 122gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
1e8e9920 123{
124 /* ??? Validate that we own the lock here. */
125
126 if (--lock->count == 0)
127 {
9736f4d2 128 __atomic_store_n (&lock->owner, 0, MEMMODEL_RELEASE);
1e8e9920 129 futex_wake (&lock->owner, 1);
130 }
131}
132
133int
fd6481cf 134gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
1e8e9920 135{
136 int otid, tid = gomp_tid ();
137
9736f4d2 138 otid = 0;
139 if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
140 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
1e8e9920 141 {
142 lock->count = 1;
143 return 1;
144 }
145 if (otid == tid)
146 return ++lock->count;
147
148 return 0;
149}
150
fd6481cf 151omp_lock_symver (omp_init_lock)
152omp_lock_symver (omp_destroy_lock)
153omp_lock_symver (omp_set_lock)
154omp_lock_symver (omp_unset_lock)
155omp_lock_symver (omp_test_lock)
156omp_lock_symver (omp_init_nest_lock)
157omp_lock_symver (omp_destroy_nest_lock)
158omp_lock_symver (omp_set_nest_lock)
159omp_lock_symver (omp_unset_nest_lock)
160omp_lock_symver (omp_test_nest_lock)
161
162#else
163
1e8e9920 164ialias (omp_init_lock)
165ialias (omp_init_nest_lock)
166ialias (omp_destroy_lock)
167ialias (omp_destroy_nest_lock)
168ialias (omp_set_lock)
169ialias (omp_set_nest_lock)
170ialias (omp_unset_lock)
171ialias (omp_unset_nest_lock)
172ialias (omp_test_lock)
173ialias (omp_test_nest_lock)
fd6481cf 174
175#endif