tsan_vector_clock.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //===-- tsan_vector_clock.cpp ---------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of ThreadSanitizer (TSan), a race detector.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "tsan_vector_clock.h"
  13. #include "sanitizer_common/sanitizer_placement_new.h"
  14. #include "tsan_mman.h"
  15. namespace __tsan {
  16. #if TSAN_VECTORIZE
  17. const uptr kVectorClockSize = kThreadSlotCount * sizeof(Epoch) / sizeof(m128);
  18. #endif
  19. VectorClock::VectorClock() { Reset(); }
  20. void VectorClock::Reset() {
  21. #if !TSAN_VECTORIZE
  22. for (uptr i = 0; i < kThreadSlotCount; i++)
  23. clk_[i] = kEpochZero;
  24. #else
  25. m128 z = _mm_setzero_si128();
  26. m128* vclk = reinterpret_cast<m128*>(clk_);
  27. for (uptr i = 0; i < kVectorClockSize; i++) _mm_store_si128(&vclk[i], z);
  28. #endif
  29. }
  30. void VectorClock::Acquire(const VectorClock* src) {
  31. if (!src)
  32. return;
  33. #if !TSAN_VECTORIZE
  34. for (uptr i = 0; i < kThreadSlotCount; i++)
  35. clk_[i] = max(clk_[i], src->clk_[i]);
  36. #else
  37. m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
  38. m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(src->clk_);
  39. for (uptr i = 0; i < kVectorClockSize; i++) {
  40. m128 s = _mm_load_si128(&vsrc[i]);
  41. m128 d = _mm_load_si128(&vdst[i]);
  42. m128 m = _mm_max_epu16(s, d);
  43. _mm_store_si128(&vdst[i], m);
  44. }
  45. #endif
  46. }
  47. static VectorClock* AllocClock(VectorClock** dstp) {
  48. if (UNLIKELY(!*dstp))
  49. *dstp = New<VectorClock>();
  50. return *dstp;
  51. }
  52. void VectorClock::Release(VectorClock** dstp) const {
  53. VectorClock* dst = AllocClock(dstp);
  54. dst->Acquire(this);
  55. }
  56. void VectorClock::ReleaseStore(VectorClock** dstp) const {
  57. VectorClock* dst = AllocClock(dstp);
  58. *dst = *this;
  59. }
  60. VectorClock& VectorClock::operator=(const VectorClock& other) {
  61. #if !TSAN_VECTORIZE
  62. for (uptr i = 0; i < kThreadSlotCount; i++)
  63. clk_[i] = other.clk_[i];
  64. #else
  65. m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
  66. m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(other.clk_);
  67. for (uptr i = 0; i < kVectorClockSize; i++) {
  68. m128 s = _mm_load_si128(&vsrc[i]);
  69. _mm_store_si128(&vdst[i], s);
  70. }
  71. #endif
  72. return *this;
  73. }
  74. void VectorClock::ReleaseStoreAcquire(VectorClock** dstp) {
  75. VectorClock* dst = AllocClock(dstp);
  76. #if !TSAN_VECTORIZE
  77. for (uptr i = 0; i < kThreadSlotCount; i++) {
  78. Epoch tmp = dst->clk_[i];
  79. dst->clk_[i] = clk_[i];
  80. clk_[i] = max(clk_[i], tmp);
  81. }
  82. #else
  83. m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
  84. m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
  85. for (uptr i = 0; i < kVectorClockSize; i++) {
  86. m128 t = _mm_load_si128(&vdst[i]);
  87. m128 c = _mm_load_si128(&vclk[i]);
  88. m128 m = _mm_max_epu16(c, t);
  89. _mm_store_si128(&vdst[i], c);
  90. _mm_store_si128(&vclk[i], m);
  91. }
  92. #endif
  93. }
  94. void VectorClock::ReleaseAcquire(VectorClock** dstp) {
  95. VectorClock* dst = AllocClock(dstp);
  96. #if !TSAN_VECTORIZE
  97. for (uptr i = 0; i < kThreadSlotCount; i++) {
  98. dst->clk_[i] = max(dst->clk_[i], clk_[i]);
  99. clk_[i] = dst->clk_[i];
  100. }
  101. #else
  102. m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
  103. m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
  104. for (uptr i = 0; i < kVectorClockSize; i++) {
  105. m128 c = _mm_load_si128(&vclk[i]);
  106. m128 d = _mm_load_si128(&vdst[i]);
  107. m128 m = _mm_max_epu16(c, d);
  108. _mm_store_si128(&vdst[i], m);
  109. _mm_store_si128(&vclk[i], m);
  110. }
  111. #endif
  112. }
  113. } // namespace __tsan