1 /* elision-trylock.c: Lock eliding trylock for pthreads. 2 Copyright (C) 2015-2022 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 #include <pthread.h> 20 #include <pthreadP.h> 21 #include <lowlevellock.h> 22 #include <elision-conf.h> 23 #include "htm.h" 24 25 #define aconf __elision_aconf 26 27 /* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is 28 the adaptation counter in the mutex. */ 29 30 int __lll_trylock_elision(int * futex,short * adapt_count)31__lll_trylock_elision (int *futex, short *adapt_count) 32 { 33 /* Implement POSIX semantics by forbiding nesting elided trylocks. */ 34 __libc_tabort (_ABORT_NESTED_TRYLOCK); 35 36 /* Only try a transaction if it's worth it. */ 37 if (atomic_load_relaxed (adapt_count) > 0) 38 { 39 goto use_lock; 40 } 41 42 if (__libc_tbegin (0)) 43 { 44 if (*futex == 0) 45 return 0; 46 47 /* Lock was busy. This is never a nested transaction. 48 End it, and set the adapt count. */ 49 __libc_tend (0); 50 51 if (aconf.skip_lock_busy > 0) 52 atomic_store_relaxed (adapt_count, aconf.skip_lock_busy); 53 } 54 else 55 { 56 if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) 57 { 58 /* A persistent failure indicates that a retry will probably 59 result in another failure. Use normal locking now and 60 for the next couple of calls. */ 61 if (aconf.skip_trylock_internal_abort > 0) 62 atomic_store_relaxed (adapt_count, 63 aconf.skip_trylock_internal_abort); 64 } 65 } 66 67 use_lock: 68 return lll_trylock (*futex); 69 } 70 libc_hidden_def (__lll_trylock_elision) 71