am 5ca7d87f: am f1f150d0: am 0c863cb5: Merge "Refactor to share map_info amongst threads."

* commit '5ca7d87fe47ad18594b5c5f79d00aa86ed1435cb':
  Refactor to share map_info amongst threads.
diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c
index aa63547..1b08e8e 100644
--- a/debuggerd/tombstone.c
+++ b/debuggerd/tombstone.c
@@ -415,7 +415,7 @@
 
 /* Return true if some thread is not detached cleanly */
 static bool dump_sibling_thread_report(
-        log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec) {
+        log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec, backtrace_map_info_t* map_info) {
     char task_path[64];
     snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
 
@@ -449,7 +449,7 @@
         _LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
         dump_thread_info(log, pid, new_tid, 0);
         backtrace_context_t new_context;
-        if (backtrace_create_context(&new_context, pid, new_tid, 0)) {
+        if (backtrace_create_context_with_map(&new_context, pid, new_tid, 0, map_info)) {
             dump_thread(&new_context, log, 0, total_sleep_time_usec);
             backtrace_destroy_context(&new_context);
         }
@@ -676,7 +676,9 @@
     }
 
     backtrace_context_t context;
-    if (backtrace_create_context(&context, pid, tid, 0)) {
+    /* Gather the map info once for all this process' threads. */
+    backtrace_map_info_t* map_info = backtrace_create_map_info_list(pid);
+    if (backtrace_create_context_with_map(&context, pid, tid, 0, map_info)) {
         dump_abort_message(&context, log, abort_msg_address);
         dump_thread(&context, log, SCOPE_AT_FAULT, total_sleep_time_usec);
         backtrace_destroy_context(&context);
@@ -688,9 +690,12 @@
 
     bool detach_failed = false;
     if (dump_sibling_threads) {
-        detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec);
+        detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec, map_info);
     }
 
+    /* Destroy the previously created map info. */
+    backtrace_destroy_map_info_list(map_info);
+
     if (want_logs) {
         dump_logs(log, pid, false);
     }
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index b15678c..bf4efd3 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -33,7 +33,9 @@
   // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
   // different process.
   // Tracing a thread in a different process is not supported.
-  static Backtrace* Create(pid_t pid, pid_t tid);
+  // If map_info is NULL, then create the map and manage it internally.
+  // If map_info is not NULL, the map is still owned by the caller.
+  static Backtrace* Create(pid_t pid, pid_t tid, backtrace_map_info_t* map_info = NULL);
 
   virtual ~Backtrace();
 
@@ -70,7 +72,7 @@
   }
 
 protected:
-  Backtrace(BacktraceImpl* impl);
+  Backtrace(BacktraceImpl* impl, pid_t pid, backtrace_map_info_t* map_info);
 
   virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value);
 
@@ -78,6 +80,8 @@
 
   backtrace_map_info_t* map_info_;
 
+  bool map_info_requires_delete_;
+
   backtrace_t backtrace_;
 
   friend class BacktraceImpl;
diff --git a/include/backtrace/backtrace.h b/include/backtrace/backtrace.h
index 8a45690..186d327 100644
--- a/include/backtrace/backtrace.h
+++ b/include/backtrace/backtrace.h
@@ -73,6 +73,14 @@
 bool backtrace_create_context(
     backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames);
 
+/* The same as backtrace_create_context, except that it is assumed that
+ * the pid map has already been acquired and the caller will handle freeing
+ * the map data.
+ */
+bool backtrace_create_context_with_map(
+    backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames,
+    backtrace_map_info_t* map_info);
+
 /* Gather the backtrace data for a pthread instead of a process. */
 bool backtrace_create_thread_context(
     backtrace_context_t* context, pid_t tid, size_t num_ignore_frames);
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index b22d301..ccfce81 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -42,11 +42,18 @@
 //-------------------------------------------------------------------------
 // Backtrace functions.
 //-------------------------------------------------------------------------
-Backtrace::Backtrace(BacktraceImpl* impl) : impl_(impl), map_info_(NULL) {
+Backtrace::Backtrace(BacktraceImpl* impl, pid_t pid, backtrace_map_info_t* map_info)
+    : impl_(impl), map_info_(map_info), map_info_requires_delete_(false) {
   impl_->SetParent(this);
   backtrace_.num_frames = 0;
-  backtrace_.pid = -1;
+  backtrace_.pid = pid;
   backtrace_.tid = -1;
+
+  if (map_info_ == NULL) {
+    // Create the map and manage it internally.
+    map_info_ = backtrace_create_map_info_list(pid);
+    map_info_requires_delete_ = true;
+  }
 }
 
 Backtrace::~Backtrace() {
@@ -57,7 +64,7 @@
     }
   }
 
-  if (map_info_) {
+  if (map_info_ && map_info_requires_delete_) {
     backtrace_destroy_map_info_list(map_info_);
     map_info_ = NULL;
   }
@@ -151,8 +158,8 @@
 //-------------------------------------------------------------------------
 // BacktraceCurrent functions.
 //-------------------------------------------------------------------------
-BacktraceCurrent::BacktraceCurrent(BacktraceImpl* impl) : Backtrace(impl) {
-  map_info_ = backtrace_create_map_info_list(-1);
+BacktraceCurrent::BacktraceCurrent(
+    BacktraceImpl* impl, backtrace_map_info_t *map_info) : Backtrace(impl, getpid(), map_info) {
 
   backtrace_.pid = getpid();
 }
@@ -179,11 +186,9 @@
 //-------------------------------------------------------------------------
 // BacktracePtrace functions.
 //-------------------------------------------------------------------------
-BacktracePtrace::BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid)
-    : Backtrace(impl) {
-  map_info_ = backtrace_create_map_info_list(tid);
-
-  backtrace_.pid = pid;
+BacktracePtrace::BacktracePtrace(
+    BacktraceImpl* impl, pid_t pid, pid_t tid, backtrace_map_info_t* map_info)
+    : Backtrace(impl, pid, map_info) {
   backtrace_.tid = tid;
 }
 
@@ -212,26 +217,27 @@
 #endif
 }
 
-Backtrace* Backtrace::Create(pid_t pid, pid_t tid) {
+Backtrace* Backtrace::Create(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
   if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) {
     if (tid == BACKTRACE_NO_TID || tid == gettid()) {
-      return CreateCurrentObj();
+      return CreateCurrentObj(map_info);
     } else {
-      return CreateThreadObj(tid);
+      return CreateThreadObj(tid, map_info);
     }
   } else if (tid == BACKTRACE_NO_TID) {
-    return CreatePtraceObj(pid, pid);
+    return CreatePtraceObj(pid, pid, map_info);
   } else {
-    return CreatePtraceObj(pid, tid);
+    return CreatePtraceObj(pid, tid, map_info);
   }
 }
 
 //-------------------------------------------------------------------------
 // Common interface functions.
 //-------------------------------------------------------------------------
-bool backtrace_create_context(
-    backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames) {
-  Backtrace* backtrace = Backtrace::Create(pid, tid);
+bool backtrace_create_context_with_map(
+    backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames,
+    backtrace_map_info_t* map_info) {
+  Backtrace* backtrace = Backtrace::Create(pid, tid, map_info);
   if (!backtrace) {
     return false;
   }
@@ -245,6 +251,12 @@
   return true;
 }
 
+bool backtrace_create_context(
+    backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames) {
+  return backtrace_create_context_with_map(context, pid, tid, num_ignore_frames, NULL);
+}
+
+
 void backtrace_destroy_context(backtrace_context_t* context) {
   if (context->data) {
     Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
diff --git a/libbacktrace/Backtrace.h b/libbacktrace/Backtrace.h
index 00f0a10..d741ef1 100644
--- a/libbacktrace/Backtrace.h
+++ b/libbacktrace/Backtrace.h
@@ -45,7 +45,7 @@
 
 class BacktraceCurrent : public Backtrace {
 public:
-  BacktraceCurrent(BacktraceImpl* impl);
+  BacktraceCurrent(BacktraceImpl* impl, backtrace_map_info_t* map_info);
   virtual ~BacktraceCurrent();
 
   bool ReadWord(uintptr_t ptr, uint32_t* out_value);
@@ -53,14 +53,14 @@
 
 class BacktracePtrace : public Backtrace {
 public:
-  BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid);
+  BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, backtrace_map_info_t* map_info);
   virtual ~BacktracePtrace();
 
   bool ReadWord(uintptr_t ptr, uint32_t* out_value);
 };
 
-Backtrace* CreateCurrentObj();
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid);
-Backtrace* CreateThreadObj(pid_t tid);
+Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info);
+Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info);
+Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info);
 
 #endif // _LIBBACKTRACE_BACKTRACE_H
diff --git a/libbacktrace/BacktraceThread.cpp b/libbacktrace/BacktraceThread.cpp
index 8e664c4..70616b0 100644
--- a/libbacktrace/BacktraceThread.cpp
+++ b/libbacktrace/BacktraceThread.cpp
@@ -114,8 +114,9 @@
 }
 
 BacktraceThread::BacktraceThread(
-    BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid)
-    : BacktraceCurrent(impl), thread_intf_(thread_intf) {
+    BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid,
+    backtrace_map_info_t* map_info)
+    : BacktraceCurrent(impl, map_info), thread_intf_(thread_intf) {
   backtrace_.tid = tid;
 }
 
diff --git a/libbacktrace/BacktraceThread.h b/libbacktrace/BacktraceThread.h
index 8ed1122..bcb56c9 100644
--- a/libbacktrace/BacktraceThread.h
+++ b/libbacktrace/BacktraceThread.h
@@ -71,7 +71,8 @@
   // the compiler to catch if an implementation does not properly
   // subclass both.
   BacktraceThread(
-      BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid);
+      BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid,
+      backtrace_map_info_t* map_info);
   virtual ~BacktraceThread();
 
   virtual bool Unwind(size_t num_ignore_frames);
diff --git a/libbacktrace/Corkscrew.cpp b/libbacktrace/Corkscrew.cpp
index 2be5930..eae13c6 100644
--- a/libbacktrace/Corkscrew.cpp
+++ b/libbacktrace/Corkscrew.cpp
@@ -204,15 +204,15 @@
 //-------------------------------------------------------------------------
 // C++ object creation functions.
 //-------------------------------------------------------------------------
-Backtrace* CreateCurrentObj() {
-  return new BacktraceCurrent(new CorkscrewCurrent());
+Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info) {
+  return new BacktraceCurrent(new CorkscrewCurrent(), map_info);
 }
 
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid) {
-  return new BacktracePtrace(new CorkscrewPtrace(), pid, tid);
+Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
+  return new BacktracePtrace(new CorkscrewPtrace(), pid, tid, map_info);
 }
 
-Backtrace* CreateThreadObj(pid_t tid) {
+Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info) {
   CorkscrewThread* thread_obj = new CorkscrewThread();
-  return new BacktraceThread(thread_obj, thread_obj, tid);
+  return new BacktraceThread(thread_obj, thread_obj, tid, map_info);
 }
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
index 6c0cad6..94a82fe 100644
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -194,11 +194,11 @@
 //-------------------------------------------------------------------------
 // C++ object creation function.
 //-------------------------------------------------------------------------
-Backtrace* CreateCurrentObj() {
-  return new BacktraceCurrent(new UnwindCurrent());
+Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info) {
+  return new BacktraceCurrent(new UnwindCurrent(), map_info);
 }
 
-Backtrace* CreateThreadObj(pid_t tid) {
+Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info) {
   UnwindThread* thread_obj = new UnwindThread();
-  return new BacktraceThread(thread_obj, thread_obj, tid);
+  return new BacktraceThread(thread_obj, thread_obj, tid, map_info);
 }
diff --git a/libbacktrace/UnwindPtrace.cpp b/libbacktrace/UnwindPtrace.cpp
index a734a24..7a9bbdd 100644
--- a/libbacktrace/UnwindPtrace.cpp
+++ b/libbacktrace/UnwindPtrace.cpp
@@ -131,6 +131,6 @@
 //-------------------------------------------------------------------------
 // C++ object creation function.
 //-------------------------------------------------------------------------
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid) {
-  return new BacktracePtrace(new UnwindPtrace(), pid, tid);
+Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
+  return new BacktracePtrace(new UnwindPtrace(), pid, tid, map_info);
 }