Bug 680190 - Notify jemalloc when forking on Android; r=cjones
authorJim Chen <jimnchen@gmail.com>
Tue, 30 Aug 2011 17:11:36 -0700
changeset 76245 157511556e27b5a1042ffe87187bdfa4fc88e4cd
parent 76244 902d3de6f41dfb75d8896ef3e9c86b46ba9ea771
child 76246 a2b9d2cfc61a41908a58d4c8cabececf3d99a933
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerscjones
bugs680190
milestone9.0a1
Bug 680190 - Notify jemalloc when forking on Android; r=cjones
ipc/chromium/src/base/process_util_linux.cc
memory/jemalloc/jemalloc.c
--- a/ipc/chromium/src/base/process_util_linux.cc
+++ b/ipc/chromium/src/base/process_util_linux.cc
@@ -14,16 +14,23 @@
 
 #include "base/debug_util.h"
 #include "base/eintr_wrapper.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/string_tokenizer.h"
 #include "base/string_util.h"
 
+#ifdef MOZ_MEMORY_ANDROID
+extern "C" {
+extern void _malloc_prefork(void);
+extern void _malloc_postfork(void);
+}
+#endif
+
 namespace {
 
 enum ParsingState {
   KEY_NAME,
   KEY_VALUE
 };
 
 static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
@@ -39,17 +46,27 @@ bool LaunchApp(const std::vector<std::st
                    wait, process_handle);
 }
 
 bool LaunchApp(const std::vector<std::string>& argv,
                const file_handle_mapping_vector& fds_to_remap,
                const environment_map& env_vars_to_set,
                bool wait, ProcessHandle* process_handle,
                ProcessArchitecture arch) {
+#ifdef MOZ_MEMORY_ANDROID
+  /* We specifically don't call pthread_atfork in jemalloc because it is not
+    available in bionic until 2.3. However without it, jemalloc could
+    potentially deadlock, when stl allocates memory through jemalloc, after
+    fork and before execvp. Therefore, we must manually inform jemalloc here */
+  ::_malloc_prefork();
+#endif
   pid_t pid = fork();
+#ifdef MOZ_MEMORY_ANDROID
+  ::_malloc_postfork();
+#endif
   if (pid < 0)
     return false;
 
   if (pid == 0) {
     InjectiveMultimap fd_shuffle;
     for (file_handle_mapping_vector::const_iterator
         it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) {
       fd_shuffle.push_back(InjectionArc(it->first, it->second, false));
--- a/memory/jemalloc/jemalloc.c
+++ b/memory/jemalloc/jemalloc.c
@@ -1261,18 +1261,23 @@ static void	*huge_palloc(size_t alignmen
 static void	*huge_ralloc(void *ptr, size_t size, size_t oldsize);
 static void	huge_dalloc(void *ptr);
 static void	malloc_print_stats(void);
 #ifndef MOZ_MEMORY_WINDOWS
 static
 #endif
 bool		malloc_init_hard(void);
 
+#ifdef MOZ_MEMORY_ANDROID
+void	_malloc_prefork(void);
+void	_malloc_postfork(void);
+#else
 static void	_malloc_prefork(void);
 static void	_malloc_postfork(void);
+#endif
 
 #ifdef MOZ_MEMORY_DARWIN
 /*
  * MALLOC_ZONE_T_NOTE
  *
  * On Darwin, we hook into the memory allocator using a malloc_zone_t struct.
  * We must be very careful around this struct because of different behaviour on
  * different versions of OSX.
@@ -5601,16 +5606,18 @@ MALLOC_OUT:
 #ifndef MOZ_MEMORY_WINDOWS
 		/* Print statistics at exit. */
 		atexit(malloc_print_stats);
 #endif
 	}
 
 #if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_MEMORY_ANDROID))
 	/* Prevent potential deadlock on malloc locks after fork. */
+	/* XXX on Android there is no pthread_atfork, so we specifically
+	   call _malloc_prefork and _malloc_postfork in process_util_linux.cc */
 	pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork);
 #endif
 
 	/* Set variables according to the value of opt_small_max_2pow. */
 	if (opt_small_max_2pow < opt_quantum_2pow)
 		opt_small_max_2pow = opt_quantum_2pow;
 	small_max = (1U << opt_small_max_2pow);
 
@@ -6431,17 +6438,21 @@ size_t
 /******************************************************************************/
 /*
  * Begin library-private functions, used by threading libraries for protection
  * of malloc during fork().  These functions are only called if the program is
  * running in threaded mode, so there is no need to check whether the program
  * is threaded here.
  */
 
+#ifdef MOZ_MEMORY_ANDROID
+void
+#else
 static void
+#endif
 _malloc_prefork(void)
 {
 	unsigned i;
 
 	/* Acquire all mutexes in a safe order. */
 
 	malloc_spin_lock(&arenas_lock);
 	for (i = 0; i < narenas; i++) {
@@ -6449,17 +6460,21 @@ static void
 			malloc_spin_lock(&arenas[i]->lock);
 	}
 
 	malloc_mutex_lock(&base_mtx);
 
 	malloc_mutex_lock(&huge_mtx);
 }
 
+#ifdef MOZ_MEMORY_ANDROID
+void
+#else
 static void
+#endif
 _malloc_postfork(void)
 {
 	unsigned i;
 
 	/* Release all mutexes, now that fork() has completed. */
 
 	malloc_mutex_unlock(&huge_mtx);