1 /* elision-lock.c: Elided pthread mutex lock.
2 Copyright (C) 2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
22 #include <lowlevellock.h>
23 #include <elision-conf.h>
26 /* PowerISA 2.0.7 Section B.5.5 defines isync to be insufficient as a
27 barrier in acquire mechanism for HTM operations, a strong 'sync' is
29 #undef __arch_compare_and_exchange_val_32_acq
30 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
32 __typeof (*(mem)) __tmp; \
33 __typeof (mem) __memp = (mem); \
35 "1: lwarx %0,0,%1" MUTEX_HINT_ACQ "\n" \
42 : "b" (__memp), "r" (oldval), "r" (newval) \
47 #if !defined(LLL_LOCK) && !defined(EXTRAARG)
48 /* Make sure the configuration code is always linked in for static
50 #include "elision-conf.c"
57 # define LLL_LOCK(a,b) lll_lock(a,b), 0
60 #define aconf __elision_aconf
62 /* Adaptive lock using transactions.
63 By default the lock region is run as a transaction, and when it
64 aborts or the lock is busy the lock adapts itself. */
67 __lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared)
75 int try_begin = aconf.try_tbegin;
78 if (__builtin_tbegin (0))
82 /* Lock was busy. Fall back to normal locking. */
83 __builtin_tabort (_ABORT_LOCK_BUSY);
87 /* A persistent failure indicates that a retry will probably
88 result in another failure. Use normal locking now and
89 for the next couple of calls. */
91 || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
93 if (aconf.skip_lock_internal_abort > 0)
94 *adapt_count = aconf.skip_lock_internal_abort;
97 /* Same logic as above, but for for a number of temporary failures
99 else if (aconf.skip_lock_out_of_tbegin_retries > 0
100 && aconf.try_tbegin > 0)
101 *adapt_count = aconf.skip_lock_out_of_tbegin_retries;
106 return LLL_LOCK ((*lock), pshared);