Index: base/memory/shared_memory_unittest.cc |
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc |
index 6fe57060e6fcd6cd83853875fcea4c1595c52138..c36fca248fba6cd6adca2a9183154a24f4b68c13 100644 |
--- a/base/memory/shared_memory_unittest.cc |
+++ b/base/memory/shared_memory_unittest.cc |
@@ -2,6 +2,7 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "base/atomicops.h" |
#include "base/basictypes.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/memory/shared_memory.h" |
@@ -90,56 +91,6 @@ class MultipleThreadMain : public PlatformThread::Delegate { |
const char* const MultipleThreadMain::s_test_name_ = |
"SharedMemoryOpenThreadTest"; |
-// TODO(port): |
-// This test requires the ability to pass file descriptors between processes. |
-// We haven't done that yet in Chrome for POSIX. |
-#if defined(OS_WIN) |
-// Each thread will open the shared memory. Each thread will take the memory, |
-// and keep changing it while trying to lock it, with some small pauses in |
-// between. Verify that each thread's value in the shared memory is always |
-// correct. |
-class MultipleLockThread : public PlatformThread::Delegate { |
- public: |
- explicit MultipleLockThread(int id) : id_(id) {} |
- ~MultipleLockThread() override {} |
- |
- // PlatformThread::Delegate interface. |
- void ThreadMain() override { |
- const uint32 kDataSize = sizeof(int); |
- SharedMemoryHandle handle = NULL; |
- { |
- SharedMemory memory1; |
- EXPECT_TRUE(memory1.CreateNamedDeprecated( |
- "SharedMemoryMultipleLockThreadTest", true, kDataSize)); |
- EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); |
- // TODO(paulg): Implement this once we have a posix version of |
- // SharedMemory::ShareToProcess. |
- EXPECT_TRUE(true); |
- } |
- |
- SharedMemory memory2(handle, false); |
- EXPECT_TRUE(memory2.Map(kDataSize)); |
- volatile int* const ptr = static_cast<int*>(memory2.memory()); |
- |
- for (int idx = 0; idx < 20; idx++) { |
- memory2.LockDeprecated(); |
- int i = (id_ << 16) + idx; |
- *ptr = i; |
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); |
- EXPECT_EQ(*ptr, i); |
- memory2.UnlockDeprecated(); |
- } |
- |
- memory2.Close(); |
- } |
- |
- private: |
- int id_; |
- |
- DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); |
-}; |
-#endif |
- |
} // namespace |
// Android doesn't support SharedMemory::Open/Delete/ |
@@ -320,34 +271,6 @@ TEST(SharedMemoryTest, MultipleThreads) { |
MultipleThreadMain::CleanUp(); |
} |
-// TODO(port): this test requires the MultipleLockThread class |
-// (defined above), which requires the ability to pass file |
-// descriptors between processes. We haven't done that yet in Chrome |
-// for POSIX. |
-#if defined(OS_WIN) |
-// Create a set of threads to each open a shared memory segment and write to it |
-// with the lock held. Verify that they are always reading/writing consistent |
-// data. |
-TEST(SharedMemoryTest, Lock) { |
- PlatformThreadHandle thread_handles[kNumThreads]; |
- MultipleLockThread* thread_delegates[kNumThreads]; |
- |
- // Spawn the threads. |
- for (int index = 0; index < kNumThreads; ++index) { |
- PlatformThreadHandle pth; |
- thread_delegates[index] = new MultipleLockThread(index); |
- EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); |
- thread_handles[index] = pth; |
- } |
- |
- // Wait for the threads to finish. |
- for (int index = 0; index < kNumThreads; ++index) { |
- PlatformThread::Join(thread_handles[index]); |
- delete thread_delegates[index]; |
- } |
-} |
-#endif |
- |
// Allocate private (unique) shared memory with an empty string for a |
// name. Make sure several of them don't point to the same thing as |
// we might expect if the names are equal. |
@@ -664,53 +587,66 @@ class SharedMemoryProcessTest : public MultiProcessTest { |
#if defined(OS_MACOSX) |
mac::ScopedNSAutoreleasePool pool; |
#endif |
- const uint32 kDataSize = 1024; |
SharedMemory memory; |
- bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); |
+ bool rv = memory.CreateNamedDeprecated(s_test_name_, true, data_size_); |
EXPECT_TRUE(rv); |
if (rv != true) |
errors++; |
- rv = memory.Map(kDataSize); |
+ rv = memory.Map(data_size_); |
EXPECT_TRUE(rv); |
if (rv != true) |
errors++; |
int *ptr = static_cast<int*>(memory.memory()); |
- for (int idx = 0; idx < 20; idx++) { |
- memory.LockDeprecated(); |
- int i = (1 << 16) + idx; |
- *ptr = i; |
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(10)); |
- if (*ptr != i) |
- errors++; |
- memory.UnlockDeprecated(); |
+ // Atomically increment the value at *ptr by 1. |
+ while (true) { |
+ int j = *ptr; |
+ int old_value = base::subtle::NoBarrier_CompareAndSwap(ptr, j, j + 1); |
Nico
2015/06/11 15:39:18
can you use a lock instead?
erikchen
2015/06/11 17:36:30
This code needs to be atomic across multiple proce
Nico
2015/06/11 17:46:40
Ah, right. Maybe say "// This runs concurrently in
erikchen
2015/06/11 17:55:18
Done.
That's weird. I thought I did use an atomic
|
+ if (old_value == j) |
+ break; |
} |
- |
memory.Close(); |
return errors; |
} |
- private: |
static const char* const s_test_name_; |
+ static const uint32 data_size_; |
Nico
2015/06/11 15:39:18
s_data_size for consistency
erikchen
2015/06/11 17:36:30
Done.
|
}; |
const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; |
+const uint32 SharedMemoryProcessTest::data_size_ = 1024; |
-TEST_F(SharedMemoryProcessTest, Tasks) { |
+TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { |
SharedMemoryProcessTest::CleanUp(); |
+ // Create a shared memory region. Set the first word to 0. |
+ SharedMemory memory; |
+ bool rv = memory.CreateNamedDeprecated(s_test_name_, true, data_size_); |
+ ASSERT_TRUE(rv); |
+ rv = memory.Map(data_size_); |
+ ASSERT_TRUE(rv); |
+ int* ptr = static_cast<int*>(memory.memory()); |
+ *ptr = 0; |
+ |
+ // Start |kNumTasks| processes, each of which atomically increments the first |
+ // word by 1. |
Process processes[kNumTasks]; |
for (int index = 0; index < kNumTasks; ++index) { |
processes[index] = SpawnChild("SharedMemoryTestMain"); |
ASSERT_TRUE(processes[index].IsValid()); |
} |
+ // Check that each process exited correctly. |
int exit_code = 0; |
for (int index = 0; index < kNumTasks; ++index) { |
EXPECT_TRUE(processes[index].WaitForExit(&exit_code)); |
EXPECT_EQ(0, exit_code); |
} |
+ // Check that the shared memory region reflects |kNumTasks| increments. |
+ ASSERT_EQ(kNumTasks, *ptr); |
+ |
+ memory.Close(); |
SharedMemoryProcessTest::CleanUp(); |
} |