| // Copyright 2017 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "base/allocator/partition_allocator/spin_lock.h" | |
| #include <memory> | |
| #include "base/bind.h" | |
| #include "base/bind_helpers.h" | |
| #include "base/threading/thread.h" | |
| #include "testing/gtest/include/gtest/gtest.h" | |
| namespace base { | |
| static constexpr size_t kBufferSize = 16; | |
| static subtle::SpinLock g_lock; | |
| static void FillBuffer(volatile char* buffer, char fill_pattern) { | |
| for (size_t i = 0; i < kBufferSize; ++i) | |
| buffer[i] = fill_pattern; | |
| } | |
| static void ChangeAndCheckBuffer(volatile char* buffer) { | |
| FillBuffer(buffer, '\0'); | |
| int total = 0; | |
| for (size_t i = 0; i < kBufferSize; ++i) | |
| total += buffer[i]; | |
| EXPECT_EQ(0, total); | |
| // This will mess with the other thread's calculation if we accidentally get | |
| // concurrency. | |
| FillBuffer(buffer, '!'); | |
| } | |
| static void ThreadMain(volatile char* buffer) { | |
| for (int i = 0; i < 500000; ++i) { | |
| subtle::SpinLock::Guard guard(g_lock); | |
| ChangeAndCheckBuffer(buffer); | |
| } | |
| } | |
| TEST(SpinLockTest, Torture) { | |
| char shared_buffer[kBufferSize]; | |
| Thread thread1("thread1"); | |
| Thread thread2("thread2"); | |
| thread1.StartAndWaitForTesting(); | |
| thread2.StartAndWaitForTesting(); | |
| thread1.task_runner()->PostTask( | |
| FROM_HERE, | |
| BindOnce(&ThreadMain, Unretained(static_cast<char*>(shared_buffer)))); | |
| thread2.task_runner()->PostTask( | |
| FROM_HERE, | |
| BindOnce(&ThreadMain, Unretained(static_cast<char*>(shared_buffer)))); | |
| } | |
| } // namespace base |