]>
Commit | Line | Data |
---|---|---|
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. */ | |
42 | strong_alias (gomp_init_lock_30, gomp_init_lock_25) | |
43 | strong_alias (gomp_destroy_lock_30, gomp_destroy_lock_25) | |
44 | strong_alias (gomp_set_lock_30, gomp_set_lock_25) | |
45 | strong_alias (gomp_unset_lock_30, gomp_unset_lock_25) | |
46 | strong_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 |
65 | static inline int gomp_tid (void) |
66 | { | |
67 | return syscall (SYS_gettid); | |
68 | } | |
a68ab351 | 69 | # elif !defined(__LP64__) |
953ff289 DN |
70 | static inline int gomp_tid (void) |
71 | { | |
72 | return (int) gomp_thread (); | |
73 | } | |
a68ab351 | 74 | # else |
953ff289 DN |
75 | static __thread int tid_cache; |
76 | static 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 | ||
86 | void | |
a68ab351 | 87 | gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock) |
953ff289 | 88 | { |
43fa5db5 | 89 | memset (lock, 0, sizeof (*lock)); |
953ff289 DN |
90 | } |
91 | ||
92 | void | |
a68ab351 | 93 | gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock) |
953ff289 DN |
94 | { |
95 | } | |
96 | ||
97 | void | |
a68ab351 | 98 | gomp_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 | ||
121 | void | |
a68ab351 | 122 | gomp_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 | ||
133 | int | |
a68ab351 | 134 | gomp_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 |
151 | omp_lock_symver (omp_init_lock) |
152 | omp_lock_symver (omp_destroy_lock) | |
153 | omp_lock_symver (omp_set_lock) | |
154 | omp_lock_symver (omp_unset_lock) | |
155 | omp_lock_symver (omp_test_lock) | |
156 | omp_lock_symver (omp_init_nest_lock) | |
157 | omp_lock_symver (omp_destroy_nest_lock) | |
158 | omp_lock_symver (omp_set_nest_lock) | |
159 | omp_lock_symver (omp_unset_nest_lock) | |
160 | omp_lock_symver (omp_test_nest_lock) | |
161 | ||
162 | #else | |
163 | ||
953ff289 DN |
164 | ialias (omp_init_lock) |
165 | ialias (omp_init_nest_lock) | |
166 | ialias (omp_destroy_lock) | |
167 | ialias (omp_destroy_nest_lock) | |
168 | ialias (omp_set_lock) | |
169 | ialias (omp_set_nest_lock) | |
170 | ialias (omp_unset_lock) | |
171 | ialias (omp_unset_nest_lock) | |
172 | ialias (omp_test_lock) | |
173 | ialias (omp_test_nest_lock) | |
a68ab351 JJ |
174 | |
175 | #endif |