Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: third_party/tcmalloc/chromium/src/tests/malloc_hook_test.cc

Issue 9311003: Update the tcmalloc chromium branch to r144 (gperftools 2.0), and merge chromium-specific changes. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Rebasec Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, Google Inc. 1 // Copyright (c) 2011, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 18 matching lines...) Expand all
29 29
30 // ---- 30 // ----
31 // Author: llib@google.com (Bill Clarke) 31 // Author: llib@google.com (Bill Clarke)
32 32
33 #include "config_for_unittests.h" 33 #include "config_for_unittests.h"
34 #include <assert.h> 34 #include <assert.h>
35 #include <stdio.h> 35 #include <stdio.h>
36 #ifdef HAVE_MMAP 36 #ifdef HAVE_MMAP
37 #include <sys/mman.h> 37 #include <sys/mman.h>
38 #endif 38 #endif
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h> // for sleep()
41 #endif
39 #include <algorithm> 42 #include <algorithm>
40 #include <string> 43 #include <string>
41 #include <vector> 44 #include <vector>
42 #include <google/malloc_hook.h> 45 #include <gperftools/malloc_hook.h>
43 #include "malloc_hook-inl.h" 46 #include "malloc_hook-inl.h"
44 #include "base/logging.h" 47 #include "base/logging.h"
45 #include "base/spinlock.h" 48 #include "base/simple_mutex.h"
46 #include "base/sysinfo.h" 49 #include "base/sysinfo.h"
47 #include "tests/testutil.h" 50 #include "tests/testutil.h"
48 51
52 // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
53 // form of the name instead.
54 #ifndef MAP_ANONYMOUS
55 # define MAP_ANONYMOUS MAP_ANON
56 #endif
57
49 namespace { 58 namespace {
50 59
51 using std::string; 60 using std::string;
52 using std::vector; 61 using std::vector;
53 62
54 vector<void (*)()> g_testlist; // the tests to run 63 vector<void (*)()> g_testlist; // the tests to run
55 64
56 #define TEST(a, b) \ 65 #define TEST(a, b) \
57 struct Test_##a##_##b { \ 66 struct Test_##a##_##b { \
58 Test_##a##_##b() { g_testlist.push_back(&Run); } \ 67 Test_##a##_##b() { g_testlist.push_back(&Run); } \
59 static void Run(); \ 68 static void Run(); \
60 }; \ 69 }; \
61 static Test_##a##_##b g_test_##a##_##b; \ 70 static Test_##a##_##b g_test_##a##_##b; \
62 void Test_##a##_##b::Run() 71 void Test_##a##_##b::Run()
63 72
64 73
65 static int RUN_ALL_TESTS() { 74 static int RUN_ALL_TESTS() {
66 vector<void (*)()>::const_iterator it; 75 vector<void (*)()>::const_iterator it;
67 for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { 76 for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
68 (*it)(); // The test will error-exit if there's a problem. 77 (*it)(); // The test will error-exit if there's a problem.
69 } 78 }
70 fprintf(stderr, "\nPassed %d tests\n\nPASS\n", 79 fprintf(stderr, "\nPassed %d tests\n\nPASS\n",
71 static_cast<int>(g_testlist.size())); 80 static_cast<int>(g_testlist.size()));
72 return 0; 81 return 0;
73 } 82 }
74 83
84 void Sleep(int seconds) {
85 #ifdef _MSC_VER
86 _sleep(seconds * 1000); // Windows's _sleep takes milliseconds argument
87 #else
88 sleep(seconds);
89 #endif
90 }
91
92 using std::min;
75 using base::internal::kHookListMaxValues; 93 using base::internal::kHookListMaxValues;
76 94
77 // Since HookList is a template and is defined in malloc_hook.cc, we can only 95 // Since HookList is a template and is defined in malloc_hook.cc, we can only
78 // use an instantiation of it from malloc_hook.cc. We then reinterpret those 96 // use an instantiation of it from malloc_hook.cc. We then reinterpret those
79 // values as integers for testing. 97 // values as integers for testing.
80 typedef base::internal::HookList<MallocHook::NewHook> TestHookList; 98 typedef base::internal::HookList<MallocHook::NewHook> TestHookList;
81 99
82 int TestHookList_Traverse(const TestHookList& list, int* output_array, int n) { 100 int TestHookList_Traverse(const TestHookList& list, int* output_array, int n) {
83 MallocHook::NewHook values_as_hooks[kHookListMaxValues]; 101 MallocHook::NewHook values_as_hooks[kHookListMaxValues];
84 int result = list.Traverse(values_as_hooks, std::min(n, kHookListMaxValues)); 102 int result = list.Traverse(values_as_hooks, min(n, kHookListMaxValues));
85 for (int i = 0; i < result; ++i) { 103 for (int i = 0; i < result; ++i) {
86 output_array[i] = reinterpret_cast<const int&>(values_as_hooks[i]); 104 output_array[i] = reinterpret_cast<const int&>(values_as_hooks[i]);
87 } 105 }
88 return result; 106 return result;
89 } 107 }
90 108
91 bool TestHookList_Add(TestHookList* list, int val) { 109 bool TestHookList_Add(TestHookList* list, int val) {
92 return list->Add(reinterpret_cast<MallocHook::NewHook>(val)); 110 return list->Add(reinterpret_cast<MallocHook::NewHook>(val));
93 } 111 }
94 112
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 EXPECT_EQ(value_index, num_values); // Should not have found value. 240 EXPECT_EQ(value_index, num_values); // Should not have found value.
223 snprintf(buf, sizeof(buf), "%d]", num_values); 241 snprintf(buf, sizeof(buf), "%d]", num_values);
224 message += buf; 242 message += buf;
225 sched_yield(); 243 sched_yield();
226 } 244 }
227 fprintf(stderr, "thread %d: %s\n", thread_num, message.c_str()); 245 fprintf(stderr, "thread %d: %s\n", thread_num, message.c_str());
228 } 246 }
229 247
230 static volatile int num_threads_remaining; 248 static volatile int num_threads_remaining;
231 static TestHookList list = INIT_HOOK_LIST(69); 249 static TestHookList list = INIT_HOOK_LIST(69);
232 static SpinLock threadcount_lock; 250 static Mutex threadcount_lock;
233 251
234 void MultithreadedTestThreadRunner(int thread_num) { 252 void MultithreadedTestThreadRunner(int thread_num) {
235 // Wait for all threads to start running. 253 // Wait for all threads to start running.
236 { 254 {
237 SpinLockHolder h(&threadcount_lock); 255 MutexLock ml(&threadcount_lock);
238 assert(num_threads_remaining > 0); 256 assert(num_threads_remaining > 0);
239 --num_threads_remaining; 257 --num_threads_remaining;
240 258
241 // We should use condvars and the like, but for this test, we'll 259 // We should use condvars and the like, but for this test, we'll
242 // go simple and busy-wait. 260 // go simple and busy-wait.
243 while (num_threads_remaining > 0) { 261 while (num_threads_remaining > 0) {
244 threadcount_lock.Unlock(); 262 threadcount_lock.Unlock();
245 SleepForMilliseconds(100); 263 Sleep(1);
246 threadcount_lock.Lock(); 264 threadcount_lock.Lock();
247 } 265 }
248 } 266 }
249 267
250 // shift is the smallest number such that (1<<shift) > kHookListMaxValues 268 // shift is the smallest number such that (1<<shift) > kHookListMaxValues
251 int shift = 0; 269 int shift = 0;
252 for (int i = kHookListMaxValues; i > 0; i >>= 1) 270 for (int i = kHookListMaxValues; i > 0; i >>= 1)
253 shift += 1; 271 shift += 1;
254 272
255 MultithreadedTestThread(&list, shift, thread_num); 273 MultithreadedTestThread(&list, shift, thread_num);
256 } 274 }
257 275
258 276
259 TEST(HookListTest, MultithreadedTest) { 277 TEST(HookListTest, MultithreadedTest) {
260 ASSERT_TRUE(TestHookList_Remove(&list, 69)); 278 ASSERT_TRUE(TestHookList_Remove(&list, 69));
261 ASSERT_EQ(0, list.priv_end); 279 ASSERT_EQ(0, list.priv_end);
262 280
263 // Run kHookListMaxValues thread, each running MultithreadedTestThread. 281 // Run kHookListMaxValues thread, each running MultithreadedTestThread.
264 // First, we need to set up the rest of the globals. 282 // First, we need to set up the rest of the globals.
265 num_threads_remaining = kHookListMaxValues; // a global var 283 num_threads_remaining = kHookListMaxValues; // a global var
266 RunManyThreadsWithId(&MultithreadedTestThreadRunner, num_threads_remaining, 284 RunManyThreadsWithId(&MultithreadedTestThreadRunner, num_threads_remaining,
267 1 << 15); 285 1 << 15);
268 286
269 int values[kHookListMaxValues + 1]; 287 int values[kHookListMaxValues + 1];
270 EXPECT_EQ(0, TestHookList_Traverse(list, values, kHookListMaxValues)); 288 EXPECT_EQ(0, TestHookList_Traverse(list, values, kHookListMaxValues));
271 EXPECT_EQ(0, list.priv_end); 289 EXPECT_EQ(0, list.priv_end);
272 } 290 }
273 291
274 #ifdef HAVE_MMAP 292 // We only do mmap-hooking on (some) linux systems.
293 #if defined(HAVE_MMAP) && defined(__linux) && \
294 (defined(__i386__) || defined(__x86_64__) || defined(__PPC__))
295
275 int mmap_calls = 0; 296 int mmap_calls = 0;
276 int mmap_matching_calls = 0; 297 int mmap_matching_calls = 0;
277 int munmap_calls = 0; 298 int munmap_calls = 0;
278 int munmap_matching_calls = 0; 299 int munmap_matching_calls = 0;
279 const int kMmapMagicFd = 1; 300 const int kMmapMagicFd = 1;
280 void* const kMmapMagicPointer = reinterpret_cast<void*>(1); 301 void* const kMmapMagicPointer = reinterpret_cast<void*>(1);
281 302
282 int MmapReplacement(const void* start, 303 int MmapReplacement(const void* start,
283 size_t size, 304 size_t size,
284 int protection, 305 int protection,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 EXPECT_EQ(2, munmap_calls); 350 EXPECT_EQ(2, munmap_calls);
330 EXPECT_EQ(1, munmap_matching_calls); 351 EXPECT_EQ(1, munmap_matching_calls);
331 352
332 // The DEATH test below is flaky, because we've just munmapped the memory, 353 // The DEATH test below is flaky, because we've just munmapped the memory,
333 // making it available for mmap()ing again. There is no guarantee that it 354 // making it available for mmap()ing again. There is no guarantee that it
334 // will stay unmapped, and in fact it gets reused ~10% of the time. 355 // will stay unmapped, and in fact it gets reused ~10% of the time.
335 // It the area is reused, then not only we don't die, but we also corrupt 356 // It the area is reused, then not only we don't die, but we also corrupt
336 // whoever owns that memory now. 357 // whoever owns that memory now.
337 // EXPECT_DEATH(*ptr = 'a', "SIGSEGV"); 358 // EXPECT_DEATH(*ptr = 'a', "SIGSEGV");
338 } 359 }
339 #endif // #ifdef HAVE_MMAN 360 #endif // #ifdef HAVE_MMAP && linux && ...
340 361
341 } // namespace 362 } // namespace
342 363
343 int main(int argc, char** argv) { 364 int main(int argc, char** argv) {
344 return RUN_ALL_TESTS(); 365 return RUN_ALL_TESTS();
345 } 366 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698