]>
Commit | Line | Data |
---|---|---|
5a414ff7 | 1 | /* Commit an elided pthread lock. |
04277e02 | 2 | Copyright (C) 2014-2019 Free Software Foundation, Inc. |
5a414ff7 DV |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
5a414ff7 DV |
18 | |
19 | #include <pthreadP.h> | |
20 | #include <lowlevellock.h> | |
8bfc4a2a | 21 | #include <htm.h> |
5a414ff7 DV |
22 | |
23 | int | |
dd037fb3 | 24 | __lll_unlock_elision(int *futex, short *adapt_count, int private) |
5a414ff7 DV |
25 | { |
26 | /* If the lock is free, we elided the lock earlier. This does not | |
27 | necessarily mean that we are in a transaction, because the user code may | |
dd037fb3 | 28 | have closed the transaction, but that is impossible to detect reliably. |
03b00777 SL |
29 | Relaxed MO access to futex is sufficient because a correct program |
30 | will only release a lock it has acquired; therefore, it must either | |
31 | changed the futex word's value to something !=0 or it must have used | |
32 | elision; these are actions by the same thread, so these actions are | |
33 | sequenced-before the relaxed load (and thus also happens-before the | |
34 | relaxed load). Therefore, relaxed MO is sufficient. */ | |
dd037fb3 | 35 | if (atomic_load_relaxed (futex) == 0) |
5a414ff7 | 36 | { |
8bfc4a2a | 37 | __libc_tend (); |
5a414ff7 DV |
38 | } |
39 | else | |
dd037fb3 SL |
40 | { |
41 | /* Update the adapt_count while unlocking before completing the critical | |
42 | section. adapt_count is accessed concurrently outside of a | |
03b00777 SL |
43 | transaction or a critical section (e.g. in elision-lock.c). So we need |
44 | to use atomic accesses. However, the value of adapt_count is just a | |
45 | hint, so relaxed MO accesses are sufficient. | |
dd037fb3 | 46 | If adapt_count would be decremented while locking, multiple |
03b00777 | 47 | CPUs, trying to lock the acquired mutex, will decrement adapt_count to |
dd037fb3 SL |
48 | zero and another CPU will try to start a transaction, which will be |
49 | immediately aborted as the mutex is locked. | |
03b00777 SL |
50 | The update of adapt_count is done before releasing the lock as POSIX' |
51 | mutex destruction requirements disallow accesses to the mutex after it | |
52 | has been released and thus could have been acquired or destroyed by | |
53 | another thread. */ | |
dd037fb3 SL |
54 | short adapt_count_val = atomic_load_relaxed (adapt_count); |
55 | if (adapt_count_val > 0) | |
56 | atomic_store_relaxed (adapt_count, adapt_count_val - 1); | |
57 | ||
58 | lll_unlock ((*futex), private); | |
59 | } | |
5a414ff7 DV |
60 | return 0; |
61 | } |