Merge "sysconf(_SC_ARG_MAX): go back to imitating the kernel."
diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp
index ec3f6f2..ffcedf0 100644
--- a/benchmarks/stdlib_benchmark.cpp
+++ b/benchmarks/stdlib_benchmark.cpp
@@ -24,11 +24,6 @@
 #include <benchmark/benchmark.h>
 #include "util.h"
 
-#if defined(__BIONIC__)
-
-#else
-#endif
-
 static __always_inline void MakeAllocationResident(void* ptr, size_t nbytes, int pagesize) {
   uint8_t* data = reinterpret_cast<uint8_t*>(ptr);
   for (size_t i = 0; i < nbytes; i += pagesize) {
diff --git a/docs/native_allocator.md b/docs/native_allocator.md
index adfa6ef..249b144 100644
--- a/docs/native_allocator.md
+++ b/docs/native_allocator.md
@@ -144,6 +144,32 @@
 These benchmarks are only used to verify the speed of the allocator and
 ignore anything related to RSS and virtual address space consumed.
 
+For all of these benchmark runs, it can be useful to add these two options:
+
+    --benchmark_repetitions=XX
+    --benchmark_report_aggregates_only=true
+
+This will run the benchmark XX times and then give a mean, median, and stddev
+and helps to get a number that can be compared to the new allocator.
+
+In addition, there is another option:
+
+    --bionic_cpu=XX
+
+Which will lock the benchmark to only run on core XX. This also avoids
+any issue related to the code migrating from one core to another
+with different characteristics. For example, on a big-little cpu, if the
+benchmark moves from big to little or vice-versa, this can cause scores
+to fluctuate in indeterminte ways.
+
+For most runs, the best set of options to add is:
+
+    --benchmark_repetitions=10 --benchmark_report_aggregates_only=true --bionic_cpu=3
+
+On most phones with a big-little cpu, the third core is the little core.
+Choosing to run on the little core can tend to highlight any performance
+differences.
+
 #### Allocate/Free Benchmarks
 These are the benchmarks to verify the allocation speed of a loop doing a
 single allocation, touching every page in the allocation to make it resident
@@ -240,6 +266,18 @@
 
 These numbers should be as performant as the current allocator.
 
+#### mallinfo Benchmark
+This benchmark only verifies that mallinfo is still close to the performance
+of the current allocator.
+
+To run the benchmark, use these commands:
+
+    adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=BM_mallinfo
+    adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=BM_mallinfo
+
+Calls to mallinfo are used in ART so a new allocator is required to be
+nearly as performant as the current allocator.
+
 ### Memory Trace Benchmarks
 These benchmarks measure all three axes of a native allocator, RSS, virtual
 address space consumed, speed of allocation. They are designed to
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 1f099cf..b6a9ed2 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -101,13 +101,15 @@
 
   __libc_add_main_thread();
 
-  // Register atfork handlers to take and release the arc4random lock.
-  pthread_atfork(arc4random_fork_handler, _thread_arc4_unlock, _thread_arc4_unlock);
-
   __system_properties_init(); // Requires 'environ'.
   __libc_init_fdsan(); // Requires system properties (for debug.fdsan).
 }
 
+void __libc_init_fork_handler() {
+  // Register atfork handlers to take and release the arc4random lock.
+  pthread_atfork(arc4random_fork_handler, _thread_arc4_unlock, _thread_arc4_unlock);
+}
+
 __noreturn static void __early_abort(int line) {
   // We can't write to stdout or stderr because we're aborting before we've checked that
   // it's safe for us to use those file descriptors. We probably can't strace either, so
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 73f5817..0c2e78a 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -56,4 +56,8 @@
 
 __LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp);
 
+// The fork handler must be initialised after __libc_init_malloc, as
+// pthread_atfork may call malloc() during its once-init.
+__LIBC_HIDDEN__ void __libc_init_fork_handler();
+
 #endif
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index d6d5552..ca94652 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -99,6 +99,8 @@
   // Hooks for various libraries to let them know that we're starting up.
   __libc_globals.mutate(__libc_init_malloc);
 
+  __libc_init_fork_handler();
+
 #if __has_feature(hwaddress_sanitizer)
   // Notify the HWASan runtime library whenever a library is loaded or unloaded
   // so that it can update its shadow memory.
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 28c0b0c..5c1d27e 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -181,6 +181,7 @@
   layout_static_tls(args);
   __libc_init_main_thread_final();
   __libc_init_common();
+  __libc_init_fork_handler();
 
   call_ifunc_resolvers();
   apply_gnu_relro();