]>
Commit | Line | Data |
---|---|---|
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. */ | |
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. */ | |
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 | 65 | static inline int gomp_tid (void) |
66 | { | |
67 | return syscall (SYS_gettid); | |
68 | } | |
fd6481cf | 69 | # elif !defined(__LP64__) |
1e8e9920 | 70 | static inline int gomp_tid (void) |
71 | { | |
72 | return (int) gomp_thread (); | |
73 | } | |
fd6481cf | 74 | # else |
1e8e9920 | 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 | } | |
fd6481cf | 83 | # endif |
1e8e9920 | 84 | |
85 | ||
86 | void | |
fd6481cf | 87 | gomp_init_nest_lock_25 (omp_nest_lock_25_t *lock) |
1e8e9920 | 88 | { |
b0eb3deb | 89 | memset (lock, 0, sizeof (*lock)); |
1e8e9920 | 90 | } |
91 | ||
92 | void | |
fd6481cf | 93 | gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *lock) |
1e8e9920 | 94 | { |
95 | } | |
96 | ||
97 | void | |
fd6481cf | 98 | gomp_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 | ||
121 | void | |
fd6481cf | 122 | gomp_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 | ||
133 | int | |
fd6481cf | 134 | gomp_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 | 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 | ||
1e8e9920 | 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) | |
fd6481cf | 174 | |
175 | #endif |