Add method to use allocator app defaults.
Currently, apps turn off zeroing of memory and enable the decay
timer. For shell commands, set these values when the environment
variable MALLOC_USE_APP_DEFAULTS is set. This fixes performance
differences found between shell spawned command-line tools and
native code running in an app.
Add a unit test to verify setting after exec.
Bug: 302212507
Test: Set the variable to 1 and verified the decay time is enabled.
Test: Set the variable to "" and also unset it and verified the decay
Test: time is not enabled.
Test: Verified that with the variable set, the memory is not zero'd
Test: by default.
Test: Unit tests pass.
Change-Id: I22a47f70f1ce1205c16195532c54b2bf9403e9cd
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index cd96375..85e742c 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -185,6 +185,7 @@
/*load_bias = */ 0);
__libc_init_mte_stack(/*stack_top = */ raw_args);
__libc_init_scudo();
+ __libc_globals.mutate(__libc_init_malloc);
__libc_init_profiling_handlers();
__libc_init_fork_handler();
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 441d884..1e0ef14 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -41,6 +41,7 @@
#include <platform/bionic/malloc.h>
#include <private/ScopedPthreadMutexLocker.h>
#include <private/bionic_config.h>
+#include <private/bionic_defs.h>
#include "gwp_asan_wrappers.h"
#include "heap_tagging.h"
@@ -358,3 +359,37 @@
const MallocDispatch* NativeAllocatorDispatch() {
return &__libc_malloc_default_dispatch;
}
+
+#if !defined(LIBC_STATIC)
+void MallocInitImpl(libc_globals* globals);
+#endif
+
+// Initializes memory allocation framework.
+// This routine is called from __libc_init routines in libc_init_dynamic.cpp
+// and libc_init_static.cpp.
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
+#if !defined(LIBC_STATIC)
+ MallocInitImpl(globals);
+#endif
+ const char* value = getenv("MALLOC_USE_APP_DEFAULTS");
+ if (value == nullptr || value[0] == '\0') {
+ return;
+ }
+
+ // Normal apps currently turn off zero init for performance reasons.
+ SetHeapZeroInitialize(false);
+
+ // Do not call mallopt directly since that will try and lock the globals
+ // data structure.
+ int retval;
+ auto dispatch_table = GetDispatchTable();
+ if (__predict_false(dispatch_table != nullptr)) {
+ retval = dispatch_table->mallopt(M_DECAY_TIME, 1);
+ } else {
+ retval = Malloc(mallopt)(M_DECAY_TIME, 1);
+ }
+ if (retval == 1) {
+ globals->decay_time_enabled = true;
+ }
+}
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 7b6d7d4..e2c6eb1 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -375,7 +375,7 @@
extern "C" size_t __scudo_get_stack_depot_size();
// Initializes memory allocation framework once per process.
-static void MallocInitImpl(libc_globals* globals) {
+void MallocInitImpl(libc_globals* globals) {
char prop[PROP_VALUE_MAX];
char* options = prop;
@@ -409,13 +409,6 @@
}
}
-// Initializes memory allocation framework.
-// This routine is called from __libc_init routines in libc_init_dynamic.cpp.
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
- MallocInitImpl(globals);
-}
-
// =============================================================================
// Functions to support dumping of native heap allocations using malloc debug.
// =============================================================================
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 8bd8bc6..37c1ef0 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1779,3 +1779,32 @@
GTEST_SKIP() << "bionic-only test";
#endif
}
+
+TEST(android_mallopt, DISABLED_verify_decay_time_on) {
+#if defined(__BIONIC__)
+ bool value;
+ EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
+ EXPECT_TRUE(value) << "decay time did not get enabled properly.";
+#endif
+}
+
+TEST(android_mallopt, decay_time_set_using_env_variable) {
+#if defined(__BIONIC__)
+ SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
+
+ bool value;
+ ASSERT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
+ ASSERT_FALSE(value) << "decay time did not get disabled properly.";
+
+ // Verify that setting the environment variable here will be carried into
+ // fork'd and exec'd processes.
+ ASSERT_EQ(0, setenv("MALLOC_USE_APP_DEFAULTS", "1", 1));
+ ExecTestHelper eth;
+ eth.SetArgs({testing::internal::GetArgvs()[0].c_str(), "--gtest_also_run_disabled_tests",
+ "--gtest_filter=android_mallopt.DISABLED_verify_decay_time_on", nullptr});
+ eth.Run([&]() { execv(testing::internal::GetArgvs()[0].c_str(), eth.GetArgs()); }, 0,
+ R"(\[ PASSED \] 1 test)");
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}