| 1 | /* force-elision.h: Automatic enabling of elision for mutexes |
| 2 | Copyright (C) 2013-2019 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 | <http://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 | |