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