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

Side by Side Diff: third_party/tcmalloc/vendor/src/debugallocation.cc

Issue 9701040: Revert 126715 - Update the tcmalloc vendor branch to r144 (gperftools 2.0). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: 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) 2000, Google Inc. 1 // Copyright (c) 2000, 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 13 matching lines...) Expand all
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 29
30 // --- 30 // ---
31 // Author: Urs Holzle <opensource@google.com> 31 // Author: Urs Holzle <opensource@google.com>
32 32
33 #include "config.h" 33 #include "config.h"
34 #include <errno.h>
35 #ifdef HAVE_FCNTL_H
36 #include <fcntl.h>
37 #endif
38 #ifdef HAVE_INTTYPES_H
39 #include <inttypes.h>
40 #endif
41 // We only need malloc.h for struct mallinfo. 34 // We only need malloc.h for struct mallinfo.
42 #ifdef HAVE_STRUCT_MALLINFO 35 #ifdef HAVE_STRUCT_MALLINFO
43 // Malloc can be in several places on older versions of OS X. 36 // Malloc can be in several places on older versions of OS X.
44 # if defined(HAVE_MALLOC_H) 37 # if defined(HAVE_MALLOC_H)
45 # include <malloc.h> 38 # include <malloc.h>
46 # elif defined(HAVE_MALLOC_MALLOC_H) 39 # elif defined(HAVE_MALLOC_MALLOC_H)
47 # include <malloc/malloc.h> 40 # include <malloc/malloc.h>
48 # elif defined(HAVE_SYS_MALLOC_H) 41 # elif defined(HAVE_SYS_MALLOC_H)
49 # include <sys/malloc.h> 42 # include <sys/malloc.h>
50 # endif 43 # endif
51 #endif 44 #endif
52 #ifdef HAVE_PTHREAD
53 #include <pthread.h> 45 #include <pthread.h>
46 #include <stdio.h>
47 #ifdef HAVE_INTTYPES_H
48 #include <inttypes.h>
54 #endif 49 #endif
55 #include <stdarg.h> 50 #include <stdarg.h>
56 #include <stdio.h>
57 #include <string.h>
58 #ifdef HAVE_MMAP 51 #ifdef HAVE_MMAP
59 #include <sys/mman.h> 52 #include <sys/mman.h>
60 #endif 53 #endif
54 #include <sys/types.h>
61 #include <sys/stat.h> 55 #include <sys/stat.h>
62 #include <sys/types.h> 56 #ifdef HAVE_FCNTL_H
57 #include <fcntl.h>
58 #endif
63 #ifdef HAVE_UNISTD_H 59 #ifdef HAVE_UNISTD_H
64 #include <unistd.h> 60 #include <unistd.h>
65 #endif 61 #endif
62 #include <errno.h>
63 #include <string.h>
66 64
67 #include <gperftools/malloc_extension.h> 65 #include <google/malloc_extension.h>
68 #include <gperftools/malloc_hook.h> 66 #include <google/malloc_hook.h>
69 #include <gperftools/stacktrace.h> 67 #include <google/stacktrace.h>
70 #include "addressmap-inl.h"
71 #include "base/commandlineflags.h" 68 #include "base/commandlineflags.h"
72 #include "base/googleinit.h" 69 #include "base/googleinit.h"
73 #include "base/logging.h" 70 #include "base/logging.h"
74 #include "base/spinlock.h" 71 #include "base/spinlock.h"
72 #include "addressmap-inl.h"
75 #include "malloc_hook-inl.h" 73 #include "malloc_hook-inl.h"
76 #include "symbolize.h" 74 #include "symbolize.h"
77 75
78 #define TCMALLOC_USING_DEBUGALLOCATION 76 #define TCMALLOC_USING_DEBUGALLOCATION
79 #include "tcmalloc.cc" 77 #include "tcmalloc.cc"
80 78
81 // __THROW is defined in glibc systems. It means, counter-intuitively, 79 // __THROW is defined in glibc systems. It means, counter-intuitively,
82 // "This function will never throw an exception." It's an optional 80 // "This function will never throw an exception." It's an optional
83 // optimization tool, but we may need to use it to match glibc prototypes. 81 // optimization tool, but we may need to use it to match glibc prototypes.
84 #ifndef __THROW // I guess we're not on a glibc system 82 #ifndef __THROW // I guess we're not on a glibc system
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 EnvToInt("TCMALLOC_MAX_FREE_QUEUE_SIZE", 10*1024*1024), 117 EnvToInt("TCMALLOC_MAX_FREE_QUEUE_SIZE", 10*1024*1024),
120 "If greater than 0, keep freed blocks in a queue instead of " 118 "If greater than 0, keep freed blocks in a queue instead of "
121 "releasing them to the allocator immediately. Release them when " 119 "releasing them to the allocator immediately. Release them when "
122 "the total size of all blocks in the queue would otherwise exceed " 120 "the total size of all blocks in the queue would otherwise exceed "
123 "this limit."); 121 "this limit.");
124 122
125 DEFINE_bool(symbolize_stacktrace, 123 DEFINE_bool(symbolize_stacktrace,
126 EnvToBool("TCMALLOC_SYMBOLIZE_STACKTRACE", true), 124 EnvToBool("TCMALLOC_SYMBOLIZE_STACKTRACE", true),
127 "Symbolize the stack trace when provided (on some error exits)"); 125 "Symbolize the stack trace when provided (on some error exits)");
128 126
129 // If we are LD_PRELOAD-ed against a non-pthreads app, then
130 // pthread_once won't be defined. We declare it here, for that
131 // case (with weak linkage) which will cause the non-definition to
132 // resolve to NULL. We can then check for NULL or not in Instance.
133 extern "C" int pthread_once(pthread_once_t *, void (*)(void))
134 ATTRIBUTE_WEAK;
135
136 // ========================================================================= // 127 // ========================================================================= //
137 128
138 // A safe version of printf() that does not do any allocation and 129 // A safe version of printf() that does not do any allocation and
139 // uses very little stack space. 130 // uses very little stack space.
140 static void TracePrintf(int fd, const char *fmt, ...) 131 static void TracePrintf(int fd, const char *fmt, ...)
141 __attribute__ ((__format__ (__printf__, 2, 3))); 132 __attribute__ ((__format__ (__printf__, 2, 3)));
142 133
143 // The do_* functions are defined in tcmalloc/tcmalloc.cc, 134 // The do_* functions are defined in tcmalloc/tcmalloc.cc,
144 // which is included before this file 135 // which is included before this file
145 // when TCMALLOC_FOR_DEBUGALLOCATION is defined 136 // when TCMALLOC_FOR_DEBUGALLOCATION is defined
(...skipping 25 matching lines...) Expand all
171 bool Full() { 162 bool Full() {
172 return (q_front_ + 1) % kFreeQueueSize == q_back_; 163 return (q_front_ + 1) % kFreeQueueSize == q_back_;
173 } 164 }
174 165
175 void Push(const QueueEntry& block) { 166 void Push(const QueueEntry& block) {
176 q_[q_front_] = block; 167 q_[q_front_] = block;
177 q_front_ = (q_front_ + 1) % kFreeQueueSize; 168 q_front_ = (q_front_ + 1) % kFreeQueueSize;
178 } 169 }
179 170
180 QueueEntry Pop() { 171 QueueEntry Pop() {
181 RAW_CHECK(q_back_ != q_front_, "Queue is empty");
182 const QueueEntry& ret = q_[q_back_]; 172 const QueueEntry& ret = q_[q_back_];
183 q_back_ = (q_back_ + 1) % kFreeQueueSize; 173 q_back_ = (q_back_ + 1) % kFreeQueueSize;
184 return ret; 174 return ret;
185 } 175 }
186 176
187 size_t size() const { 177 size_t size() const {
188 return (q_front_ - q_back_ + kFreeQueueSize) % kFreeQueueSize; 178 return (q_front_ - q_back_ + kFreeQueueSize) % kFreeQueueSize;
189 } 179 }
190 180
191 private: 181 private:
192 // Maximum number of blocks kept in the free queue before being freed. 182 // Maximum number of blocks kept in the free queue before being freed.
193 static const int kFreeQueueSize = 1024; 183 static const int kFreeQueueSize = 1024;
194 184
195 QueueEntry q_[kFreeQueueSize]; 185 QueueEntry q_[kFreeQueueSize];
196 int q_front_; 186 int q_front_;
197 int q_back_; 187 int q_back_;
198 }; 188 };
199 189
200 struct MallocBlockQueueEntry { 190 struct MallocBlockQueueEntry {
201 MallocBlockQueueEntry() : block(NULL), size(0), 191 MallocBlockQueueEntry() : block(NULL), size(0),
202 num_deleter_pcs(0), deleter_threadid(0) {} 192 num_deleter_pcs(0), deleter_threadid(0) {}
203 MallocBlockQueueEntry(MallocBlock* b, size_t s) : block(b), size(s) { 193 MallocBlockQueueEntry(MallocBlock* b, size_t s) : block(b), size(s) {
204 if (FLAGS_max_free_queue_size != 0 && b != NULL) { 194 if (FLAGS_max_free_queue_size != 0) {
205 // Adjust the number of frames to skip (4) if you change the 195 // Adjust the number of frames to skip (4) if you change the
206 // location of this call. 196 // location of this call.
207 num_deleter_pcs = 197 num_deleter_pcs =
208 GetStackTrace(deleter_pcs, 198 GetStackTrace(deleter_pcs,
209 sizeof(deleter_pcs) / sizeof(deleter_pcs[0]), 199 sizeof(deleter_pcs) / sizeof(deleter_pcs[0]),
210 4); 200 4);
211 deleter_threadid = pthread_self(); 201 deleter_threadid = pthread_self();
212 } else { 202 } else {
213 num_deleter_pcs = 0; 203 num_deleter_pcs = 0;
214 // Zero is an illegal pthread id by my reading of the pthread 204 // Zero is an illegal pthread id by my reading of the pthread
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 // start the program (see man malloc). 259 // start the program (see man malloc).
270 260
271 // We use either BASE_MALLOC or mmap to make the actual allocation. In 261 // We use either BASE_MALLOC or mmap to make the actual allocation. In
272 // order to remember which one of the two was used for any block, we store an 262 // order to remember which one of the two was used for any block, we store an
273 // appropriate magic word next to the block. 263 // appropriate magic word next to the block.
274 static const int kMagicMalloc = 0xDEADBEEF; 264 static const int kMagicMalloc = 0xDEADBEEF;
275 static const int kMagicMMap = 0xABCDEFAB; 265 static const int kMagicMMap = 0xABCDEFAB;
276 266
277 // This array will be filled with 0xCD, for use with memcmp. 267 // This array will be filled with 0xCD, for use with memcmp.
278 static unsigned char kMagicDeletedBuffer[1024]; 268 static unsigned char kMagicDeletedBuffer[1024];
279 static pthread_once_t deleted_buffer_initialized_; 269 static bool deleted_buffer_initialized_;
280 static bool deleted_buffer_initialized_no_pthreads_;
281 270
282 private: // data layout 271 private: // data layout
283 272
284 // The four fields size1_,offset_,magic1_,alloc_type_ 273 // The four fields size1_,offset_,magic1_,alloc_type_
285 // should together occupy a multiple of 16 bytes. (At the 274 // should together occupy a multiple of 16 bytes. (At the
286 // moment, sizeof(size_t) == 4 or 8 depending on piii vs 275 // moment, sizeof(size_t) == 4 or 8 depending on piii vs
287 // k8, and 4 of those sum to 16 or 32 bytes). 276 // k8, and 4 of those sum to 16 or 32 bytes).
288 // This, combined with BASE_MALLOC's alignment guarantees, 277 // This, combined with BASE_MALLOC's alignment guarantees,
289 // ensures that SSE types can be stored into the returned 278 // ensures that SSE types can be stored into the returned
290 // block, at &size2_. 279 // block, at &size2_.
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 } 554 }
566 } 555 }
567 556
568 static size_t FreeQueueSize() { 557 static size_t FreeQueueSize() {
569 SpinLockHolder l(&free_queue_lock_); 558 SpinLockHolder l(&free_queue_lock_);
570 return free_queue_size_; 559 return free_queue_size_;
571 } 560 }
572 561
573 static void ProcessFreeQueue(MallocBlock* b, size_t size, 562 static void ProcessFreeQueue(MallocBlock* b, size_t size,
574 int max_free_queue_size) { 563 int max_free_queue_size) {
575 // MallocBlockQueueEntry are about 144 in size, so we can only 564 SpinLockHolder l(&free_queue_lock_);
576 // use a small array of them on the stack.
577 MallocBlockQueueEntry entries[4];
578 int num_entries = 0;
579 MallocBlockQueueEntry new_entry(b, size);
580 free_queue_lock_.Lock();
581 if (free_queue_ == NULL) 565 if (free_queue_ == NULL)
582 free_queue_ = new FreeQueue<MallocBlockQueueEntry>; 566 free_queue_ = new FreeQueue<MallocBlockQueueEntry>;
583 RAW_CHECK(!free_queue_->Full(), "Free queue mustn't be full!"); 567 RAW_CHECK(!free_queue_->Full(), "Free queue mustn't be full!");
584 568
585 if (b != NULL) { 569 if (b != NULL) {
586 free_queue_size_ += size + sizeof(MallocBlockQueueEntry); 570 free_queue_size_ += size + sizeof(MallocBlockQueueEntry);
571 MallocBlockQueueEntry new_entry(b, size);
587 free_queue_->Push(new_entry); 572 free_queue_->Push(new_entry);
588 } 573 }
589 574
590 // Free blocks until the total size of unfreed blocks no longer exceeds 575 // Free blocks until the total size of unfreed blocks no longer exceeds
591 // max_free_queue_size, and the free queue has at least one free 576 // max_free_queue_size, and the free queue has at least one free
592 // space in it. 577 // space in it.
593 while (free_queue_size_ > max_free_queue_size || free_queue_->Full()) { 578 while (free_queue_size_ > max_free_queue_size || free_queue_->Full()) {
594 RAW_CHECK(num_entries < arraysize(entries), "entries array overflow"); 579 MallocBlockQueueEntry cur = free_queue_->Pop();
595 entries[num_entries] = free_queue_->Pop(); 580 CheckForDanglingWrites(cur);
596 free_queue_size_ -= 581 free_queue_size_ -= cur.size + sizeof(MallocBlockQueueEntry);
597 entries[num_entries].size + sizeof(MallocBlockQueueEntry); 582 BASE_FREE(cur.block);
598 num_entries++;
599 if (num_entries == arraysize(entries)) {
600 // The queue will not be full at this point, so it is ok to
601 // release the lock. The queue may still contain more than
602 // max_free_queue_size, but this is not a strict invariant.
603 free_queue_lock_.Unlock();
604 for (int i = 0; i < num_entries; i++) {
605 CheckForDanglingWrites(entries[i]);
606 BASE_FREE(entries[i].block);
607 }
608 num_entries = 0;
609 free_queue_lock_.Lock();
610 }
611 } 583 }
612 RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!"); 584 RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!");
613 free_queue_lock_.Unlock();
614 for (int i = 0; i < num_entries; i++) {
615 CheckForDanglingWrites(entries[i]);
616 BASE_FREE(entries[i].block);
617 }
618 }
619
620 static void InitDeletedBuffer() {
621 memset(kMagicDeletedBuffer, kMagicDeletedByte, sizeof(kMagicDeletedBuffer));
622 deleted_buffer_initialized_no_pthreads_ = true;
623 } 585 }
624 586
625 static void CheckForDanglingWrites(const MallocBlockQueueEntry& queue_entry) { 587 static void CheckForDanglingWrites(const MallocBlockQueueEntry& queue_entry) {
626 // Initialize the buffer if necessary. 588 // Initialize the buffer if necessary.
627 if (pthread_once) 589 if (!deleted_buffer_initialized_) {
628 pthread_once(&deleted_buffer_initialized_, &InitDeletedBuffer); 590 // This is threadsafe. We hold free_queue_lock_.
629 if (!deleted_buffer_initialized_no_pthreads_) { 591 memset(kMagicDeletedBuffer, 0xcd, sizeof(kMagicDeletedBuffer));
630 // This will be the case on systems that don't link in pthreads, 592 deleted_buffer_initialized_ = true;
631 // including on FreeBSD where pthread_once has a non-zero address
632 // (but doesn't do anything) even when pthreads isn't linked in.
633 InitDeletedBuffer();
634 } 593 }
635 594
636 const unsigned char* p = 595 const unsigned char* p =
637 reinterpret_cast<unsigned char*>(queue_entry.block); 596 reinterpret_cast<unsigned char*>(queue_entry.block);
638 597
639 static const size_t size_of_buffer = sizeof(kMagicDeletedBuffer); 598 static const size_t size_of_buffer = sizeof(kMagicDeletedBuffer);
640 const size_t size = queue_entry.size; 599 const size_t size = queue_entry.size;
641 const size_t buffers = size / size_of_buffer; 600 const size_t buffers = size / size_of_buffer;
642 const size_t remainder = size % size_of_buffer; 601 const size_t remainder = size % size_of_buffer;
643 size_t buffer_idx; 602 size_t buffer_idx;
(...skipping 15 matching lines...) Expand all
659 RAW_LOG(ERROR, 618 RAW_LOG(ERROR,
660 "Found a corrupted memory buffer in MallocBlock (may be offset " 619 "Found a corrupted memory buffer in MallocBlock (may be offset "
661 "from user ptr): buffer index: %zd, buffer ptr: %p, size of " 620 "from user ptr): buffer index: %zd, buffer ptr: %p, size of "
662 "buffer: %zd", buffer_idx, buffer, size_of_buffer); 621 "buffer: %zd", buffer_idx, buffer, size_of_buffer);
663 622
664 // The magic deleted buffer should only be 1024 bytes, but in case 623 // The magic deleted buffer should only be 1024 bytes, but in case
665 // this changes, let's put an upper limit on the number of debug 624 // this changes, let's put an upper limit on the number of debug
666 // lines we'll output: 625 // lines we'll output:
667 if (size_of_buffer <= 1024) { 626 if (size_of_buffer <= 1024) {
668 for (int i = 0; i < size_of_buffer; ++i) { 627 for (int i = 0; i < size_of_buffer; ++i) {
669 if (buffer[i] != kMagicDeletedByte) { 628 if (buffer[i] != 0xcd) {
670 RAW_LOG(ERROR, "Buffer byte %d is 0x%02x (should be 0x%02x).", 629 RAW_LOG(ERROR, "Buffer byte %d is 0x%02x (should be 0xcd).",
671 i, buffer[i], kMagicDeletedByte); 630 i, buffer[i]);
672 } 631 }
673 } 632 }
674 } else { 633 } else {
675 RAW_LOG(ERROR, "Buffer too large to print corruption."); 634 RAW_LOG(ERROR, "Buffer too large to print corruption.");
676 } 635 }
677 636
678 const MallocBlock* b = queue_entry.block; 637 const MallocBlock* b = queue_entry.block;
679 const size_t size = queue_entry.size; 638 const size_t size = queue_entry.size;
680 if (queue_entry.num_deleter_pcs > 0) { 639 if (queue_entry.num_deleter_pcs > 0) {
681 TracePrintf(STDERR_FILENO, "Deleted by thread %p\n", 640 TracePrintf(STDERR_FILENO, "Deleted by thread %p\n",
(...skipping 23 matching lines...) Expand all
705 RAW_LOG(ERROR, 664 RAW_LOG(ERROR,
706 "Skipping the printing of the deleter's stack! Its stack was " 665 "Skipping the printing of the deleter's stack! Its stack was "
707 "not found; either the corruption occurred too early in " 666 "not found; either the corruption occurred too early in "
708 "execution to obtain a stack trace or --max_free_queue_size was " 667 "execution to obtain a stack trace or --max_free_queue_size was "
709 "set to 0."); 668 "set to 0.");
710 } 669 }
711 670
712 RAW_LOG(FATAL, 671 RAW_LOG(FATAL,
713 "Memory was written to after being freed. MallocBlock: %p, user " 672 "Memory was written to after being freed. MallocBlock: %p, user "
714 "ptr: %p, size: %zd. If you can't find the source of the error, " 673 "ptr: %p, size: %zd. If you can't find the source of the error, "
715 "try using ASan (http://code.google.com/p/address-sanitizer/), " 674 "try using valgrind or purify, or study the output of the "
716 "Valgrind, or Purify, or study the " 675 "deleter's stack printed above.", b, b->data_addr(), size);
717 "output of the deleter's stack printed above.",
718 b, b->data_addr(), size);
719 } 676 }
720 677
721 static MallocBlock* FromRawPointer(void* p) { 678 static MallocBlock* FromRawPointer(void* p) {
722 const size_t data_offset = MallocBlock::data_offset(); 679 const size_t data_offset = MallocBlock::data_offset();
723 // Find the header just before client's memory. 680 // Find the header just before client's memory.
724 MallocBlock *mb = reinterpret_cast<MallocBlock *>( 681 MallocBlock *mb = reinterpret_cast<MallocBlock *>(
725 reinterpret_cast<char *>(p) - data_offset); 682 reinterpret_cast<char *>(p) - data_offset);
726 // If mb->alloc_type_ is kMagicDeletedSizeT, we're not an ok pointer. 683 // If mb->alloc_type_ is kMagicDeletedSizeT, we're not an ok pointer.
727 if (mb->alloc_type_ == kMagicDeletedSizeT) { 684 if (mb->alloc_type_ == kMagicDeletedSizeT) {
728 RAW_LOG(FATAL, "memory allocation bug: object at %p has been already" 685 RAW_LOG(FATAL, "memory allocation bug: object at %p has been already"
729 " deallocated; or else a word before the object has been" 686 " deallocated; or else a word before the object has been"
730 " corrupted (memory stomping bug)", p); 687 " corrupted (memory stomping bug)", p);
731 } 688 }
732 // If mb->offset_ is zero (common case), mb is the real header. If 689 // If mb->offset_ is zero (common case), mb is the real header. If
733 // mb->offset_ is non-zero, this block was allocated by memalign, and 690 // mb->offset_ is non-zero, this block was allocated by memalign, and
734 // mb->offset_ is the distance backwards to the real header from mb, 691 // mb->offset_ is the distance backwards to the real header from mb,
735 // which is a fake header. The following subtraction works for both zero 692 // which is a fake header. The following subtraction works for both zero
736 // and non-zero values. 693 // and non-zero values.
737 return reinterpret_cast<MallocBlock *>( 694 return reinterpret_cast<MallocBlock *>(
738 reinterpret_cast<char *>(mb) - mb->offset_); 695 reinterpret_cast<char *>(mb) - mb->offset_);
739 } 696 }
740 static const MallocBlock* FromRawPointer(const void* p) { 697 static const MallocBlock* FromRawPointer(const void* p) {
741 // const-safe version: we just cast about 698 // const-safe version: we just cast about
742 return FromRawPointer(const_cast<void*>(p)); 699 return FromRawPointer(const_cast<void*>(p));
743 } 700 }
744 701
745 void Check(int type) const { 702 void Check(int type) {
746 alloc_map_lock_.Lock(); 703 alloc_map_lock_.Lock();
747 CheckLocked(type); 704 CheckLocked(type);
748 alloc_map_lock_.Unlock(); 705 alloc_map_lock_.Unlock();
749 } 706 }
750 707
751 static bool CheckEverything() { 708 static bool CheckEverything() {
752 alloc_map_lock_.Lock(); 709 alloc_map_lock_.Lock();
753 if (alloc_map_ != NULL) alloc_map_->Iterate(CheckCallback, 0); 710 if (alloc_map_ != NULL) alloc_map_->Iterate(CheckCallback, 0);
754 alloc_map_lock_.Unlock(); 711 alloc_map_lock_.Unlock();
755 return true; // if we get here, we're okay 712 return true; // if we get here, we're okay
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 const int MallocBlock::kMagicMMap; 770 const int MallocBlock::kMagicMMap;
814 771
815 MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL; 772 MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL;
816 SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED); 773 SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED);
817 774
818 FreeQueue<MallocBlockQueueEntry>* MallocBlock::free_queue_ = NULL; 775 FreeQueue<MallocBlockQueueEntry>* MallocBlock::free_queue_ = NULL;
819 size_t MallocBlock::free_queue_size_ = 0; 776 size_t MallocBlock::free_queue_size_ = 0;
820 SpinLock MallocBlock::free_queue_lock_(SpinLock::LINKER_INITIALIZED); 777 SpinLock MallocBlock::free_queue_lock_(SpinLock::LINKER_INITIALIZED);
821 778
822 unsigned char MallocBlock::kMagicDeletedBuffer[1024]; 779 unsigned char MallocBlock::kMagicDeletedBuffer[1024];
823 pthread_once_t MallocBlock::deleted_buffer_initialized_ = PTHREAD_ONCE_INIT; 780 bool MallocBlock::deleted_buffer_initialized_ = false;
824 bool MallocBlock::deleted_buffer_initialized_no_pthreads_ = false;
825 781
826 const char* const MallocBlock::kAllocName[] = { 782 const char* const MallocBlock::kAllocName[] = {
827 "malloc", 783 "malloc",
828 "new", 784 "new",
829 "new []", 785 "new []",
830 NULL, 786 NULL,
831 }; 787 };
832 788
833 const char* const MallocBlock::kDeallocName[] = { 789 const char* const MallocBlock::kDeallocName[] = {
834 "free", 790 "free",
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) { 964 if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) {
1009 // Subtract bytes kept in the free queue 965 // Subtract bytes kept in the free queue
1010 size_t qsize = MallocBlock::FreeQueueSize(); 966 size_t qsize = MallocBlock::FreeQueueSize();
1011 if (*value >= qsize) { 967 if (*value >= qsize) {
1012 *value -= qsize; 968 *value -= qsize;
1013 } 969 }
1014 } 970 }
1015 return result; 971 return result;
1016 } 972 }
1017 973
1018 virtual bool VerifyNewMemory(const void* p) { 974 virtual bool VerifyNewMemory(void* p) {
1019 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType); 975 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType);
1020 return true; 976 return true;
1021 } 977 }
1022 978
1023 virtual bool VerifyArrayNewMemory(const void* p) { 979 virtual bool VerifyArrayNewMemory(void* p) {
1024 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType); 980 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType);
1025 return true; 981 return true;
1026 } 982 }
1027 983
1028 virtual bool VerifyMallocMemory(const void* p) { 984 virtual bool VerifyMallocMemory(void* p) {
1029 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType); 985 if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType);
1030 return true; 986 return true;
1031 } 987 }
1032 988
1033 virtual bool VerifyAllMemory() { 989 virtual bool VerifyAllMemory() {
1034 return MallocBlock::CheckEverything(); 990 return MallocBlock::CheckEverything();
1035 } 991 }
1036 992
1037 virtual bool MallocMemoryStats(int* blocks, size_t* total, 993 virtual bool MallocMemoryStats(int* blocks, size_t* total,
1038 int histogram[kMallocHistogramSize]) { 994 int histogram[kMallocHistogramSize]) {
1039 return MallocBlock::MemoryStats(blocks, total, histogram); 995 return MallocBlock::MemoryStats(blocks, total, histogram);
1040 } 996 }
1041 997
1042 virtual size_t GetEstimatedAllocatedSize(size_t size) { 998 virtual size_t GetEstimatedAllocatedSize(size_t size) {
1043 return size; 999 return size;
1044 } 1000 }
1045 1001
1046 virtual size_t GetAllocatedSize(const void* p) { 1002 virtual size_t GetAllocatedSize(void* p) {
1047 if (p) { 1003 if (p) {
1048 RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned, 1004 RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned,
1049 "ptr not allocated by tcmalloc"); 1005 "ptr not allocated by tcmalloc");
1050 return MallocBlock::FromRawPointer(p)->data_size(); 1006 return MallocBlock::FromRawPointer(p)->data_size();
1051 } 1007 }
1052 return 0; 1008 return 0;
1053 } 1009 }
1054 1010
1055 virtual MallocExtension::Ownership GetOwnership(const void* p) { 1011 virtual MallocExtension::Ownership GetOwnership(const void* p) {
1056 if (p) { 1012 if (p) {
(...skipping 15 matching lines...) Expand all
1072 i.total_bytes_free = MallocBlock::FreeQueueSize(); 1028 i.total_bytes_free = MallocBlock::FreeQueueSize();
1073 v->push_back(i); 1029 v->push_back(i);
1074 } 1030 }
1075 1031
1076 }; 1032 };
1077 1033
1078 static DebugMallocImplementation debug_malloc_implementation; 1034 static DebugMallocImplementation debug_malloc_implementation;
1079 1035
1080 REGISTER_MODULE_INITIALIZER(debugallocation, { 1036 REGISTER_MODULE_INITIALIZER(debugallocation, {
1081 // Either we or valgrind will control memory management. We 1037 // Either we or valgrind will control memory management. We
1082 // register our extension if we're the winner. Otherwise let 1038 // register our extension if we're the winner.
1083 // Valgrind use its own malloc (so don't register our extension). 1039 if (RunningOnValgrind()) {
1084 if (!RunningOnValgrind()) { 1040 // Let Valgrind uses its own malloc (so don't register our extension).
1041 } else {
1085 MallocExtension::Register(&debug_malloc_implementation); 1042 MallocExtension::Register(&debug_malloc_implementation);
1043 // When the program exits, check all blocks still in the free
1044 // queue for corruption.
1045 atexit(DanglingWriteChecker);
1086 } 1046 }
1087 }); 1047 });
1088 1048
1089 REGISTER_MODULE_DESTRUCTOR(debugallocation, {
1090 if (!RunningOnValgrind()) {
1091 // When the program exits, check all blocks still in the free
1092 // queue for corruption.
1093 DanglingWriteChecker();
1094 }
1095 });
1096
1097 // ========================================================================= // 1049 // ========================================================================= //
1098 1050
1099 // This is mostly the same a cpp_alloc in tcmalloc.cc. 1051 // This is mostly the same a cpp_alloc in tcmalloc.cc.
1100 // TODO(csilvers): change Allocate() above to call cpp_alloc, so we 1052 // TODO(csilvers): change Allocate() above to call cpp_alloc, so we
1101 // don't have to reproduce the logic here. To make tc_new_mode work 1053 // don't have to reproduce the logic here. To make tc_new_mode work
1102 // properly, I think we'll need to separate out the logic of throwing 1054 // properly, I think we'll need to separate out the logic of throwing
1103 // from the logic of calling the new-handler. 1055 // from the logic of calling the new-handler.
1104 inline void* debug_cpp_alloc(size_t size, int new_type, bool nothrow) { 1056 inline void* debug_cpp_alloc(size_t size, int new_type, bool nothrow) {
1105 for (;;) { 1057 for (;;) {
1106 void* p = DebugAllocate(size, new_type); 1058 void* p = DebugAllocate(size, new_type);
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 1363
1412 #ifdef HAVE_STRUCT_MALLINFO 1364 #ifdef HAVE_STRUCT_MALLINFO
1413 extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW { 1365 extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
1414 return BASE_MALLINFO(); 1366 return BASE_MALLINFO();
1415 } 1367 }
1416 #endif 1368 #endif
1417 1369
1418 extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW { 1370 extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
1419 return MallocExtension::instance()->GetAllocatedSize(ptr); 1371 return MallocExtension::instance()->GetAllocatedSize(ptr);
1420 } 1372 }
OLDNEW
« no previous file with comments | « third_party/tcmalloc/vendor/src/config.h.in ('k') | third_party/tcmalloc/vendor/src/google/heap-checker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698