OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "base/memory/shared_memory.h" | 7 #include "base/memory/shared_memory.h" |
8 #include "base/process/kill.h" | 8 #include "base/process/kill.h" |
9 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 | 21 |
22 #if defined(OS_POSIX) | 22 #if defined(OS_POSIX) |
23 #include <errno.h> | 23 #include <errno.h> |
24 #include <fcntl.h> | 24 #include <fcntl.h> |
25 #include <sys/mman.h> | 25 #include <sys/mman.h> |
26 #include <sys/stat.h> | 26 #include <sys/stat.h> |
27 #include <sys/types.h> | 27 #include <sys/types.h> |
28 #include <unistd.h> | 28 #include <unistd.h> |
29 #endif | 29 #endif |
30 | 30 |
31 #if defined(OS_WIN) | |
32 #include "base/win/scoped_handle.h" | |
33 #endif | |
34 | |
35 static const int kNumThreads = 5; | 31 static const int kNumThreads = 5; |
36 #if !defined(OS_IOS) // iOS does not allow multiple processes. | 32 #if !defined(OS_IOS) // iOS does not allow multiple processes. |
37 static const int kNumTasks = 5; | 33 static const int kNumTasks = 5; |
38 #endif | 34 #endif |
39 | 35 |
40 namespace base { | 36 namespace base { |
41 | 37 |
42 namespace { | 38 namespace { |
43 | 39 |
44 // Each thread will open the shared memory. Each thread will take a different 4 | 40 // Each thread will open the shared memory. Each thread will take a different 4 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 int16 id_; | 79 int16 id_; |
84 | 80 |
85 static const char* const s_test_name_; | 81 static const char* const s_test_name_; |
86 | 82 |
87 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); | 83 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); |
88 }; | 84 }; |
89 | 85 |
90 const char* const MultipleThreadMain::s_test_name_ = | 86 const char* const MultipleThreadMain::s_test_name_ = |
91 "SharedMemoryOpenThreadTest"; | 87 "SharedMemoryOpenThreadTest"; |
92 | 88 |
93 // TODO(port): | |
94 // This test requires the ability to pass file descriptors between processes. | |
95 // We haven't done that yet in Chrome for POSIX. | |
96 #if defined(OS_WIN) | |
97 // Each thread will open the shared memory. Each thread will take the memory, | |
98 // and keep changing it while trying to lock it, with some small pauses in | |
99 // between. Verify that each thread's value in the shared memory is always | |
100 // correct. | |
101 class MultipleLockThread : public PlatformThread::Delegate { | |
102 public: | |
103 explicit MultipleLockThread(int id) : id_(id) {} | |
104 ~MultipleLockThread() override {} | |
105 | |
106 // PlatformThread::Delegate interface. | |
107 void ThreadMain() override { | |
108 const uint32 kDataSize = sizeof(int); | |
109 SharedMemoryHandle handle = NULL; | |
110 { | |
111 SharedMemory memory1; | |
112 EXPECT_TRUE(memory1.CreateNamedDeprecated( | |
113 "SharedMemoryMultipleLockThreadTest", true, kDataSize)); | |
114 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); | |
115 // TODO(paulg): Implement this once we have a posix version of | |
116 // SharedMemory::ShareToProcess. | |
117 EXPECT_TRUE(true); | |
118 } | |
119 | |
120 SharedMemory memory2(handle, false); | |
121 EXPECT_TRUE(memory2.Map(kDataSize)); | |
122 volatile int* const ptr = static_cast<int*>(memory2.memory()); | |
123 | |
124 for (int idx = 0; idx < 20; idx++) { | |
125 memory2.LockDeprecated(); | |
126 int i = (id_ << 16) + idx; | |
127 *ptr = i; | |
128 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); | |
129 EXPECT_EQ(*ptr, i); | |
130 memory2.UnlockDeprecated(); | |
131 } | |
132 | |
133 memory2.Close(); | |
134 } | |
135 | |
136 private: | |
137 int id_; | |
138 | |
139 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); | |
140 }; | |
141 #endif | |
142 | |
143 } // namespace | 89 } // namespace |
144 | 90 |
145 // Android doesn't support SharedMemory::Open/Delete/ | 91 // Android doesn't support SharedMemory::Open/Delete/ |
146 // CreateNamedDeprecated(openExisting=true) | 92 // CreateNamedDeprecated(openExisting=true) |
147 #if !defined(OS_ANDROID) | 93 #if !defined(OS_ANDROID) |
148 TEST(SharedMemoryTest, OpenClose) { | 94 TEST(SharedMemoryTest, OpenClose) { |
149 const uint32 kDataSize = 1024; | 95 const uint32 kDataSize = 1024; |
150 std::string test_name = "SharedMemoryOpenCloseTest"; | 96 std::string test_name = "SharedMemoryOpenCloseTest"; |
151 | 97 |
152 // Open two handles to a memory segment, confirm that they are mapped | 98 // Open two handles to a memory segment, confirm that they are mapped |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 | 259 |
314 // Wait for the threads to finish. | 260 // Wait for the threads to finish. |
315 for (int index = 0; index < numthreads; index++) { | 261 for (int index = 0; index < numthreads; index++) { |
316 PlatformThread::Join(thread_handles[index]); | 262 PlatformThread::Join(thread_handles[index]); |
317 delete thread_delegates[index]; | 263 delete thread_delegates[index]; |
318 } | 264 } |
319 } | 265 } |
320 MultipleThreadMain::CleanUp(); | 266 MultipleThreadMain::CleanUp(); |
321 } | 267 } |
322 | 268 |
323 // TODO(port): this test requires the MultipleLockThread class | |
324 // (defined above), which requires the ability to pass file | |
325 // descriptors between processes. We haven't done that yet in Chrome | |
326 // for POSIX. | |
327 #if defined(OS_WIN) | |
328 // Create a set of threads to each open a shared memory segment and write to it | |
329 // with the lock held. Verify that they are always reading/writing consistent | |
330 // data. | |
331 TEST(SharedMemoryTest, Lock) { | |
332 PlatformThreadHandle thread_handles[kNumThreads]; | |
333 MultipleLockThread* thread_delegates[kNumThreads]; | |
334 | |
335 // Spawn the threads. | |
336 for (int index = 0; index < kNumThreads; ++index) { | |
337 PlatformThreadHandle pth; | |
338 thread_delegates[index] = new MultipleLockThread(index); | |
339 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); | |
340 thread_handles[index] = pth; | |
341 } | |
342 | |
343 // Wait for the threads to finish. | |
344 for (int index = 0; index < kNumThreads; ++index) { | |
345 PlatformThread::Join(thread_handles[index]); | |
346 delete thread_delegates[index]; | |
347 } | |
348 } | |
349 #endif | |
350 | |
351 // Allocate private (unique) shared memory with an empty string for a | 269 // Allocate private (unique) shared memory with an empty string for a |
352 // name. Make sure several of them don't point to the same thing as | 270 // name. Make sure several of them don't point to the same thing as |
353 // we might expect if the names are equal. | 271 // we might expect if the names are equal. |
354 TEST(SharedMemoryTest, AnonymousPrivate) { | 272 TEST(SharedMemoryTest, AnonymousPrivate) { |
355 int i, j; | 273 int i, j; |
356 int count = 4; | 274 int count = 4; |
357 bool rv; | 275 bool rv; |
358 const uint32 kDataSize = 8192; | 276 const uint32 kDataSize = 8192; |
359 | 277 |
360 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]); | 278 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 | 360 |
443 errno = 0; | 361 errno = 0; |
444 void* writable = mmap( | 362 void* writable = mmap( |
445 NULL, contents.size(), PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0); | 363 NULL, contents.size(), PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0); |
446 int mmap_errno = errno; | 364 int mmap_errno = errno; |
447 EXPECT_EQ(MAP_FAILED, writable) | 365 EXPECT_EQ(MAP_FAILED, writable) |
448 << "It shouldn't be possible to re-mmap the descriptor writable."; | 366 << "It shouldn't be possible to re-mmap the descriptor writable."; |
449 EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); | 367 EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); |
450 if (writable != MAP_FAILED) | 368 if (writable != MAP_FAILED) |
451 EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); | 369 EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); |
452 | |
453 #elif defined(OS_WIN) | |
454 EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0)) | |
455 << "Shouldn't be able to map memory writable."; | |
456 | |
457 HANDLE temp_handle; | |
458 BOOL rv = ::DuplicateHandle(GetCurrentProcess(), | |
459 handle, | |
460 GetCurrentProcess(), | |
461 &temp_handle, | |
462 FILE_MAP_ALL_ACCESS, | |
463 false, | |
464 0); | |
465 EXPECT_EQ(FALSE, rv) | |
466 << "Shouldn't be able to duplicate the handle into a writable one."; | |
467 if (rv) | |
468 base::win::ScopedHandle writable_handle(temp_handle); | |
469 rv = ::DuplicateHandle(GetCurrentProcess(), | |
470 handle, | |
471 GetCurrentProcess(), | |
472 &temp_handle, | |
473 FILE_MAP_READ, | |
474 false, | |
475 0); | |
476 EXPECT_EQ(TRUE, rv) | |
477 << "Should be able to duplicate the handle into a readable one."; | |
478 if (rv) | |
479 base::win::ScopedHandle writable_handle(temp_handle); | |
480 #else | 370 #else |
481 #error Unexpected platform; write a test that tries to make 'handle' writable. | 371 #error Unexpected platform; write a test that tries to make 'handle' writable. |
482 #endif // defined(OS_POSIX) || defined(OS_WIN) | 372 #endif // defined(OS_POSIX) |
483 } | 373 } |
484 | 374 |
485 TEST(SharedMemoryTest, ShareToSelf) { | 375 TEST(SharedMemoryTest, ShareToSelf) { |
486 StringPiece contents = "Hello World"; | 376 StringPiece contents = "Hello World"; |
487 | 377 |
488 SharedMemory shmem; | 378 SharedMemory shmem; |
489 ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); | 379 ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); |
490 memcpy(shmem.memory(), contents.data(), contents.size()); | 380 memcpy(shmem.memory(), contents.data(), contents.size()); |
491 EXPECT_TRUE(shmem.Unmap()); | 381 EXPECT_TRUE(shmem.Unmap()); |
492 | 382 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 SharedMemoryProcessTest::CleanUp(); | 604 SharedMemoryProcessTest::CleanUp(); |
715 } | 605 } |
716 | 606 |
717 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { | 607 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { |
718 return SharedMemoryProcessTest::TaskTestMain(); | 608 return SharedMemoryProcessTest::TaskTestMain(); |
719 } | 609 } |
720 | 610 |
721 #endif // !OS_IOS | 611 #endif // !OS_IOS |
722 | 612 |
723 } // namespace base | 613 } // namespace base |
OLD | NEW |