Chromium Code Reviews| Index: base/allocator/allocator_shim.cc |
| diff --git a/base/allocator/allocator_shim.cc b/base/allocator/allocator_shim.cc |
| index af08ec039fd73af7a90a879c6fd54cd88060d883..c9d76751467a7697d4945a14d74f717211489f7e 100644 |
| --- a/base/allocator/allocator_shim.cc |
| +++ b/base/allocator/allocator_shim.cc |
| @@ -5,7 +5,6 @@ |
| #include "base/allocator/allocator_shim.h" |
| #include <errno.h> |
| -#include <unistd.h> |
| #include <new> |
| @@ -15,6 +14,12 @@ |
| #include "base/threading/platform_thread.h" |
| #include "build/build_config.h" |
| +#if !defined(OS_WIN) |
| +#include <unistd.h> |
| +#else |
| +#include "base/allocator/allocator_impl_win.h" |
| +#endif |
| + |
| // No calls to malloc / new in this file. They would would cause re-entrancy of |
| // the shim, which is hard to deal with. Keep this code as simple as possible |
| // and don't use any external C++ object here, not even //base ones. Even if |
| @@ -43,15 +48,22 @@ bool CalledOnValidThread() { |
| } |
| inline size_t GetPageSize() { |
| +#if defined(OS_WIN) |
| + return 4096; |
| +#else |
| static size_t pagesize = 0; |
| if (!pagesize) |
| pagesize = sysconf(_SC_PAGESIZE); |
| return pagesize; |
| +#endif |
| } |
| // Calls the std::new handler thread-safely. Returns true if a new_handler was |
| // set and called, false if no new_handler was set. |
| -bool CallNewHandler() { |
| +bool CallNewHandler(size_t size) { |
| +#if defined(OS_WIN) |
| + return base::allocator::WinCallNewHandler(size); |
| +#else |
| // TODO(primiano): C++11 has introduced ::get_new_handler() which is supposed |
| // to be thread safe and would avoid the spinlock boilerplate here. However |
| // it doesn't seem to be available yet in the Linux chroot headers yet. |
| @@ -69,6 +81,7 @@ bool CallNewHandler() { |
| // Assume the new_handler will abort if it fails. Exception are disabled and |
| // we don't support the case of a new_handler throwing std::bad_balloc. |
| return true; |
| +#endif |
| } |
| inline const allocator::AllocatorDispatch* GetChainHead() { |
| @@ -148,7 +161,7 @@ void* ShimCppNew(size_t size) { |
| void* ptr; |
| do { |
| ptr = chain_head->alloc_function(chain_head, size); |
| - } while (!ptr && CallNewHandler()); |
| + } while (!ptr && CallNewHandler(size)); |
| return ptr; |
| } |
| @@ -162,7 +175,8 @@ void* ShimMalloc(size_t size) { |
| void* ptr; |
| do { |
| ptr = chain_head->alloc_function(chain_head, size); |
| - } while (!ptr && g_call_new_handler_on_malloc_failure && CallNewHandler()); |
| + } while (!ptr && g_call_new_handler_on_malloc_failure && |
| + CallNewHandler(size)); |
| return ptr; |
| } |
| @@ -171,7 +185,8 @@ void* ShimCalloc(size_t n, size_t size) { |
| void* ptr; |
| do { |
| ptr = chain_head->alloc_zero_initialized_function(chain_head, n, size); |
| - } while (!ptr && g_call_new_handler_on_malloc_failure && CallNewHandler()); |
| + } while (!ptr && g_call_new_handler_on_malloc_failure && |
| + CallNewHandler(size)); |
| return ptr; |
| } |
| @@ -183,7 +198,7 @@ void* ShimRealloc(void* address, size_t size) { |
| do { |
| ptr = chain_head->realloc_function(chain_head, address, size); |
| } while (!ptr && size && g_call_new_handler_on_malloc_failure && |
| - CallNewHandler()); |
| + CallNewHandler(size)); |
| return ptr; |
| } |
| @@ -192,7 +207,8 @@ void* ShimMemalign(size_t alignment, size_t size) { |
| void* ptr; |
| do { |
| ptr = chain_head->alloc_aligned_function(chain_head, alignment, size); |
| - } while (!ptr && g_call_new_handler_on_malloc_failure && CallNewHandler()); |
| + } while (!ptr && g_call_new_handler_on_malloc_failure && |
| + CallNewHandler(size)); |
| return ptr; |
| } |
| @@ -227,10 +243,48 @@ void ShimFree(void* address) { |
| return chain_head->free_function(chain_head, address); |
| } |
| +#if defined(OS_WIN) |
| + |
| +void* (*malloc_unchecked)(size_t) = &base::allocator::UncheckedAlloc; |
|
Sigurður Ásgeirsson
2016/07/11 19:51:51
I'm unhappy about putting this code here for some
|
| + |
| +namespace { |
| + |
| +int win_new_mode = 0; |
| + |
| +} // namespace |
| + |
| +// This function behaves similarly to MSVC's _set_new_mode. |
| +// If flag is 0 (default), calls to malloc will behave normally. |
| +// If flag is 1, calls to malloc will behave like calls to new, |
| +// and the std_new_handler will be invoked on failure. |
| +// Returns the previous mode. |
| +// |
| +// Replaces _set_new_mode in ucrt\heap\new_mode.cpp |
| +int _set_new_mode(int flag) { |
| + // The MS CRT calls this function early on in startup, so this serves as a low |
| + // overhead proof that the allocator shim is in place for this process. |
| + base::allocator::g_is_win_shim_layer_initialized = true; |
| + int old_mode = win_new_mode; |
| + win_new_mode = flag; |
| + |
| + base::allocator::SetCallNewHandlerOnMallocFailure(win_new_mode != 0); |
| + |
| + return old_mode; |
| +} |
| + |
| +// Replaces _query_new_mode in ucrt\heap\new_mode.cpp |
| +int _query_new_mode() { |
| + return win_new_mode; |
| +} |
| + |
| +#endif |
| + |
| } // extern "C" |
| +#if !defined(OS_WIN) |
|
Sigurður Ásgeirsson
2016/07/11 19:51:51
this needs a different implementation on Win, as p
|
| // Cpp symbols (new / delete) should always be routed through the shim layer. |
| #include "base/allocator/allocator_shim_override_cpp_symbols.h" |
| +#endif |
| // Android does not support symbol interposition. The way malloc symbols are |
| // intercepted on Android is by using link-time -wrap flags. |