diff --git a/test/unittests/base/atomic-utils-unittest.cc b/test/unittests/base/atomic-utils-unittest.cc index 06256764b6..794d4c4a50 100644 --- a/test/unittests/base/atomic-utils-unittest.cc +++ b/test/unittests/base/atomic-utils-unittest.cc @@ -207,5 +207,80 @@ TEST(AsAtomic8, CompareAndSwap_Concurrent) { } } +TEST(AsAtomicWord, SetBits_Sequential) { + uintptr_t word = 0; + // Fill the word with a repeated 0xF0 pattern. + for (unsigned i = 0; i < sizeof(word); i++) { + word = (word << 8) | 0xF0; + } + // Check the pattern. + for (unsigned i = 0; i < sizeof(word); i++) { + EXPECT_EQ(0xF0u, (word >> (i * 8) & 0xFFu)); + } + // Set the i-th byte value to i. + uintptr_t mask = 0xFF; + for (unsigned i = 0; i < sizeof(word); i++) { + uintptr_t byte = static_cast(i) << (i * 8); + AsAtomicWord::SetBits(&word, byte, mask); + mask <<= 8; + } + for (unsigned i = 0; i < sizeof(word); i++) { + EXPECT_EQ(i, (word >> (i * 8) & 0xFFu)); + } +} + +namespace { + +class BitSettingThread final : public Thread { + public: + BitSettingThread() + : Thread(Options("BitSettingThread")), + word_addr_(nullptr), + bit_index_(0) {} + + void Initialize(uintptr_t* word_addr, int bit_index) { + word_addr_ = word_addr; + bit_index_ = bit_index; + } + + void Run() override { + uintptr_t bit = 1; + bit = bit << bit_index_; + AsAtomicWord::SetBits(word_addr_, bit, bit); + } + + private: + uintptr_t* word_addr_; + int bit_index_; +}; + +} // namespace. + +TEST(AsAtomicWord, SetBits_Concurrent) { + const int kBitCount = sizeof(uintptr_t) * 8; + const int kThreadCount = kBitCount / 2; + BitSettingThread threads[kThreadCount]; + + uintptr_t word; + AsAtomicWord::Relaxed_Store(&word, 0); + for (int i = 0; i < kThreadCount; i++) { + // Thread i sets bit number i * 2. + threads[i].Initialize(&word, i * 2); + } + for (int i = 0; i < kThreadCount; i++) { + threads[i].Start(); + } + for (int i = 0; i < kThreadCount; i++) { + threads[i].Join(); + } + uintptr_t actual_word = AsAtomicWord::Relaxed_Load(&word); + for (int i = 0; i < kBitCount; i++) { + // Every second bit must be set. + uintptr_t expected = (i % 2 == 0); + EXPECT_EQ(expected, actual_word & 1u); + actual_word >>= 1; + } +} + } // namespace base } // namespace v8