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; |
Primiano Tucci (use gerrit)
2016/07/15 14:02:10
To be honest I am not sure I understand all the bl
|
+ |
+namespace { |
+ |
+int win_new_mode = 0; |
+ |
+} // namespace |
+ |
+// This function behaves similarly to MSVC's _set_new_mode. |
Primiano Tucci (use gerrit)
2016/07/12 14:51:05
I think this block is better placed in the impl.cc
Sigurður Ásgeirsson
2016/07/14 19:04:27
There is a small difference in that this one calls
Primiano Tucci (use gerrit)
2016/07/15 14:02:10
Oh I see. Ok now I follow it. In windows there is
|
+// 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) |
Primiano Tucci (use gerrit)
2016/07/12 14:51:05
maybe add a comment here explaining that on win th
Sigurður Ásgeirsson
2016/07/14 19:04:27
Done.
|
// 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. |