local.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* Copyright (C) 2008-2022 Free Software Foundation, Inc.
  2. Contributed by Richard Henderson <rth@redhat.com>.
  3. This file is part of the GNU Transactional Memory Library (libitm).
  4. Libitm is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
  9. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  10. FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. #include "libitm_i.h"
  20. namespace GTM HIDDEN {
  21. // This function needs to be noinline because we need to prevent that it gets
  22. // inlined into another function that calls further functions. This could
  23. // break our assumption that we only call memcpy and thus only need to
  24. // additionally protect the memcpy stack (see the hack in mask_stack_bottom()).
  25. // Even if that isn't an issue because those other calls don't happen during
  26. // copying, we still need mask_stack_bottom() to be called "close" to the
  27. // memcpy in terms of stack frames, so just ensure that for now using the
  28. // noinline.
  29. void __attribute__((noinline))
  30. gtm_undolog::rollback (gtm_thread* tx, size_t until_size)
  31. {
  32. size_t i, n = undolog.size();
  33. void *top = mask_stack_top(tx);
  34. void *bot = mask_stack_bottom(tx);
  35. if (n > 0)
  36. {
  37. for (i = n; i-- > until_size; )
  38. {
  39. void *ptr = (void *) undolog[i--];
  40. size_t len = undolog[i];
  41. size_t words = (len + sizeof(gtm_word) - 1) / sizeof(gtm_word);
  42. i -= words;
  43. // Filter out any updates that overlap the libitm stack. We don't
  44. // bother filtering out just the overlapping bytes because we don't
  45. // merge writes and thus any overlapping write is either bogus or
  46. // would restore data on stack frames that are not in use anymore.
  47. // FIXME The memcpy can/will end up as another call but we
  48. // calculated BOT based on the current function. Can we inline or
  49. // reimplement this without too much trouble due to unaligned calls
  50. // and still have good performance, so that we can remove the hack
  51. // in mask_stack_bottom()?
  52. if (likely(ptr > top || (uint8_t*)ptr + len <= bot))
  53. __builtin_memcpy (ptr, &undolog[i], len);
  54. }
  55. undolog.set_size(until_size);
  56. }
  57. }
  58. void ITM_REGPARM
  59. GTM_LB (const void *ptr, size_t len)
  60. {
  61. gtm_thread *tx = gtm_thr();
  62. tx->undolog.log(ptr, len);
  63. }
  64. } // namespace GTM
  65. using namespace GTM;
  66. /* ??? Use configure to determine if aliases are supported. Or convince
  67. the compiler to not just tail call this, but actually generate the
  68. same_body_alias itself. */
  69. void ITM_REGPARM
  70. _ITM_LB (const void *ptr, size_t len)
  71. {
  72. GTM_LB (ptr, len);
  73. }
  74. #define ITM_LOG_DEF(T) \
  75. void ITM_REGPARM _ITM_L##T (const _ITM_TYPE_##T *ptr) \
  76. { GTM_LB (ptr, sizeof (*ptr)); }
  77. ITM_LOG_DEF(U1)
  78. ITM_LOG_DEF(U2)
  79. ITM_LOG_DEF(U4)
  80. ITM_LOG_DEF(U8)
  81. ITM_LOG_DEF(F)
  82. ITM_LOG_DEF(D)
  83. ITM_LOG_DEF(E)
  84. ITM_LOG_DEF(CF)
  85. ITM_LOG_DEF(CD)
  86. ITM_LOG_DEF(CE)