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
106static bool kOSSupportsMemalign = false;
107static inline void* Memalign(size_t align, size_t size) {
108  //LOG(FATAL) << "memalign not supported on windows";
109  exit(1);
110  return NULL;
111}
112static 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__)
121static bool kOSSupportsMemalign = false;
122static 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}
127static 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
134static bool kOSSupportsMemalign = true;
135static inline void* Memalign(size_t align, size_t size) {
136  return memalign(align, size);
137}
138static 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
152using std::vector;
153using std::string;
154
155DECLARE_double(tcmalloc_release_rate);
156DECLARE_int32(max_free_queue_size);     // in debugallocation.cc
157DECLARE_int64(tcmalloc_sample_parameter);
158
159namespace testing {
160
161static const int FLAGS_numtests = 50000;
162static const int FLAGS_log_every_n_tests = 50000; // log exactly once
163
164// Testing parameters
165static const int FLAGS_lgmaxsize = 16;   // lg() of the max size object to alloc
166static const int FLAGS_numthreads = 10;  // Number of threads
167static const int FLAGS_threadmb = 4;     // Max memory size allocated by thread
168static const int FLAGS_lg_max_memalign = 18; // lg of max alignment for memalign
169
170static const double FLAGS_memalign_min_fraction = 0;    // min expected%
171static const double FLAGS_memalign_max_fraction = 0.4;  // max expected%
172static const double FLAGS_memalign_max_alignment_ratio = 6;  // alignment/size
173
174// Weights of different operations
175static const int FLAGS_allocweight = 50;    // Weight for picking allocation
176static const int FLAGS_freeweight = 50;     // Weight for picking free
177static const int FLAGS_updateweight = 10;   // Weight for picking update
178static const int FLAGS_passweight = 1;      // Weight for passing object
179
180static const int kSizeBits = 8 * sizeof(size_t);
181static const size_t kMaxSize = ~static_cast<size_t>(0);
182static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1);
183
184static 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.
190static const size_t kTooBig = kMaxSize - 100000;
191
192static int news_handled = 0;
193
194// Global array of threads
195class TesterThread;
196static TesterThread** threads;
197
198// To help with generating random numbers
199class 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
253void 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
262int 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
285class 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
329class 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
545static void RunThread(int thread_id) {
546  threads[thread_id]->Run();
547}
548
549static void TryHugeAllocation(size_t s, AllocatorState* rnd) {
550  void* p = rnd->alloc(s);
551  CHECK(p == NULL);   // huge allocation s should fail!
552}
553
554static 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
579static 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.
596static 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
627static void TestNewHandler() throw (std::bad_alloc) {
628  ++news_handled;
629  throw std::bad_alloc();
630}
631
632static 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
659static 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
676static 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
702static 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
745MAKE_HOOK_CALLBACK(NewHook);
746MAKE_HOOK_CALLBACK(DeleteHook);
747MAKE_HOOK_CALLBACK(MmapHook);
748MAKE_HOOK_CALLBACK(MremapHook);
749MAKE_HOOK_CALLBACK(MunmapHook);
750MAKE_HOOK_CALLBACK(SbrkHook);
751
752static 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
772static 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
780static 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
794namespace {
795
796struct RangeCallbackState {
797  uintptr_t ptr;
798  base::MallocRange::Type expected_type;
799  size_t min_size;
800  bool matched;
801};
802
803static 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.
824static 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
837static 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
855static 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
863static 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.
924volatile bool g_no_memory = false;
925std::new_handler g_old_handler = NULL;
926static void OnNoMemory() {
927  g_no_memory = true;
928  std::set_new_handler(g_old_handler);
929}
930
931static 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
974static 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
1306using testing::RunAllTests;
1307
1308int 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