Przeglądaj źródła

pipeline: Fixes for fragile TLS implementation on Android

rdb 1 miesiąc temu
rodzic
commit
418d041252

+ 6 - 0
panda/src/pipeline/threadPosixImpl.I

@@ -46,8 +46,14 @@ prepare_for_exit() {
 INLINE Thread *ThreadPosixImpl::
 get_current_thread() {
   TAU_PROFILE("Thread *ThreadPosixImpl::get_current_thread()", " ", TAU_USER);
+#ifdef ANDROID
+  // Android doesn't correctly share TLS variables across multiple DSOs, so
+  // we can't inline this.
+  return do_get_current_thread();
+#else
   Thread *thread = _current_thread;
   return (thread != nullptr) ? thread : init_current_thread();
+#endif
 }
 
 /**

+ 25 - 1
panda/src/pipeline/threadPosixImpl.cxx

@@ -33,7 +33,12 @@
 static JavaVM *java_vm = nullptr;
 #endif
 
+// See comment in header file.
+#ifdef ANDROID
+static __thread Thread *_current_thread = nullptr;
+#else
 __thread Thread *ThreadPosixImpl::_current_thread = nullptr;
+#endif
 static patomic_flag _main_thread_known = ATOMIC_FLAG_INIT;
 
 /**
@@ -53,6 +58,10 @@ ThreadPosixImpl::
     _detached = true;
   }
 
+  if (_current_thread == _parent_obj) {
+    _current_thread = nullptr;
+  }
+
   _mutex.unlock();
 }
 
@@ -332,7 +341,9 @@ root_func(void *data) {
 #ifdef ANDROID
     // We cannot let the thread end without detaching it.
     if (self->_jni_env != nullptr) {
-      java_vm->DetachCurrentThread();
+      if (java_vm != nullptr) {
+        java_vm->DetachCurrentThread();
+      }
       self->_jni_env = nullptr;
     }
 #endif
@@ -341,6 +352,8 @@ root_func(void *data) {
     // might delete the parent object, and in turn, delete the ThreadPosixImpl
     // object.
     unref_delete(self->_parent_obj);
+
+    _current_thread = nullptr;
   }
 
   return nullptr;
@@ -360,6 +373,17 @@ init_current_thread() {
   return thread;
 }
 
+#ifdef ANDROID
+/**
+ *
+ */
+Thread *ThreadPosixImpl::
+do_get_current_thread() {
+  Thread *thread = _current_thread;
+  return (thread != nullptr) ? thread : init_current_thread();
+}
+#endif  // ANDROID
+
 #ifdef ANDROID
 /**
  * Called by Java when loading this library from the Java virtual machine.

+ 9 - 1
panda/src/pipeline/threadPosixImpl.h

@@ -48,7 +48,7 @@ public:
 
   INLINE static void prepare_for_exit();
 
-  INLINE static Thread *get_current_thread();
+  static Thread *get_current_thread();
   static Thread *bind_thread(Thread *thread);
   INLINE static bool is_threading_supported();
   INLINE static bool is_true_threads();
@@ -69,6 +69,10 @@ private:
   static void *root_func(void *data);
   static Thread *init_current_thread();
 
+#ifdef ANDROID
+  static Thread *do_get_current_thread();
+#endif
+
   // There appears to be a name collision with the word "Status".
   enum PStatus {
     S_new,
@@ -88,7 +92,11 @@ private:
   JNIEnv *_jni_env;
 #endif
 
+  // Android doesn't do TLS correctly across .so boundaries, so we hide the
+  // current thread in the .cxx file.
+#ifndef ANDROID
   static __thread Thread *_current_thread;
+#endif
 };
 
 #include "threadPosixImpl.I"

+ 2 - 1
pandatool/src/deploy-stub/android_main.cxx

@@ -118,7 +118,8 @@ void android_main(struct android_app *app) {
   PT(Thread) current_thread = Thread::bind_thread(thread_name, "android_app");
 
   android_cat.info()
-    << "New native activity started on " << *current_thread << "\n";
+    << "New native activity started on " << *current_thread
+    << " (" << current_thread << ")\n";
 
   // Fetch the data directory.
   jmethodID get_appinfo = env->GetMethodID(activity_class, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");