stmlock.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* Copyright (C) 2009-2015 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. #ifndef LIBITM_STMLOCK_H
  20. #define LIBITM_STMLOCK_H 1
  21. namespace GTM HIDDEN {
  22. /* A versioned write lock on a cacheline. This must be wide enough to
  23. store a pointer, and preferably wide enough to avoid overflowing the
  24. version counter. Thus we use a "word", which should be 64-bits on
  25. 64-bit systems even when their pointer size is forced smaller. */
  26. typedef gtm_word gtm_stmlock;
  27. /* This has to be the same size as gtm_stmlock, we just use this name
  28. for documentation purposes. */
  29. typedef gtm_word gtm_version;
  30. /* The maximum value a version number can have. This is a consequence
  31. of having the low bit of gtm_stmlock reserved for the owned bit. */
  32. #define GTM_VERSION_MAX (~(gtm_version)0 >> 1)
  33. /* A value that may be used to indicate "uninitialized" for a version. */
  34. #define GTM_VERSION_INVALID (~(gtm_version)0)
  35. /* This bit is set when the write lock is held. When set, the balance of
  36. the bits in the lock is a pointer that references STM backend specific
  37. data; it is up to the STM backend to determine if this thread holds the
  38. lock. If this bit is clear, the balance of the bits are the last
  39. version number committed to the cacheline. */
  40. static inline bool
  41. gtm_stmlock_owned_p (gtm_stmlock lock)
  42. {
  43. return lock & 1;
  44. }
  45. static inline gtm_stmlock
  46. gtm_stmlock_set_owned (void *data)
  47. {
  48. return (gtm_stmlock)(uintptr_t)data | 1;
  49. }
  50. static inline void *
  51. gtm_stmlock_get_addr (gtm_stmlock lock)
  52. {
  53. return (void *)((uintptr_t)lock & ~(uintptr_t)1);
  54. }
  55. static inline gtm_version
  56. gtm_stmlock_get_version (gtm_stmlock lock)
  57. {
  58. return lock >> 1;
  59. }
  60. static inline gtm_stmlock
  61. gtm_stmlock_set_version (gtm_version ver)
  62. {
  63. return ver << 1;
  64. }
  65. /* We use a fixed set of locks for all memory, hashed into the
  66. following table. */
  67. #define LOCK_ARRAY_SIZE (1024 * 1024)
  68. extern gtm_stmlock gtm_stmlock_array[LOCK_ARRAY_SIZE];
  69. static inline gtm_stmlock *
  70. gtm_get_stmlock (const gtm_cacheline *addr)
  71. {
  72. size_t idx = ((uintptr_t) addr / CACHELINE_SIZE) % LOCK_ARRAY_SIZE;
  73. return gtm_stmlock_array + idx;
  74. }
  75. /* The current global version number. */
  76. extern atomic<gtm_version> gtm_clock;
  77. static inline gtm_version
  78. gtm_get_clock (void)
  79. {
  80. atomic_thread_fence(memory_order_release);
  81. return gtm_clock.load(memory_order_acquire);
  82. }
  83. static inline gtm_version
  84. gtm_inc_clock (void)
  85. {
  86. /* ??? Here we have a choice, the pre-inc operator mapping to
  87. __atomic_add_fetch with memory_order_seq_cst, or fetch_add
  88. with memory_order_acq_rel plus another separate increment.
  89. We really ought to recognize and optimize fetch_op(x) op x... */
  90. gtm_version r = ++gtm_clock;
  91. /* ??? Ought to handle wraparound for 32-bit. */
  92. if (sizeof(r) < 8 && r > GTM_VERSION_MAX)
  93. abort ();
  94. return r;
  95. }
  96. } // namespace GTM
  97. #endif // LIBITM_STMLOCK_H