| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/process/memory.h" | 5 #include "base/process/memory.h" |
| 6 | 6 |
| 7 #include <CoreFoundation/CoreFoundation.h> | 7 #include <CoreFoundation/CoreFoundation.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <mach/mach.h> | 9 #include <mach/mach.h> |
| 10 #include <mach/mach_vm.h> | 10 #include <mach/mach_vm.h> |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 calloc_type g_old_calloc_purgeable; | 124 calloc_type g_old_calloc_purgeable; |
| 125 valloc_type g_old_valloc_purgeable; | 125 valloc_type g_old_valloc_purgeable; |
| 126 free_type g_old_free_purgeable; | 126 free_type g_old_free_purgeable; |
| 127 realloc_type g_old_realloc_purgeable; | 127 realloc_type g_old_realloc_purgeable; |
| 128 memalign_type g_old_memalign_purgeable; | 128 memalign_type g_old_memalign_purgeable; |
| 129 | 129 |
| 130 void* oom_killer_malloc(struct _malloc_zone_t* zone, | 130 void* oom_killer_malloc(struct _malloc_zone_t* zone, |
| 131 size_t size) { | 131 size_t size) { |
| 132 void* result = g_old_malloc(zone, size); | 132 void* result = g_old_malloc(zone, size); |
| 133 if (!result && size) | 133 if (!result && size) |
| 134 debug::BreakDebugger(); | 134 TerminateBecauseOutOfMemory(size); |
| 135 return result; | 135 return result; |
| 136 } | 136 } |
| 137 | 137 |
| 138 void* oom_killer_calloc(struct _malloc_zone_t* zone, | 138 void* oom_killer_calloc(struct _malloc_zone_t* zone, |
| 139 size_t num_items, | 139 size_t num_items, |
| 140 size_t size) { | 140 size_t size) { |
| 141 void* result = g_old_calloc(zone, num_items, size); | 141 void* result = g_old_calloc(zone, num_items, size); |
| 142 if (!result && num_items && size) | 142 if (!result && num_items && size) |
| 143 debug::BreakDebugger(); | 143 TerminateBecauseOutOfMemory(num_items * size); |
| 144 return result; | 144 return result; |
| 145 } | 145 } |
| 146 | 146 |
| 147 void* oom_killer_valloc(struct _malloc_zone_t* zone, | 147 void* oom_killer_valloc(struct _malloc_zone_t* zone, |
| 148 size_t size) { | 148 size_t size) { |
| 149 void* result = g_old_valloc(zone, size); | 149 void* result = g_old_valloc(zone, size); |
| 150 if (!result && size) | 150 if (!result && size) |
| 151 debug::BreakDebugger(); | 151 TerminateBecauseOutOfMemory(size); |
| 152 return result; | 152 return result; |
| 153 } | 153 } |
| 154 | 154 |
| 155 void oom_killer_free(struct _malloc_zone_t* zone, | 155 void oom_killer_free(struct _malloc_zone_t* zone, |
| 156 void* ptr) { | 156 void* ptr) { |
| 157 g_old_free(zone, ptr); | 157 g_old_free(zone, ptr); |
| 158 } | 158 } |
| 159 | 159 |
| 160 void* oom_killer_realloc(struct _malloc_zone_t* zone, | 160 void* oom_killer_realloc(struct _malloc_zone_t* zone, |
| 161 void* ptr, | 161 void* ptr, |
| 162 size_t size) { | 162 size_t size) { |
| 163 void* result = g_old_realloc(zone, ptr, size); | 163 void* result = g_old_realloc(zone, ptr, size); |
| 164 if (!result && size) | 164 if (!result && size) |
| 165 debug::BreakDebugger(); | 165 TerminateBecauseOutOfMemory(size); |
| 166 return result; | 166 return result; |
| 167 } | 167 } |
| 168 | 168 |
| 169 void* oom_killer_memalign(struct _malloc_zone_t* zone, | 169 void* oom_killer_memalign(struct _malloc_zone_t* zone, |
| 170 size_t alignment, | 170 size_t alignment, |
| 171 size_t size) { | 171 size_t size) { |
| 172 void* result = g_old_memalign(zone, alignment, size); | 172 void* result = g_old_memalign(zone, alignment, size); |
| 173 // Only die if posix_memalign would have returned ENOMEM, since there are | 173 // Only die if posix_memalign would have returned ENOMEM, since there are |
| 174 // other reasons why NULL might be returned (see | 174 // other reasons why NULL might be returned (see |
| 175 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 175 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
| 176 if (!result && size && alignment >= sizeof(void*) && | 176 if (!result && size && alignment >= sizeof(void*) && |
| 177 (alignment & (alignment - 1)) == 0) { | 177 (alignment & (alignment - 1)) == 0) { |
| 178 debug::BreakDebugger(); | 178 TerminateBecauseOutOfMemory(size); |
| 179 } | 179 } |
| 180 return result; | 180 return result; |
| 181 } | 181 } |
| 182 | 182 |
| 183 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, | 183 void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone, |
| 184 size_t size) { | 184 size_t size) { |
| 185 void* result = g_old_malloc_purgeable(zone, size); | 185 void* result = g_old_malloc_purgeable(zone, size); |
| 186 if (!result && size) | 186 if (!result && size) |
| 187 debug::BreakDebugger(); | 187 TerminateBecauseOutOfMemory(size); |
| 188 return result; | 188 return result; |
| 189 } | 189 } |
| 190 | 190 |
| 191 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, | 191 void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone, |
| 192 size_t num_items, | 192 size_t num_items, |
| 193 size_t size) { | 193 size_t size) { |
| 194 void* result = g_old_calloc_purgeable(zone, num_items, size); | 194 void* result = g_old_calloc_purgeable(zone, num_items, size); |
| 195 if (!result && num_items && size) | 195 if (!result && num_items && size) |
| 196 debug::BreakDebugger(); | 196 TerminateBecauseOutOfMemory(num_items * size); |
| 197 return result; | 197 return result; |
| 198 } | 198 } |
| 199 | 199 |
| 200 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, | 200 void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone, |
| 201 size_t size) { | 201 size_t size) { |
| 202 void* result = g_old_valloc_purgeable(zone, size); | 202 void* result = g_old_valloc_purgeable(zone, size); |
| 203 if (!result && size) | 203 if (!result && size) |
| 204 debug::BreakDebugger(); | 204 TerminateBecauseOutOfMemory(size); |
| 205 return result; | 205 return result; |
| 206 } | 206 } |
| 207 | 207 |
| 208 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, | 208 void oom_killer_free_purgeable(struct _malloc_zone_t* zone, |
| 209 void* ptr) { | 209 void* ptr) { |
| 210 g_old_free_purgeable(zone, ptr); | 210 g_old_free_purgeable(zone, ptr); |
| 211 } | 211 } |
| 212 | 212 |
| 213 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, | 213 void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone, |
| 214 void* ptr, | 214 void* ptr, |
| 215 size_t size) { | 215 size_t size) { |
| 216 void* result = g_old_realloc_purgeable(zone, ptr, size); | 216 void* result = g_old_realloc_purgeable(zone, ptr, size); |
| 217 if (!result && size) | 217 if (!result && size) |
| 218 debug::BreakDebugger(); | 218 TerminateBecauseOutOfMemory(size); |
| 219 return result; | 219 return result; |
| 220 } | 220 } |
| 221 | 221 |
| 222 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, | 222 void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, |
| 223 size_t alignment, | 223 size_t alignment, |
| 224 size_t size) { | 224 size_t size) { |
| 225 void* result = g_old_memalign_purgeable(zone, alignment, size); | 225 void* result = g_old_memalign_purgeable(zone, alignment, size); |
| 226 // Only die if posix_memalign would have returned ENOMEM, since there are | 226 // Only die if posix_memalign would have returned ENOMEM, since there are |
| 227 // other reasons why NULL might be returned (see | 227 // other reasons why NULL might be returned (see |
| 228 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). | 228 // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). |
| 229 if (!result && size && alignment >= sizeof(void*) | 229 if (!result && size && alignment >= sizeof(void*) |
| 230 && (alignment & (alignment - 1)) == 0) { | 230 && (alignment & (alignment - 1)) == 0) { |
| 231 debug::BreakDebugger(); | 231 TerminateBecauseOutOfMemory(size); |
| 232 } | 232 } |
| 233 return result; | 233 return result; |
| 234 } | 234 } |
| 235 | 235 |
| 236 #endif // !defined(ADDRESS_SANITIZER) | 236 #endif // !defined(ADDRESS_SANITIZER) |
| 237 | 237 |
| 238 // === C++ operator new === | 238 // === C++ operator new === |
| 239 | 239 |
| 240 void oom_killer_new() { | 240 void oom_killer_new() { |
| 241 debug::BreakDebugger(); | 241 TerminateBecauseOutOfMemory(0); |
| 242 } | 242 } |
| 243 | 243 |
| 244 #if !defined(ADDRESS_SANITIZER) | 244 #if !defined(ADDRESS_SANITIZER) |
| 245 | 245 |
| 246 // === Core Foundation CFAllocators === | 246 // === Core Foundation CFAllocators === |
| 247 | 247 |
| 248 bool CanGetContextForCFAllocator() { | 248 bool CanGetContextForCFAllocator() { |
| 249 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); | 249 return !base::mac::IsOSLaterThanYosemite_DontCallThis(); |
| 250 } | 250 } |
| 251 | 251 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 270 | 270 |
| 271 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; | 271 CFAllocatorAllocateCallBack g_old_cfallocator_system_default; |
| 272 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; | 272 CFAllocatorAllocateCallBack g_old_cfallocator_malloc; |
| 273 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; | 273 CFAllocatorAllocateCallBack g_old_cfallocator_malloc_zone; |
| 274 | 274 |
| 275 void* oom_killer_cfallocator_system_default(CFIndex alloc_size, | 275 void* oom_killer_cfallocator_system_default(CFIndex alloc_size, |
| 276 CFOptionFlags hint, | 276 CFOptionFlags hint, |
| 277 void* info) { | 277 void* info) { |
| 278 void* result = g_old_cfallocator_system_default(alloc_size, hint, info); | 278 void* result = g_old_cfallocator_system_default(alloc_size, hint, info); |
| 279 if (!result) | 279 if (!result) |
| 280 debug::BreakDebugger(); | 280 TerminateBecauseOutOfMemory(alloc_size); |
| 281 return result; | 281 return result; |
| 282 } | 282 } |
| 283 | 283 |
| 284 void* oom_killer_cfallocator_malloc(CFIndex alloc_size, | 284 void* oom_killer_cfallocator_malloc(CFIndex alloc_size, |
| 285 CFOptionFlags hint, | 285 CFOptionFlags hint, |
| 286 void* info) { | 286 void* info) { |
| 287 void* result = g_old_cfallocator_malloc(alloc_size, hint, info); | 287 void* result = g_old_cfallocator_malloc(alloc_size, hint, info); |
| 288 if (!result) | 288 if (!result) |
| 289 debug::BreakDebugger(); | 289 TerminateBecauseOutOfMemory(alloc_size); |
| 290 return result; | 290 return result; |
| 291 } | 291 } |
| 292 | 292 |
| 293 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, | 293 void* oom_killer_cfallocator_malloc_zone(CFIndex alloc_size, |
| 294 CFOptionFlags hint, | 294 CFOptionFlags hint, |
| 295 void* info) { | 295 void* info) { |
| 296 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); | 296 void* result = g_old_cfallocator_malloc_zone(alloc_size, hint, info); |
| 297 if (!result) | 297 if (!result) |
| 298 debug::BreakDebugger(); | 298 TerminateBecauseOutOfMemory(alloc_size); |
| 299 return result; | 299 return result; |
| 300 } | 300 } |
| 301 | 301 |
| 302 #endif // !defined(ADDRESS_SANITIZER) | 302 #endif // !defined(ADDRESS_SANITIZER) |
| 303 | 303 |
| 304 // === Cocoa NSObject allocation === | 304 // === Cocoa NSObject allocation === |
| 305 | 305 |
| 306 typedef id (*allocWithZone_t)(id, SEL, NSZone*); | 306 typedef id (*allocWithZone_t)(id, SEL, NSZone*); |
| 307 allocWithZone_t g_old_allocWithZone; | 307 allocWithZone_t g_old_allocWithZone; |
| 308 | 308 |
| 309 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) | 309 id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone) |
| 310 { | 310 { |
| 311 id result = g_old_allocWithZone(self, _cmd, zone); | 311 id result = g_old_allocWithZone(self, _cmd, zone); |
| 312 if (!result) | 312 if (!result) |
| 313 debug::BreakDebugger(); | 313 TerminateBecauseOutOfMemory(0); |
| 314 return result; | 314 return result; |
| 315 } | 315 } |
| 316 | 316 |
| 317 } // namespace | 317 } // namespace |
| 318 | 318 |
| 319 bool UncheckedMalloc(size_t size, void** result) { | 319 bool UncheckedMalloc(size_t size, void** result) { |
| 320 #if defined(ADDRESS_SANITIZER) | 320 #if defined(ADDRESS_SANITIZER) |
| 321 *result = malloc(size); | 321 *result = malloc(size); |
| 322 #else | 322 #else |
| 323 if (g_old_malloc) { | 323 if (g_old_malloc) { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 @selector(allocWithZone:)); | 552 @selector(allocWithZone:)); |
| 553 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( | 553 g_old_allocWithZone = reinterpret_cast<allocWithZone_t>( |
| 554 method_getImplementation(orig_method)); | 554 method_getImplementation(orig_method)); |
| 555 CHECK(g_old_allocWithZone) | 555 CHECK(g_old_allocWithZone) |
| 556 << "Failed to get allocWithZone allocation function."; | 556 << "Failed to get allocWithZone allocation function."; |
| 557 method_setImplementation(orig_method, | 557 method_setImplementation(orig_method, |
| 558 reinterpret_cast<IMP>(oom_killer_allocWithZone)); | 558 reinterpret_cast<IMP>(oom_killer_allocWithZone)); |
| 559 } | 559 } |
| 560 | 560 |
| 561 } // namespace base | 561 } // namespace base |
| OLD | NEW |