OLD | NEW |
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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 // ========================================================================= // | 127 // ========================================================================= // |
128 | 128 |
129 // 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 |
130 // uses very little stack space. | 130 // uses very little stack space. |
131 static void TracePrintf(int fd, const char *fmt, ...) | 131 static void TracePrintf(int fd, const char *fmt, ...) |
132 __attribute__ ((__format__ (__printf__, 2, 3))); | 132 __attribute__ ((__format__ (__printf__, 2, 3))); |
133 | 133 |
134 // The do_* functions are defined in tcmalloc/tcmalloc.cc, | 134 // The do_* functions are defined in tcmalloc/tcmalloc.cc, |
135 // which is included before this file | 135 // which is included before this file |
136 // when TCMALLOC_FOR_DEBUGALLOCATION is defined | 136 // when TCMALLOC_FOR_DEBUGALLOCATION is defined |
137 #define BASE_MALLOC_NEW(size) cpp_alloc(size, false) | 137 // TODO(csilvers): get rid of these now that we are tied to tcmalloc. |
| 138 #define BASE_MALLOC_NEW do_malloc |
138 #define BASE_MALLOC do_malloc | 139 #define BASE_MALLOC do_malloc |
139 #define BASE_FREE do_free | 140 #define BASE_FREE do_free |
140 #define BASE_MALLOC_STATS do_malloc_stats | 141 #define BASE_MALLOC_STATS do_malloc_stats |
141 #define BASE_MALLOPT do_mallopt | 142 #define BASE_MALLOPT do_mallopt |
142 #define BASE_MALLINFO do_mallinfo | 143 #define BASE_MALLINFO do_mallinfo |
143 #define BASE_MALLOC_SIZE(ptr) GetSizeWithCallback(ptr, &InvalidGetAllocatedSize) | |
144 | 144 |
145 // ========================================================================= // | 145 // ========================================================================= // |
146 | 146 |
147 class MallocBlock; | 147 class MallocBlock; |
148 | 148 |
149 // A circular buffer to hold freed blocks of memory. MallocBlock::Deallocate | 149 // A circular buffer to hold freed blocks of memory. MallocBlock::Deallocate |
150 // (below) pushes blocks into this queue instead of returning them to the | 150 // (below) pushes blocks into this queue instead of returning them to the |
151 // underlying allocator immediately. See MallocBlock::Deallocate for more | 151 // underlying allocator immediately. See MallocBlock::Deallocate for more |
152 // information. | 152 // information. |
153 // | 153 // |
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 | 988 |
989 virtual bool VerifyAllMemory() { | 989 virtual bool VerifyAllMemory() { |
990 return MallocBlock::CheckEverything(); | 990 return MallocBlock::CheckEverything(); |
991 } | 991 } |
992 | 992 |
993 virtual bool MallocMemoryStats(int* blocks, size_t* total, | 993 virtual bool MallocMemoryStats(int* blocks, size_t* total, |
994 int histogram[kMallocHistogramSize]) { | 994 int histogram[kMallocHistogramSize]) { |
995 return MallocBlock::MemoryStats(blocks, total, histogram); | 995 return MallocBlock::MemoryStats(blocks, total, histogram); |
996 } | 996 } |
997 | 997 |
| 998 virtual size_t GetEstimatedAllocatedSize(size_t size) { |
| 999 return size; |
| 1000 } |
| 1001 |
998 virtual size_t GetAllocatedSize(void* p) { | 1002 virtual size_t GetAllocatedSize(void* p) { |
999 if (p) { | 1003 if (p) { |
| 1004 RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned, |
| 1005 "ptr not allocated by tcmalloc"); |
1000 return MallocBlock::FromRawPointer(p)->data_size(); | 1006 return MallocBlock::FromRawPointer(p)->data_size(); |
1001 } | 1007 } |
1002 return 0; | 1008 return 0; |
1003 } | 1009 } |
1004 virtual size_t GetEstimatedAllocatedSize(size_t size) { | 1010 |
1005 return size; | 1011 virtual MallocExtension::Ownership GetOwnership(const void* p) { |
| 1012 if (p) { |
| 1013 const MallocBlock* mb = MallocBlock::FromRawPointer(p); |
| 1014 return TCMallocImplementation::GetOwnership(mb); |
| 1015 } |
| 1016 return MallocExtension::kNotOwned; // nobody owns NULL |
1006 } | 1017 } |
1007 | 1018 |
1008 virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) { | 1019 virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) { |
1009 static const char* kDebugFreeQueue = "debug.free_queue"; | 1020 static const char* kDebugFreeQueue = "debug.free_queue"; |
1010 | 1021 |
1011 TCMallocImplementation::GetFreeListSizes(v); | 1022 TCMallocImplementation::GetFreeListSizes(v); |
1012 | 1023 |
1013 MallocExtension::FreeListInfo i; | 1024 MallocExtension::FreeListInfo i; |
1014 i.type = kDebugFreeQueue; | 1025 i.type = kDebugFreeQueue; |
1015 i.min_object_size = 0; | 1026 i.min_object_size = 0; |
(...skipping 15 matching lines...) Expand all Loading... |
1031 MallocExtension::Register(&debug_malloc_implementation); | 1042 MallocExtension::Register(&debug_malloc_implementation); |
1032 // When the program exits, check all blocks still in the free | 1043 // When the program exits, check all blocks still in the free |
1033 // queue for corruption. | 1044 // queue for corruption. |
1034 atexit(DanglingWriteChecker); | 1045 atexit(DanglingWriteChecker); |
1035 } | 1046 } |
1036 }); | 1047 }); |
1037 | 1048 |
1038 // ========================================================================= // | 1049 // ========================================================================= // |
1039 | 1050 |
1040 // This is mostly the same a cpp_alloc in tcmalloc.cc. | 1051 // This is mostly the same a cpp_alloc in tcmalloc.cc. |
1041 // TODO(csilvers): write a wrapper for new-handler so we don't have to | 1052 // TODO(csilvers): change Allocate() above to call cpp_alloc, so we |
1042 // copy this code so much. | 1053 // don't have to reproduce the logic here. To make tc_new_mode work |
| 1054 // properly, I think we'll need to separate out the logic of throwing |
| 1055 // from the logic of calling the new-handler. |
1043 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) { |
1044 for (;;) { | 1057 for (;;) { |
1045 void* p = DebugAllocate(size, new_type); | 1058 void* p = DebugAllocate(size, new_type); |
1046 #ifdef PREANSINEW | 1059 #ifdef PREANSINEW |
1047 return p; | 1060 return p; |
1048 #else | 1061 #else |
1049 if (p == NULL) { // allocation failed | 1062 if (p == NULL) { // allocation failed |
1050 // Get the current new handler. NB: this function is not | 1063 // Get the current new handler. NB: this function is not |
1051 // thread-safe. We make a feeble stab at making it so here, but | 1064 // thread-safe. We make a feeble stab at making it so here, but |
1052 // this lock only protects against tcmalloc interfering with | 1065 // this lock only protects against tcmalloc interfering with |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 return BASE_MALLOPT(cmd, value); | 1361 return BASE_MALLOPT(cmd, value); |
1349 } | 1362 } |
1350 | 1363 |
1351 #ifdef HAVE_STRUCT_MALLINFO | 1364 #ifdef HAVE_STRUCT_MALLINFO |
1352 extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW { | 1365 extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW { |
1353 return BASE_MALLINFO(); | 1366 return BASE_MALLINFO(); |
1354 } | 1367 } |
1355 #endif | 1368 #endif |
1356 | 1369 |
1357 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 { |
1358 if (!ptr) { | 1371 return MallocExtension::instance()->GetAllocatedSize(ptr); |
1359 return 0; | |
1360 } | |
1361 MallocBlock* mb = MallocBlock::FromRawPointer(ptr); | |
1362 // This is just to make sure we actually own mb (and ptr). We don't | |
1363 // use the actual value, just the 'exception' it raises on error. | |
1364 (void)BASE_MALLOC_SIZE(mb); | |
1365 return mb->data_size(); | |
1366 } | 1372 } |
1367 | |
1368 // Override __libc_memalign in libc on linux boxes. | |
1369 // They have a bug in libc that causes them (very rarely) to allocate | |
1370 // with __libc_memalign() yet deallocate with free(). | |
1371 // This function is an exception to the rule of calling MallocHook method | |
1372 // from the stack frame of the allocation function; | |
1373 // heap-checker handles this special case explicitly. | |
1374 static void *MemalignOverride(size_t align, size_t size, const void *caller) | |
1375 __THROW ATTRIBUTE_SECTION(google_malloc); | |
1376 | |
1377 static void *MemalignOverride(size_t align, size_t size, const void *caller) | |
1378 __THROW { | |
1379 void *p = do_debug_memalign_or_debug_cpp_memalign(align, size); | |
1380 MallocHook::InvokeNewHook(p, size); | |
1381 return p; | |
1382 } | |
1383 void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; | |
OLD | NEW |