1 | /* force-elision.h: Automatic enabling of elision for mutexes |
2 | Copyright (C) 2013-2021 Free Software Foundation, Inc. |
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 |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | /* Automatically enable elision for existing user lock kinds. */ |
20 | #define FORCE_ELISION(m, s) \ |
21 | if (__pthread_force_elision) \ |
22 | { \ |
23 | /* See concurrency notes regarding __kind in \ |
24 | struct __pthread_mutex_s in \ |
25 | sysdeps/nptl/bits/thread-shared-types.h. \ |
26 | \ |
27 | There are the following cases for the kind of a mutex \ |
28 | (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \ |
29 | PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \ |
30 | only one of both flags can be set): \ |
31 | - both flags are not set: \ |
32 | This is the first lock operation for this mutex. Enable \ |
33 | elision as it is not enabled so far. \ |
34 | Note: It can happen that multiple threads are calling e.g. \ |
35 | pthread_mutex_lock at the same time as the first lock \ |
36 | operation for this mutex. Then elision is enabled for this \ |
37 | mutex by multiple threads. Storing with relaxed MO is enough \ |
38 | as all threads will store the same new value for the kind of \ |
39 | the mutex. But we have to ensure that we always use the \ |
40 | elision path regardless if this thread has enabled elision or \ |
41 | another one. \ |
42 | \ |
43 | - PTHREAD_MUTEX_ELISION_NP flag is set: \ |
44 | Elision was already enabled for this mutex by a previous lock \ |
45 | operation. See case above. Just use the elision path. \ |
46 | \ |
47 | - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \ |
48 | Elision was explicitly disabled by pthread_mutexattr_settype. \ |
49 | Do not use the elision path. \ |
50 | Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \ |
51 | changed after mutex initialization. */ \ |
52 | int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \ |
53 | if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ |
54 | { \ |
55 | mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \ |
56 | atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \ |
57 | } \ |
58 | if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \ |
59 | { \ |
60 | s; \ |
61 | } \ |
62 | } |
63 | |