]> 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
a945c346 1/* Copyright (C) 2005-2024 Free Software Foundation, Inc.
953ff289
DN
2 Contributed by Richard Henderson <rth@redhat.com>.
3
f1f3453e
TS
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
953ff289
DN
6
7 Libgomp is free software; you can redistribute it and/or modify it
748086b7
JJ
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.
953ff289
DN
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
748086b7 14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
953ff289
DN
15 more details.
16
748086b7
JJ
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.
953ff289 20
748086b7
JJ
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/>. */
953ff289
DN
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
953ff289
DN
30#include <string.h>
31#include <unistd.h>
32#include <sys/syscall.h>
a68ab351 33#include "wait.h"
953ff289 34
6103184e
AM
35/* Reuse the generic implementation in terms of gomp_mutex_t. */
36#include "../../lock.c"
a68ab351
JJ
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. */
953ff289
DN
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
a68ab351 64# if !defined (HAVE_TLS)
953ff289
DN
65static inline int gomp_tid (void)
66{
67 return syscall (SYS_gettid);
68}
a68ab351 69# elif !defined(__LP64__)
953ff289
DN
70static inline int gomp_tid (void)
71{
72 return (int) gomp_thread ();
73}
a68ab351 74# else
953ff289
DN
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}
a68ab351 83# endif
953ff289
DN
84
85
86void
a68ab351 87gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289 88{
43fa5db5 89 memset (lock, 0, sizeof (*lock));
953ff289
DN
90}
91
92void
a68ab351 93gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
94{
95}
96
97void
a68ab351 98gomp_set_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
99{
100 int otid, tid = gomp_tid ();
101
102 while (1)
103 {
45608a43
AM
104 otid = 0;
105 if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
106 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
953ff289
DN
107 {
108 lock->count = 1;
109 return;
110 }
111 if (otid == tid)
112 {
113 lock->count++;
114 return;
115 }
116
a68ab351 117 do_wait (&lock->owner, otid);
953ff289
DN
118 }
119}
120
121void
a68ab351 122gomp_unset_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
123{
124 /* ??? Validate that we own the lock here. */
125
126 if (--lock->count == 0)
127 {
45608a43 128 __atomic_store_n (&lock->owner, 0, MEMMODEL_RELEASE);
953ff289
DN
129 futex_wake (&lock->owner, 1);
130 }
131}
132
133int
a68ab351 134gomp_test_nest_lock_25 (omp_nest_lock_25_t *lock)
953ff289
DN
135{
136 int otid, tid = gomp_tid ();
137
45608a43
AM
138 otid = 0;
139 if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
140 MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
953ff289
DN
141 {
142 lock->count = 1;
143 return 1;
144 }
145 if (otid == tid)
146 return ++lock->count;
147
148 return 0;
149}
150
a68ab351
JJ
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
953ff289
DN
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)
a68ab351
JJ
174
175#endif