1 // Copyright (c) 2005, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // --- 31 // Unittest for the TCMalloc implementation. 32 // 33 // * The test consists of a set of threads. 34 // * Each thread maintains a set of allocated objects, with 35 // a bound on the total amount of data in the set. 36 // * Each allocated object's contents are generated by 37 // hashing the object pointer, and a generation count 38 // in the object. This allows us to easily check for 39 // data corruption. 40 // * At any given step, the thread can do any of the following: 41 // a. Allocate an object 42 // b. Increment an object's generation count and update 43 // its contents. 44 // c. Pass the object to another thread 45 // d. Free an object 46 // Also, at the end of every step, object(s) are freed to maintain 47 // the memory upper-bound. 48 // 49 // If this test is compiled with -DDEBUGALLOCATION, then we don't 50 // run some tests that test the inner workings of tcmalloc and 51 // break on debugallocation: that certain allocations are aligned 52 // in a certain way (even though no standard requires it), and that 53 // realloc() tries to minimize copying (which debug allocators don't 54 // care about). 55 56 #include "config_for_unittests.h" 57 // Complicated ordering requirements. tcmalloc.h defines (indirectly) 58 // _POSIX_C_SOURCE, which it needs so stdlib.h defines posix_memalign. 59 // unistd.h, on the other hand, requires _POSIX_C_SOURCE to be unset, 60 // at least on FreeBSD, in order to define sbrk. The solution 61 // is to #include unistd.h first. This is safe because unistd.h 62 // doesn't sub-include stdlib.h, so we'll still get posix_memalign 63 // when we #include stdlib.h. Blah. 64 #ifdef HAVE_UNISTD_H 65 #include <unistd.h> // for testing sbrk hooks 66 #endif 67 #include "tcmalloc.h" // must come early, to pick up posix_memalign 68 #include <stdlib.h> 69 #include <string.h> 70 #include <stdio.h> 71 #if defined HAVE_STDINT_H 72 #include <stdint.h> // for intptr_t 73 #endif 74 #include <sys/types.h> // for size_t 75 #ifdef HAVE_FCNTL_H 76 #include <fcntl.h> // for open; used with mmap-hook test 77 #endif 78 #ifdef HAVE_MMAP 79 #include <sys/mman.h> // for testing mmap hooks 80 #endif 81 #ifdef HAVE_MALLOC_H 82 #include <malloc.h> // defines pvalloc/etc on cygwin 83 #endif 84 #include <assert.h> 85 #include <vector> 86 #include <algorithm> 87 #include <string> 88 #include <new> 89 #include "base/logging.h" 90 #include "base/simple_mutex.h" 91 #include "gperftools/malloc_hook.h" 92 #include "gperftools/malloc_extension.h" 93 #include "gperftools/tcmalloc.h" 94 #include "thread_cache.h" 95 #include "tests/testutil.h" 96 97 // Windows doesn't define pvalloc and a few other obsolete unix 98 // functions; nor does it define posix_memalign (which is not obsolete). 99 #if defined(_WIN32) 100 # define cfree free // don't bother to try to test these obsolete fns 101 # define valloc malloc 102 # define pvalloc malloc 103 // I'd like to map posix_memalign to _aligned_malloc, but _aligned_malloc 104 // must be paired with _aligned_free (not normal free), which is too 105 // invasive a change to how we allocate memory here. So just bail 106 static bool kOSSupportsMemalign = false; 107 static inline void* Memalign(size_t align, size_t size) { 108 //LOG(FATAL) << "memalign not supported on windows"; 109 exit(1); 110 return NULL; 111 } 112 static inline int PosixMemalign(void** ptr, size_t align, size_t size) { 113 //LOG(FATAL) << "posix_memalign not supported on windows"; 114 exit(1); 115 return -1; 116 } 117 118 // OS X defines posix_memalign in some OS versions but not others; 119 // it's confusing enough to check that it's easiest to just not to test. 120 #elif defined(__APPLE__) 121 static bool kOSSupportsMemalign = false; 122 static inline void* Memalign(size_t align, size_t size) { 123 //LOG(FATAL) << "memalign not supported on OS X"; 124 exit(1); 125 return NULL; 126 } 127 static inline int PosixMemalign(void** ptr, size_t align, size_t size) { 128 //LOG(FATAL) << "posix_memalign not supported on OS X"; 129 exit(1); 130 return -1; 131 } 132 133 #else 134 static bool kOSSupportsMemalign = true; 135 static inline void* Memalign(size_t align, size_t size) { 136 return memalign(align, size); 137 } 138 static inline int PosixMemalign(void** ptr, size_t align, size_t size) { 139 return posix_memalign(ptr, align, size); 140 } 141 142 #endif 143 144 // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old 145 // form of the name instead. 146 #ifndef MAP_ANONYMOUS 147 # define MAP_ANONYMOUS MAP_ANON 148 #endif 149 150 #define LOGSTREAM stdout 151 152 using std::vector; 153 using std::string; 154 155 DECLARE_double(tcmalloc_release_rate); 156 DECLARE_int32(max_free_queue_size); // in debugallocation.cc 157 DECLARE_int64(tcmalloc_sample_parameter); 158 159 namespace testing { 160 161 static const int FLAGS_numtests = 50000; 162 static const int FLAGS_log_every_n_tests = 50000; // log exactly once 163 164 // Testing parameters 165 static const int FLAGS_lgmaxsize = 16; // lg() of the max size object to alloc 166 static const int FLAGS_numthreads = 10; // Number of threads 167 static const int FLAGS_threadmb = 4; // Max memory size allocated by thread 168 static const int FLAGS_lg_max_memalign = 18; // lg of max alignment for memalign 169 170 static const double FLAGS_memalign_min_fraction = 0; // min expected% 171 static const double FLAGS_memalign_max_fraction = 0.4; // max expected% 172 static const double FLAGS_memalign_max_alignment_ratio = 6; // alignment/size 173 174 // Weights of different operations 175 static const int FLAGS_allocweight = 50; // Weight for picking allocation 176 static const int FLAGS_freeweight = 50; // Weight for picking free 177 static const int FLAGS_updateweight = 10; // Weight for picking update 178 static const int FLAGS_passweight = 1; // Weight for passing object 179 180 static const int kSizeBits = 8 * sizeof(size_t); 181 static const size_t kMaxSize = ~static_cast<size_t>(0); 182 static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1); 183 184 static const size_t kNotTooBig = 100000; 185 // We want an allocation that is definitely more than main memory. OS 186 // X has special logic to discard very big allocs before even passing 187 // the request along to the user-defined memory allocator; we're not 188 // interested in testing their logic, so we have to make sure we're 189 // not *too* big. 190 static const size_t kTooBig = kMaxSize - 100000; 191 192 static int news_handled = 0; 193 194 // Global array of threads 195 class TesterThread; 196 static TesterThread** threads; 197 198 // To help with generating random numbers 199 class TestHarness { 200 private: 201 // Information kept per type 202 struct Type { 203 string name; 204 int type; 205 int weight; 206 }; 207 208 public: 209 TestHarness(int seed) 210 : types_(new vector<Type>), total_weight_(0), num_tests_(0) { 211 srandom(seed); 212 } 213 ~TestHarness() { 214 delete types_; 215 } 216 217 // Add operation type with specified weight. When starting a new 218 // iteration, an operation type is picked with probability 219 // proportional to its weight. 220 // 221 // "type" must be non-negative. 222 // "weight" must be non-negative. 223 void AddType(int type, int weight, const char* name); 224 225 // Call this to get the type of operation for the next iteration. 226 // It returns a random operation type from the set of registered 227 // operations. Returns -1 if tests should finish. 228 int PickType(); 229 230 // If n == 0, returns the next pseudo-random number in the range [0 .. 0] 231 // If n != 0, returns the next pseudo-random number in the range [0 .. n) 232 int Uniform(int n) { 233 if (n == 0) { 234 return random() * 0; 235 } else { 236 return random() % n; 237 } 238 } 239 // Pick "base" uniformly from range [0,max_log] and then return 240 // "base" random bits. The effect is to pick a number in the range 241 // [0,2^max_log-1] with bias towards smaller numbers. 242 int Skewed(int max_log) { 243 const int base = random() % (max_log+1); 244 return random() % (1 << base); 245 } 246 247 private: 248 vector<Type>* types_; // Registered types 249 int total_weight_; // Total weight of all types 250 int num_tests_; // Num tests run so far 251 }; 252 253 void TestHarness::AddType(int type, int weight, const char* name) { 254 Type t; 255 t.name = name; 256 t.type = type; 257 t.weight = weight; 258 types_->push_back(t); 259 total_weight_ += weight; 260 } 261 262 int TestHarness::PickType() { 263 if (num_tests_ >= FLAGS_numtests) return -1; 264 num_tests_++; 265 266 assert(total_weight_ > 0); 267 // This is a little skewed if total_weight_ doesn't divide 2^31, but it's close 268 int v = Uniform(total_weight_); 269 int i; 270 for (i = 0; i < types_->size(); i++) { 271 v -= (*types_)[i].weight; 272 if (v < 0) { 273 break; 274 } 275 } 276 277 assert(i < types_->size()); 278 if ((num_tests_ % FLAGS_log_every_n_tests) == 0) { 279 fprintf(LOGSTREAM, " Test %d out of %d: %s\n", 280 num_tests_, FLAGS_numtests, (*types_)[i].name.c_str()); 281 } 282 return (*types_)[i].type; 283 } 284 285 class AllocatorState : public TestHarness { 286 public: 287 explicit AllocatorState(int seed) : TestHarness(seed), memalign_fraction_(0) { 288 if (kOSSupportsMemalign) { 289 CHECK_GE(FLAGS_memalign_max_fraction, 0); 290 CHECK_LE(FLAGS_memalign_max_fraction, 1); 291 CHECK_GE(FLAGS_memalign_min_fraction, 0); 292 CHECK_LE(FLAGS_memalign_min_fraction, 1); 293 double delta = FLAGS_memalign_max_fraction - FLAGS_memalign_min_fraction; 294 CHECK_GE(delta, 0); 295 memalign_fraction_ = (Uniform(10000)/10000.0 * delta + 296 FLAGS_memalign_min_fraction); 297 //fprintf(LOGSTREAM, "memalign fraction: %f\n", memalign_fraction_); 298 } 299 } 300 virtual ~AllocatorState() {} 301 302 // Allocate memory. Randomly choose between malloc() or posix_memalign(). 303 void* alloc(size_t size) { 304 if (Uniform(100) < memalign_fraction_ * 100) { 305 // Try a few times to find a reasonable alignment, or fall back on malloc. 306 for (int i = 0; i < 5; i++) { 307 size_t alignment = 1 << Uniform(FLAGS_lg_max_memalign); 308 if (alignment >= sizeof(intptr_t) && 309 (size < sizeof(intptr_t) || 310 alignment < FLAGS_memalign_max_alignment_ratio * size)) { 311 void *result = reinterpret_cast<void*>(static_cast<intptr_t>(0x1234)); 312 int err = PosixMemalign(&result, alignment, size); 313 if (err != 0) { 314 CHECK_EQ(err, ENOMEM); 315 } 316 return err == 0 ? result : NULL; 317 } 318 } 319 } 320 return malloc(size); 321 } 322 323 private: 324 double memalign_fraction_; 325 }; 326 327 328 // Info kept per thread 329 class TesterThread { 330 private: 331 // Info kept per allocated object 332 struct Object { 333 char* ptr; // Allocated pointer 334 int size; // Allocated size 335 int generation; // Generation counter of object contents 336 }; 337 338 Mutex lock_; // For passing in another thread's obj 339 int id_; // My thread id 340 AllocatorState rnd_; // For generating random numbers 341 vector<Object> heap_; // This thread's heap 342 vector<Object> passed_; // Pending objects passed from others 343 size_t heap_size_; // Current heap size 344 int locks_ok_; // Number of OK TryLock() ops 345 int locks_failed_; // Number of failed TryLock() ops 346 347 // Type of operations 348 enum Type { ALLOC, FREE, UPDATE, PASS }; 349 350 // ACM minimal standard random number generator. (re-entrant.) 351 class ACMRandom { 352 int32 seed_; 353 public: 354 explicit ACMRandom(int32 seed) { seed_ = seed; } 355 int32 Next() { 356 const int32 M = 2147483647L; // 2^31-1 357 const int32 A = 16807; 358 // In effect, we are computing seed_ = (seed_ * A) % M, where M = 2^31-1 359 uint32 lo = A * (int32)(seed_ & 0xFFFF); 360 uint32 hi = A * (int32)((uint32)seed_ >> 16); 361 lo += (hi & 0x7FFF) << 16; 362 if (lo > M) { 363 lo &= M; 364 ++lo; 365 } 366 lo += hi >> 15; 367 if (lo > M) { 368 lo &= M; 369 ++lo; 370 } 371 return (seed_ = (int32) lo); 372 } 373 }; 374 375 public: 376 TesterThread(int id) 377 : id_(id), 378 rnd_(id+1), 379 heap_size_(0), 380 locks_ok_(0), 381 locks_failed_(0) { 382 } 383 384 virtual ~TesterThread() { 385 if (FLAGS_verbose) 386 fprintf(LOGSTREAM, "Thread %2d: locks %6d ok; %6d trylocks failed\n", 387 id_, locks_ok_, locks_failed_); 388 if (locks_ok_ + locks_failed_ >= 1000) { 389 CHECK_LE(locks_failed_, locks_ok_ / 2); 390 } 391 } 392 393 virtual void Run() { 394 rnd_.AddType(ALLOC, FLAGS_allocweight, "allocate"); 395 rnd_.AddType(FREE, FLAGS_freeweight, "free"); 396 rnd_.AddType(UPDATE, FLAGS_updateweight, "update"); 397 rnd_.AddType(PASS, FLAGS_passweight, "pass"); 398 399 while (true) { 400 AcquirePassedObjects(); 401 402 switch (rnd_.PickType()) { 403 case ALLOC: AllocateObject(); break; 404 case FREE: FreeObject(); break; 405 case UPDATE: UpdateObject(); break; 406 case PASS: PassObject(); break; 407 case -1: goto done; 408 default: assert(NULL == "Unknown type"); 409 } 410 411 ShrinkHeap(); 412 } 413 414 done: 415 DeleteHeap(); 416 } 417 418 // Allocate a new object 419 void AllocateObject() { 420 Object object; 421 object.size = rnd_.Skewed(FLAGS_lgmaxsize); 422 object.ptr = static_cast<char*>(rnd_.alloc(object.size)); 423 CHECK(object.ptr); 424 object.generation = 0; 425 FillContents(&object); 426 heap_.push_back(object); 427 heap_size_ += object.size; 428 } 429 430 // Mutate a random object 431 void UpdateObject() { 432 if (heap_.empty()) return; 433 const int index = rnd_.Uniform(heap_.size()); 434 CheckContents(heap_[index]); 435 heap_[index].generation++; 436 FillContents(&heap_[index]); 437 } 438 439 // Free a random object 440 void FreeObject() { 441 if (heap_.empty()) return; 442 const int index = rnd_.Uniform(heap_.size()); 443 Object object = heap_[index]; 444 CheckContents(object); 445 free(object.ptr); 446 heap_size_ -= object.size; 447 heap_[index] = heap_[heap_.size()-1]; 448 heap_.pop_back(); 449 } 450 451 // Delete all objects in the heap 452 void DeleteHeap() { 453 while (!heap_.empty()) { 454 FreeObject(); 455 } 456 } 457 458 // Free objects until our heap is small enough 459 void ShrinkHeap() { 460 while (heap_size_ > FLAGS_threadmb << 20) { 461 assert(!heap_.empty()); 462 FreeObject(); 463 } 464 } 465 466 // Pass a random object to another thread 467 void PassObject() { 468 // Pick object to pass 469 if (heap_.empty()) return; 470 const int index = rnd_.Uniform(heap_.size()); 471 Object object = heap_[index]; 472 CheckContents(object); 473 474 // Pick thread to pass 475 const int tid = rnd_.Uniform(FLAGS_numthreads); 476 TesterThread* thread = threads[tid]; 477 478 if (thread->lock_.TryLock()) { 479 // Pass the object 480 locks_ok_++; 481 thread->passed_.push_back(object); 482 thread->lock_.Unlock(); 483 heap_size_ -= object.size; 484 heap_[index] = heap_[heap_.size()-1]; 485 heap_.pop_back(); 486 } else { 487 locks_failed_++; 488 } 489 } 490 491 // Grab any objects passed to this thread by another thread 492 void AcquirePassedObjects() { 493 // We do not create unnecessary contention by always using 494 // TryLock(). Plus we unlock immediately after swapping passed 495 // objects into a local vector. 496 vector<Object> copy; 497 { // Locking scope 498 if (!lock_.TryLock()) { 499 locks_failed_++; 500 return; 501 } 502 locks_ok_++; 503 swap(copy, passed_); 504 lock_.Unlock(); 505 } 506 507 for (int i = 0; i < copy.size(); ++i) { 508 const Object& object = copy[i]; 509 CheckContents(object); 510 heap_.push_back(object); 511 heap_size_ += object.size; 512 } 513 } 514 515 // Fill object contents according to ptr/generation 516 void FillContents(Object* object) { 517 ACMRandom r(reinterpret_cast<intptr_t>(object->ptr) & 0x7fffffff); 518 for (int i = 0; i < object->generation; ++i) { 519 r.Next(); 520 } 521 const char c = static_cast<char>(r.Next()); 522 memset(object->ptr, c, object->size); 523 } 524 525 // Check object contents 526 void CheckContents(const Object& object) { 527 ACMRandom r(reinterpret_cast<intptr_t>(object.ptr) & 0x7fffffff); 528 for (int i = 0; i < object.generation; ++i) { 529 r.Next(); 530 } 531 532 // For large objects, we just check a prefix/suffix 533 const char expected = static_cast<char>(r.Next()); 534 const int limit1 = object.size < 32 ? object.size : 32; 535 const int start2 = limit1 > object.size - 32 ? limit1 : object.size - 32; 536 for (int i = 0; i < limit1; ++i) { 537 CHECK_EQ(object.ptr[i], expected); 538 } 539 for (int i = start2; i < object.size; ++i) { 540 CHECK_EQ(object.ptr[i], expected); 541 } 542 } 543 }; 544 545 static void RunThread(int thread_id) { 546 threads[thread_id]->Run(); 547 } 548 549 static void TryHugeAllocation(size_t s, AllocatorState* rnd) { 550 void* p = rnd->alloc(s); 551 CHECK(p == NULL); // huge allocation s should fail! 552 } 553 554 static void TestHugeAllocations(AllocatorState* rnd) { 555 // Check that asking for stuff tiny bit smaller than largest possible 556 // size returns NULL. 557 for (size_t i = 0; i < 70000; i += rnd->Uniform(20)) { 558 TryHugeAllocation(kMaxSize - i, rnd); 559 } 560 // Asking for memory sizes near signed/unsigned boundary (kMaxSignedSize) 561 // might work or not, depending on the amount of virtual memory. 562 #ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs 563 for (size_t i = 0; i < 100; i++) { 564 void* p = NULL; 565 p = rnd->alloc(kMaxSignedSize + i); 566 if (p) free(p); // if: free(NULL) is not necessarily defined 567 p = rnd->alloc(kMaxSignedSize - i); 568 if (p) free(p); 569 } 570 #endif 571 572 // Check that ReleaseFreeMemory has no visible effect (aka, does not 573 // crash the test): 574 MallocExtension* inst = MallocExtension::instance(); 575 CHECK(inst); 576 inst->ReleaseFreeMemory(); 577 } 578 579 static void TestCalloc(size_t n, size_t s, bool ok) { 580 char* p = reinterpret_cast<char*>(calloc(n, s)); 581 if (FLAGS_verbose) 582 fprintf(LOGSTREAM, "calloc(%"PRIxS", %"PRIxS"): %p\n", n, s, p); 583 if (!ok) { 584 CHECK(p == NULL); // calloc(n, s) should not succeed 585 } else { 586 CHECK(p != NULL); // calloc(n, s) should succeed 587 for (int i = 0; i < n*s; i++) { 588 CHECK(p[i] == '\0'); 589 } 590 free(p); 591 } 592 } 593 594 // This makes sure that reallocing a small number of bytes in either 595 // direction doesn't cause us to allocate new memory. 596 static void TestRealloc() { 597 #ifndef DEBUGALLOCATION // debug alloc doesn't try to minimize reallocs 598 // When sampling, we always allocate in units of page-size, which 599 // makes reallocs of small sizes do extra work (thus, failing these 600 // checks). Since sampling is random, we turn off sampling to make 601 // sure that doesn't happen to us here. 602 const int64 old_sample_parameter = FLAGS_tcmalloc_sample_parameter; 603 FLAGS_tcmalloc_sample_parameter = 0; // turn off sampling 604 605 int start_sizes[] = { 100, 1000, 10000, 100000 }; 606 int deltas[] = { 1, -2, 4, -8, 16, -32, 64, -128 }; 607 608 for (int s = 0; s < sizeof(start_sizes)/sizeof(*start_sizes); ++s) { 609 void* p = malloc(start_sizes[s]); 610 CHECK(p); 611 // The larger the start-size, the larger the non-reallocing delta. 612 for (int d = 0; d < (s+1) * 2; ++d) { 613 void* new_p = realloc(p, start_sizes[s] + deltas[d]); 614 CHECK(p == new_p); // realloc should not allocate new memory 615 } 616 // Test again, but this time reallocing smaller first. 617 for (int d = 0; d < s*2; ++d) { 618 void* new_p = realloc(p, start_sizes[s] - deltas[d]); 619 CHECK(p == new_p); // realloc should not allocate new memory 620 } 621 free(p); 622 } 623 FLAGS_tcmalloc_sample_parameter = old_sample_parameter; 624 #endif 625 } 626 627 static void TestNewHandler() throw (std::bad_alloc) { 628 ++news_handled; 629 throw std::bad_alloc(); 630 } 631 632 static void TestOneNew(void* (*func)(size_t)) { 633 // success test 634 try { 635 void* ptr = (*func)(kNotTooBig); 636 if (0 == ptr) { 637 fprintf(LOGSTREAM, "allocation should not have failed.\n"); 638 abort(); 639 } 640 } catch (...) { 641 fprintf(LOGSTREAM, "allocation threw unexpected exception.\n"); 642 abort(); 643 } 644 645 // failure test 646 // we should always receive a bad_alloc exception 647 try { 648 (*func)(kTooBig); 649 fprintf(LOGSTREAM, "allocation should have failed.\n"); 650 abort(); 651 } catch (const std::bad_alloc&) { 652 // correct 653 } catch (...) { 654 fprintf(LOGSTREAM, "allocation threw unexpected exception.\n"); 655 abort(); 656 } 657 } 658 659 static void TestNew(void* (*func)(size_t)) { 660 news_handled = 0; 661 662 // test without new_handler: 663 std::new_handler saved_handler = std::set_new_handler(0); 664 TestOneNew(func); 665 666 // test with new_handler: 667 std::set_new_handler(TestNewHandler); 668 TestOneNew(func); 669 if (news_handled != 1) { 670 fprintf(LOGSTREAM, "new_handler was not called.\n"); 671 abort(); 672 } 673 std::set_new_handler(saved_handler); 674 } 675 676 static void TestOneNothrowNew(void* (*func)(size_t, const std::nothrow_t&)) { 677 // success test 678 try { 679 void* ptr = (*func)(kNotTooBig, std::nothrow); 680 if (0 == ptr) { 681 fprintf(LOGSTREAM, "allocation should not have failed.\n"); 682 abort(); 683 } 684 } catch (...) { 685 fprintf(LOGSTREAM, "allocation threw unexpected exception.\n"); 686 abort(); 687 } 688 689 // failure test 690 // we should always receive a bad_alloc exception 691 try { 692 if ((*func)(kTooBig, std::nothrow) != 0) { 693 fprintf(LOGSTREAM, "allocation should have failed.\n"); 694 abort(); 695 } 696 } catch (...) { 697 fprintf(LOGSTREAM, "nothrow allocation threw unexpected exception.\n"); 698 abort(); 699 } 700 } 701 702 static void TestNothrowNew(void* (*func)(size_t, const std::nothrow_t&)) { 703 news_handled = 0; 704 705 // test without new_handler: 706 std::new_handler saved_handler = std::set_new_handler(0); 707 TestOneNothrowNew(func); 708 709 // test with new_handler: 710 std::set_new_handler(TestNewHandler); 711 TestOneNothrowNew(func); 712 if (news_handled != 1) { 713 fprintf(LOGSTREAM, "nothrow new_handler was not called.\n"); 714 abort(); 715 } 716 std::set_new_handler(saved_handler); 717 } 718 719 720 // These are used as callbacks by the sanity-check. Set* and Reset* 721 // register the hook that counts how many times the associated memory 722 // function is called. After each such call, call Verify* to verify 723 // that we used the tcmalloc version of the call, and not the libc. 724 // Note the ... in the hook signature: we don't care what arguments 725 // the hook takes. 726 #define MAKE_HOOK_CALLBACK(hook_type) \ 727 static int g_##hook_type##_calls = 0; \ 728 static void IncrementCallsTo##hook_type(...) { \ 729 g_##hook_type##_calls++; \ 730 } \ 731 static void Verify##hook_type##WasCalled() { \ 732 CHECK_GT(g_##hook_type##_calls, 0); \ 733 g_##hook_type##_calls = 0; /* reset for next call */ \ 734 } \ 735 static void Set##hook_type() { \ 736 CHECK(MallocHook::Add##hook_type( \ 737 (MallocHook::hook_type)&IncrementCallsTo##hook_type)); \ 738 } \ 739 static void Reset##hook_type() { \ 740 CHECK(MallocHook::Remove##hook_type( \ 741 (MallocHook::hook_type)&IncrementCallsTo##hook_type)); \ 742 } 743 744 // We do one for each hook typedef in malloc_hook.h 745 MAKE_HOOK_CALLBACK(NewHook); 746 MAKE_HOOK_CALLBACK(DeleteHook); 747 MAKE_HOOK_CALLBACK(MmapHook); 748 MAKE_HOOK_CALLBACK(MremapHook); 749 MAKE_HOOK_CALLBACK(MunmapHook); 750 MAKE_HOOK_CALLBACK(SbrkHook); 751 752 static void TestAlignmentForSize(int size) { 753 fprintf(LOGSTREAM, "Testing alignment of malloc(%d)\n", size); 754 static const int kNum = 100; 755 void* ptrs[kNum]; 756 for (int i = 0; i < kNum; i++) { 757 ptrs[i] = malloc(size); 758 uintptr_t p = reinterpret_cast<uintptr_t>(ptrs[i]); 759 CHECK((p % sizeof(void*)) == 0); 760 CHECK((p % sizeof(double)) == 0); 761 762 // Must have 16-byte alignment for large enough objects 763 if (size >= 16) { 764 CHECK((p % 16) == 0); 765 } 766 } 767 for (int i = 0; i < kNum; i++) { 768 free(ptrs[i]); 769 } 770 } 771 772 static void TestMallocAlignment() { 773 for (int lg = 0; lg < 16; lg++) { 774 TestAlignmentForSize((1<<lg) - 1); 775 TestAlignmentForSize((1<<lg) + 0); 776 TestAlignmentForSize((1<<lg) + 1); 777 } 778 } 779 780 static void TestHugeThreadCache() { 781 fprintf(LOGSTREAM, "==== Testing huge thread cache\n"); 782 // More than 2^16 to cause integer overflow of 16 bit counters. 783 static const int kNum = 70000; 784 char** array = new char*[kNum]; 785 for (int i = 0; i < kNum; ++i) { 786 array[i] = new char[10]; 787 } 788 for (int i = 0; i < kNum; ++i) { 789 delete[] array[i]; 790 } 791 delete[] array; 792 } 793 794 namespace { 795 796 struct RangeCallbackState { 797 uintptr_t ptr; 798 base::MallocRange::Type expected_type; 799 size_t min_size; 800 bool matched; 801 }; 802 803 static void RangeCallback(void* arg, const base::MallocRange* r) { 804 RangeCallbackState* state = reinterpret_cast<RangeCallbackState*>(arg); 805 if (state->ptr >= r->address && 806 state->ptr < r->address + r->length) { 807 if (state->expected_type == base::MallocRange::FREE) { 808 // We are expecting r->type == FREE, but ReleaseMemory 809 // may have already moved us to UNMAPPED state instead (this happens in 810 // approximately 0.1% of executions). Accept either state. 811 CHECK(r->type == base::MallocRange::FREE || 812 r->type == base::MallocRange::UNMAPPED); 813 } else { 814 CHECK_EQ(r->type, state->expected_type); 815 } 816 CHECK_GE(r->length, state->min_size); 817 state->matched = true; 818 } 819 } 820 821 // Check that at least one of the callbacks from Ranges() contains 822 // the specified address with the specified type, and has size 823 // >= min_size. 824 static void CheckRangeCallback(void* ptr, base::MallocRange::Type type, 825 size_t min_size) { 826 RangeCallbackState state; 827 state.ptr = reinterpret_cast<uintptr_t>(ptr); 828 state.expected_type = type; 829 state.min_size = min_size; 830 state.matched = false; 831 MallocExtension::instance()->Ranges(&state, RangeCallback); 832 CHECK(state.matched); 833 } 834 835 } 836 837 static void TestRanges() { 838 static const int MB = 1048576; 839 void* a = malloc(MB); 840 void* b = malloc(MB); 841 CheckRangeCallback(a, base::MallocRange::INUSE, MB); 842 CheckRangeCallback(b, base::MallocRange::INUSE, MB); 843 free(a); 844 CheckRangeCallback(a, base::MallocRange::FREE, MB); 845 CheckRangeCallback(b, base::MallocRange::INUSE, MB); 846 MallocExtension::instance()->ReleaseFreeMemory(); 847 CheckRangeCallback(a, base::MallocRange::UNMAPPED, MB); 848 CheckRangeCallback(b, base::MallocRange::INUSE, MB); 849 free(b); 850 CheckRangeCallback(a, base::MallocRange::UNMAPPED, MB); 851 CheckRangeCallback(b, base::MallocRange::FREE, MB); 852 } 853 854 #ifndef DEBUGALLOCATION 855 static size_t GetUnmappedBytes() { 856 size_t bytes; 857 CHECK(MallocExtension::instance()->GetNumericProperty( 858 "tcmalloc.pageheap_unmapped_bytes", &bytes)); 859 return bytes; 860 } 861 #endif 862 863 static void TestReleaseToSystem() { 864 // Debug allocation mode adds overhead to each allocation which 865 // messes up all the equality tests here. I just disable the 866 // teset in this mode. TODO(csilvers): get it to work for debugalloc? 867 #ifndef DEBUGALLOCATION 868 const double old_tcmalloc_release_rate = FLAGS_tcmalloc_release_rate; 869 FLAGS_tcmalloc_release_rate = 0; 870 871 static const int MB = 1048576; 872 void* a = malloc(MB); 873 void* b = malloc(MB); 874 MallocExtension::instance()->ReleaseFreeMemory(); 875 size_t starting_bytes = GetUnmappedBytes(); 876 877 // Calling ReleaseFreeMemory() a second time shouldn't do anything. 878 MallocExtension::instance()->ReleaseFreeMemory(); 879 EXPECT_EQ(starting_bytes, GetUnmappedBytes()); 880 881 // ReleaseToSystem shouldn't do anything either. 882 MallocExtension::instance()->ReleaseToSystem(MB); 883 EXPECT_EQ(starting_bytes, GetUnmappedBytes()); 884 885 free(a); 886 887 // The span to release should be 1MB. 888 MallocExtension::instance()->ReleaseToSystem(MB/2); 889 EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); 890 891 // Should do nothing since the previous call released too much. 892 MallocExtension::instance()->ReleaseToSystem(MB/4); 893 EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); 894 895 free(b); 896 897 // Use up the extra MB/4 bytes from 'a' and also release 'b'. 898 MallocExtension::instance()->ReleaseToSystem(MB/2); 899 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); 900 901 // Should do nothing since the previous call released too much. 902 MallocExtension::instance()->ReleaseToSystem(MB/2); 903 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); 904 905 // Nothing else to release. 906 MallocExtension::instance()->ReleaseFreeMemory(); 907 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); 908 909 a = malloc(MB); 910 free(a); 911 EXPECT_EQ(starting_bytes + MB, GetUnmappedBytes()); 912 913 // Releasing less than a page should still trigger a release. 914 MallocExtension::instance()->ReleaseToSystem(1); 915 EXPECT_EQ(starting_bytes + 2*MB, GetUnmappedBytes()); 916 917 FLAGS_tcmalloc_release_rate = old_tcmalloc_release_rate; 918 #endif // #ifndef DEBUGALLOCATION 919 } 920 921 // On MSVC10, in release mode, the optimizer convinces itself 922 // g_no_memory is never changed (I guess it doesn't realize OnNoMemory 923 // might be called). Work around this by setting the var volatile. 924 volatile bool g_no_memory = false; 925 std::new_handler g_old_handler = NULL; 926 static void OnNoMemory() { 927 g_no_memory = true; 928 std::set_new_handler(g_old_handler); 929 } 930 931 static void TestSetNewMode() { 932 int old_mode = tc_set_new_mode(1); 933 934 g_old_handler = std::set_new_handler(&OnNoMemory); 935 g_no_memory = false; 936 void* ret = malloc(kTooBig); 937 EXPECT_EQ(NULL, ret); 938 EXPECT_TRUE(g_no_memory); 939 940 g_old_handler = std::set_new_handler(&OnNoMemory); 941 g_no_memory = false; 942 ret = calloc(1, kTooBig); 943 EXPECT_EQ(NULL, ret); 944 EXPECT_TRUE(g_no_memory); 945 946 g_old_handler = std::set_new_handler(&OnNoMemory); 947 g_no_memory = false; 948 ret = realloc(NULL, kTooBig); 949 EXPECT_EQ(NULL, ret); 950 EXPECT_TRUE(g_no_memory); 951 952 if (kOSSupportsMemalign) { 953 // Not really important, but must be small enough such that 954 // kAlignment + kTooBig does not overflow. 955 const int kAlignment = 1 << 5; 956 957 g_old_handler = std::set_new_handler(&OnNoMemory); 958 g_no_memory = false; 959 ret = Memalign(kAlignment, kTooBig); 960 EXPECT_EQ(NULL, ret); 961 EXPECT_TRUE(g_no_memory); 962 963 g_old_handler = std::set_new_handler(&OnNoMemory); 964 g_no_memory = false; 965 EXPECT_EQ(ENOMEM, 966 PosixMemalign(&ret, kAlignment, kTooBig)); 967 EXPECT_EQ(NULL, ret); 968 EXPECT_TRUE(g_no_memory); 969 } 970 971 tc_set_new_mode(old_mode); 972 } 973 974 static int RunAllTests(int argc, char** argv) { 975 // Optional argv[1] is the seed 976 AllocatorState rnd(argc > 1 ? atoi(argv[1]) : 100); 977 978 SetTestResourceLimit(); 979 980 // TODO(odo): This test has been disabled because it is only by luck that it 981 // does not result in fragmentation. When tcmalloc makes an allocation which 982 // spans previously unused leaves of the pagemap it will allocate and fill in 983 // the leaves to cover the new allocation. The leaves happen to be 256MiB in 984 // the 64-bit build, and with the sbrk allocator these allocations just 985 // happen to fit in one leaf by luck. With other allocators (mmap, 986 // memfs_malloc when used with small pages) the allocations generally span 987 // two leaves and this results in a very bad fragmentation pattern with this 988 // code. The same failure can be forced with the sbrk allocator just by 989 // allocating something on the order of 128MiB prior to starting this test so 990 // that the test allocations straddle a 256MiB boundary. 991 992 // TODO(csilvers): port MemoryUsage() over so the test can use that 993 #if 0 994 # include <unistd.h> // for getpid() 995 // Allocate and deallocate blocks of increasing sizes to check if the alloc 996 // metadata fragments the memory. (Do not put other allocations/deallocations 997 // before this test, it may break). 998 { 999 size_t memory_usage = MemoryUsage(getpid()); 1000 fprintf(LOGSTREAM, "Testing fragmentation\n"); 1001 for ( int i = 200; i < 240; ++i ) { 1002 int size = i << 20; 1003 void *test1 = rnd.alloc(size); 1004 CHECK(test1); 1005 for ( int j = 0; j < size; j += (1 << 12) ) { 1006 static_cast<char*>(test1)[j] = 1; 1007 } 1008 free(test1); 1009 } 1010 // There may still be a bit of fragmentation at the beginning, until we 1011 // reach kPageMapBigAllocationThreshold bytes so we check for 1012 // 200 + 240 + margin. 1013 CHECK_LT(MemoryUsage(getpid()), memory_usage + (450 << 20) ); 1014 } 1015 #endif 1016 1017 // Check that empty allocation works 1018 fprintf(LOGSTREAM, "Testing empty allocation\n"); 1019 { 1020 void* p1 = rnd.alloc(0); 1021 CHECK(p1 != NULL); 1022 void* p2 = rnd.alloc(0); 1023 CHECK(p2 != NULL); 1024 CHECK(p1 != p2); 1025 free(p1); 1026 free(p2); 1027 } 1028 1029 // This code stresses some of the memory allocation via STL. 1030 // It may call operator delete(void*, nothrow_t). 1031 fprintf(LOGSTREAM, "Testing STL use\n"); 1032 { 1033 std::vector<int> v; 1034 v.push_back(1); 1035 v.push_back(2); 1036 v.push_back(3); 1037 v.push_back(0); 1038 std::stable_sort(v.begin(), v.end()); 1039 } 1040 1041 // Test each of the memory-allocation functions once, just as a sanity-check 1042 fprintf(LOGSTREAM, "Sanity-testing all the memory allocation functions\n"); 1043 { 1044 // We use new-hook and delete-hook to verify we actually called the 1045 // tcmalloc version of these routines, and not the libc version. 1046 SetNewHook(); // defined as part of MAKE_HOOK_CALLBACK, above 1047 SetDeleteHook(); // ditto 1048 1049 void* p1 = malloc(10); 1050 CHECK(p1 != NULL); // force use of this variable 1051 VerifyNewHookWasCalled(); 1052 // Also test the non-standard tc_malloc_size 1053 size_t actual_p1_size = tc_malloc_size(p1); 1054 CHECK_GE(actual_p1_size, 10); 1055 CHECK_LT(actual_p1_size, 100000); // a reasonable upper-bound, I think 1056 free(p1); 1057 VerifyDeleteHookWasCalled(); 1058 1059 1060 p1 = calloc(10, 2); 1061 CHECK(p1 != NULL); 1062 VerifyNewHookWasCalled(); 1063 // We make sure we realloc to a big size, since some systems (OS 1064 // X) will notice if the realloced size continues to fit into the 1065 // malloc-block and make this a noop if so. 1066 p1 = realloc(p1, 30000); 1067 CHECK(p1 != NULL); 1068 VerifyNewHookWasCalled(); 1069 VerifyDeleteHookWasCalled(); 1070 cfree(p1); // synonym for free 1071 VerifyDeleteHookWasCalled(); 1072 1073 if (kOSSupportsMemalign) { 1074 CHECK_EQ(PosixMemalign(&p1, sizeof(p1), 40), 0); 1075 CHECK(p1 != NULL); 1076 VerifyNewHookWasCalled(); 1077 free(p1); 1078 VerifyDeleteHookWasCalled(); 1079 1080 p1 = Memalign(sizeof(p1) * 2, 50); 1081 CHECK(p1 != NULL); 1082 VerifyNewHookWasCalled(); 1083 free(p1); 1084 VerifyDeleteHookWasCalled(); 1085 } 1086 1087 // Windows has _aligned_malloc. Let's test that that's captured too. 1088 #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(PERFTOOLS_NO_ALIGNED_MALLOC) 1089 p1 = _aligned_malloc(sizeof(p1) * 2, 64); 1090 CHECK(p1 != NULL); 1091 VerifyNewHookWasCalled(); 1092 _aligned_free(p1); 1093 VerifyDeleteHookWasCalled(); 1094 #endif 1095 1096 p1 = valloc(60); 1097 CHECK(p1 != NULL); 1098 VerifyNewHookWasCalled(); 1099 free(p1); 1100 VerifyDeleteHookWasCalled(); 1101 1102 p1 = pvalloc(70); 1103 CHECK(p1 != NULL); 1104 VerifyNewHookWasCalled(); 1105 free(p1); 1106 VerifyDeleteHookWasCalled(); 1107 1108 char* p2 = new char; 1109 CHECK(p2 != NULL); 1110 VerifyNewHookWasCalled(); 1111 delete p2; 1112 VerifyDeleteHookWasCalled(); 1113 1114 p2 = new char[100]; 1115 CHECK(p2 != NULL); 1116 VerifyNewHookWasCalled(); 1117 delete[] p2; 1118 VerifyDeleteHookWasCalled(); 1119 1120 p2 = new(std::nothrow) char; 1121 CHECK(p2 != NULL); 1122 VerifyNewHookWasCalled(); 1123 delete p2; 1124 VerifyDeleteHookWasCalled(); 1125 1126 p2 = new(std::nothrow) char[100]; 1127 CHECK(p2 != NULL); 1128 VerifyNewHookWasCalled(); 1129 delete[] p2; 1130 VerifyDeleteHookWasCalled(); 1131 1132 // Another way of calling operator new 1133 p2 = static_cast<char*>(::operator new(100)); 1134 CHECK(p2 != NULL); 1135 VerifyNewHookWasCalled(); 1136 ::operator delete(p2); 1137 VerifyDeleteHookWasCalled(); 1138 1139 // Try to call nothrow's delete too. Compilers use this. 1140 p2 = static_cast<char*>(::operator new(100, std::nothrow)); 1141 CHECK(p2 != NULL); 1142 VerifyNewHookWasCalled(); 1143 ::operator delete(p2, std::nothrow); 1144 VerifyDeleteHookWasCalled(); 1145 1146 // Try strdup(), which the system allocates but we must free. If 1147 // all goes well, libc will use our malloc! 1148 p2 = strdup("test"); 1149 CHECK(p2 != NULL); 1150 VerifyNewHookWasCalled(); 1151 free(p2); 1152 VerifyDeleteHookWasCalled(); 1153 1154 1155 // Test mmap too: both anonymous mmap and mmap of a file 1156 // Note that for right now we only override mmap on linux 1157 // systems, so those are the only ones for which we check. 1158 SetMmapHook(); 1159 SetMremapHook(); 1160 SetMunmapHook(); 1161 #if defined(HAVE_MMAP) && defined(__linux) && \ 1162 (defined(__i386__) || defined(__x86_64__)) 1163 int size = 8192*2; 1164 p1 = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, 1165 -1, 0); 1166 CHECK(p1 != NULL); 1167 VerifyMmapHookWasCalled(); 1168 p1 = mremap(p1, size, size/2, 0); 1169 CHECK(p1 != NULL); 1170 VerifyMremapHookWasCalled(); 1171 size /= 2; 1172 munmap(p1, size); 1173 VerifyMunmapHookWasCalled(); 1174 1175 int fd = open("/dev/zero", O_RDONLY); 1176 CHECK_GE(fd, 0); // make sure the open succeeded 1177 p1 = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0); 1178 CHECK(p1 != NULL); 1179 VerifyMmapHookWasCalled(); 1180 munmap(p1, 8192); 1181 VerifyMunmapHookWasCalled(); 1182 close(fd); 1183 #else // this is just to quiet the compiler: make sure all fns are called 1184 IncrementCallsToMmapHook(); 1185 IncrementCallsToMunmapHook(); 1186 IncrementCallsToMremapHook(); 1187 VerifyMmapHookWasCalled(); 1188 VerifyMremapHookWasCalled(); 1189 VerifyMunmapHookWasCalled(); 1190 #endif 1191 1192 // Test sbrk 1193 SetSbrkHook(); 1194 #if defined(HAVE_SBRK) && defined(__linux) && \ 1195 (defined(__i386__) || defined(__x86_64__)) 1196 p1 = sbrk(8192); 1197 CHECK(p1 != NULL); 1198 VerifySbrkHookWasCalled(); 1199 p1 = sbrk(-8192); 1200 CHECK(p1 != NULL); 1201 VerifySbrkHookWasCalled(); 1202 // However, sbrk hook should *not* be called with sbrk(0) 1203 p1 = sbrk(0); 1204 CHECK(p1 != NULL); 1205 CHECK_EQ(g_SbrkHook_calls, 0); 1206 #else // this is just to quiet the compiler: make sure all fns are called 1207 IncrementCallsToSbrkHook(); 1208 VerifySbrkHookWasCalled(); 1209 #endif 1210 1211 // Reset the hooks to what they used to be. These are all 1212 // defined as part of MAKE_HOOK_CALLBACK, above. 1213 ResetNewHook(); 1214 ResetDeleteHook(); 1215 ResetMmapHook(); 1216 ResetMremapHook(); 1217 ResetMunmapHook(); 1218 ResetSbrkHook(); 1219 } 1220 1221 // Check that "lots" of memory can be allocated 1222 fprintf(LOGSTREAM, "Testing large allocation\n"); 1223 { 1224 const int mb_to_allocate = 100; 1225 void* p = rnd.alloc(mb_to_allocate << 20); 1226 CHECK(p != NULL); // could not allocate 1227 free(p); 1228 } 1229 1230 TestMallocAlignment(); 1231 1232 // Check calloc() with various arguments 1233 fprintf(LOGSTREAM, "Testing calloc\n"); 1234 TestCalloc(0, 0, true); 1235 TestCalloc(0, 1, true); 1236 TestCalloc(1, 1, true); 1237 TestCalloc(1<<10, 0, true); 1238 TestCalloc(1<<20, 0, true); 1239 TestCalloc(0, 1<<10, true); 1240 TestCalloc(0, 1<<20, true); 1241 TestCalloc(1<<20, 2, true); 1242 TestCalloc(2, 1<<20, true); 1243 TestCalloc(1000, 1000, true); 1244 1245 TestCalloc(kMaxSize, 2, false); 1246 TestCalloc(2, kMaxSize, false); 1247 TestCalloc(kMaxSize, kMaxSize, false); 1248 1249 TestCalloc(kMaxSignedSize, 3, false); 1250 TestCalloc(3, kMaxSignedSize, false); 1251 TestCalloc(kMaxSignedSize, kMaxSignedSize, false); 1252 1253 // Test that realloc doesn't always reallocate and copy memory. 1254 fprintf(LOGSTREAM, "Testing realloc\n"); 1255 TestRealloc(); 1256 1257 fprintf(LOGSTREAM, "Testing operator new(nothrow).\n"); 1258 TestNothrowNew(&::operator new); 1259 fprintf(LOGSTREAM, "Testing operator new[](nothrow).\n"); 1260 TestNothrowNew(&::operator new[]); 1261 fprintf(LOGSTREAM, "Testing operator new.\n"); 1262 TestNew(&::operator new); 1263 fprintf(LOGSTREAM, "Testing operator new[].\n"); 1264 TestNew(&::operator new[]); 1265 1266 // Create threads 1267 fprintf(LOGSTREAM, "Testing threaded allocation/deallocation (%d threads)\n", 1268 FLAGS_numthreads); 1269 threads = new TesterThread*[FLAGS_numthreads]; 1270 for (int i = 0; i < FLAGS_numthreads; ++i) { 1271 threads[i] = new TesterThread(i); 1272 } 1273 1274 // This runs all the tests at the same time, with a 1M stack size each 1275 RunManyThreadsWithId(RunThread, FLAGS_numthreads, 1<<20); 1276 1277 for (int i = 0; i < FLAGS_numthreads; ++i) delete threads[i]; // Cleanup 1278 1279 // Do the memory intensive tests after threads are done, since exhausting 1280 // the available address space can make pthread_create to fail. 1281 1282 // Check that huge allocations fail with NULL instead of crashing 1283 fprintf(LOGSTREAM, "Testing huge allocations\n"); 1284 TestHugeAllocations(&rnd); 1285 1286 // Check that large allocations fail with NULL instead of crashing 1287 #ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs 1288 fprintf(LOGSTREAM, "Testing out of memory\n"); 1289 for (int s = 0; ; s += (10<<20)) { 1290 void* large_object = rnd.alloc(s); 1291 if (large_object == NULL) break; 1292 free(large_object); 1293 } 1294 #endif 1295 1296 TestHugeThreadCache(); 1297 TestRanges(); 1298 TestReleaseToSystem(); 1299 TestSetNewMode(); 1300 1301 return 0; 1302 } 1303 1304 } 1305 1306 using testing::RunAllTests; 1307 1308 int main(int argc, char** argv) { 1309 #ifdef DEBUGALLOCATION // debug allocation takes forever for huge allocs 1310 FLAGS_max_free_queue_size = 0; // return freed blocks to tcmalloc immediately 1311 #endif 1312 1313 RunAllTests(argc, argv); 1314 1315 // Test tc_version() 1316 fprintf(LOGSTREAM, "Testing tc_version()\n"); 1317 int major; 1318 int minor; 1319 const char* patch; 1320 char mmp[64]; 1321 const char* human_version = tc_version(&major, &minor, &patch); 1322 snprintf(mmp, sizeof(mmp), "%d.%d%s", major, minor, patch); 1323 CHECK(!strcmp(PACKAGE_STRING, human_version)); 1324 CHECK(!strcmp(PACKAGE_VERSION, mmp)); 1325 1326 fprintf(LOGSTREAM, "PASS\n"); 1327 } 1328