elision-trylock.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /* elision-trylock.c: Lock eliding trylock for pthreads.
  2. Copyright (C) 2015-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <pthread.h>
  16. #include <pthreadP.h>
  17. #include <lowlevellock.h>
  18. #include <elision-conf.h>
  19. #include "htm.h"
  20. #define aconf __elision_aconf
  21. /* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is
  22. the adaptation counter in the mutex. */
  23. int
  24. __lll_trylock_elision (int *futex, short *adapt_count)
  25. {
  26. #ifndef __SPE__
  27. /* Implement POSIX semantics by forbiding nesting elided trylocks. */
  28. __libc_tabort (_ABORT_NESTED_TRYLOCK);
  29. /* Only try a transaction if it's worth it. */
  30. if (atomic_load_relaxed (adapt_count) > 0)
  31. {
  32. goto use_lock;
  33. }
  34. if (__libc_tbegin (0))
  35. {
  36. if (*futex == 0)
  37. return 0;
  38. /* Lock was busy. This is never a nested transaction.
  39. End it, and set the adapt count. */
  40. __libc_tend (0);
  41. if (aconf.skip_lock_busy > 0)
  42. atomic_store_relaxed (adapt_count, aconf.skip_lock_busy);
  43. }
  44. else
  45. {
  46. if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
  47. {
  48. /* A persistent failure indicates that a retry will probably
  49. result in another failure. Use normal locking now and
  50. for the next couple of calls. */
  51. if (aconf.skip_trylock_internal_abort > 0)
  52. atomic_store_relaxed (adapt_count,
  53. aconf.skip_trylock_internal_abort);
  54. }
  55. }
  56. use_lock:
  57. #endif
  58. return lll_trylock (*futex);
  59. }