{"id":14590,"date":"2024-09-03T10:26:07","date_gmt":"2024-09-03T02:26:07","guid":{"rendered":"http:\/\/xinyiworld.top\/wordpress_it\/?p=14590"},"modified":"2024-09-11T16:11:03","modified_gmt":"2024-09-11T08:11:03","slug":"art-thread%e6%a8%a1%e5%9d%97%e4%bb%8b%e7%bb%8d","status":"publish","type":"post","link":"http:\/\/xinyiworld.top\/wordpress_it\/?p=14590","title":{"rendered":"art\/Thread\u7c7b\u4ecb\u7ecd"},"content":{"rendered":"<p>\u5934\u6587\u4ef6\uff1a<br \/>\n<code>art\/runtime\/thread.h<\/code><br \/>\n<code>art\/runtime\/thread-current-inl.h<\/code><\/p>\n<p>\u6e90\u6587\u4ef6:<code>art\/runtime\/thread.cc<\/code><\/p>\n<h2>\u91cd\u8981\u6570\u636e\u7ed3\u6784<\/h2>\n<ul>\n<li>\u7ed3\u6784\u4f53 tls_ptr_sized_values<br \/>\n\u5728thread.h\u4e2d\uff0c\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5341\u5206\u91cd\u8981\u7684tls_ptr_sized<em>values\u7c7b\u578b\u5168\u5c40\u53d8\u91cftlsPtr<\/em>,\u91cc\u9762\u8bb0\u5f55\u4e86\u5f88\u591a\u91cd\u8981\u7684\u6570\u636e\u3002<\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">struct PACKED(sizeof(void*)) tls_ptr_sized_values {\n    \/\/ Every thread may have an associated JNI environment\n    JNIEnvExt* jni_env;\n\n    \/\/ Initialized to &quot;this&quot;. On certain architectures (such as x86) reading off of Thread::Current\n    \/\/ is easy but getting the address of Thread::Current is hard. This field can be read off of\n    \/\/ Thread::Current to give the address.\n    Thread* self;\n}<\/code><\/pre>\n<h2>\u65b9\u6cd5<\/h2>\n<ul>\n<li>GetJniEnv<br \/>\n\u5b9a\u4e49\u4e0e\u5b9e\u73b0\uff1a<code>art\/runtime\/thread.h<\/code><\/li>\n<\/ul>\n<pre><code class=\"language-cpp\"> 534   \/\/ JNI methods\n 535   JNIEnvExt* GetJniEnv() const {\n 536     return tlsPtr_.jni_env;\n 537   }<\/code><\/pre>\n<p>tlsPtr_.jni_env\u662f\u5728Thread\u7684Init\u65b9\u6cd5\u4e2d\u8d4b\u503c\u7684\u3002<\/p>\n<ul>\n<li>CreateNativeThread \uff08\u521b\u5efanative\u7ebf\u7a0b\uff09<br \/>\n<code>Thread* child_thread = new Thread(is_daemon);<\/code><\/li>\n<\/ul>\n<p>\u901a\u8fc7jni\u88ab\u8c03\u7528<\/p>\n<pre><code class=\"language-cpp\">art\/runtime\/native\/java_lang_Thread.cc:61:  Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);\nart\/openjdkjvm\/OpenjdkJvm.cc:347:  art::Thread::CreateNativeThread(env, jthread, stack_size, daemon == JNI_TRUE);<\/code><\/pre>\n<ul>\n<li>Startup \uff08\u521b\u5efaTSD\u7684\u952e\uff09<br \/>\n\u5b9e\u73b0\u65b9\u6cd5\u4f4d\u4e8e\uff1a<code>art\/runtime\/thread.cc<\/code><\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">2212 void Thread::Startup() {\n2213   CHECK(!is_started_);\n2214   is_started_ = true;\n2215   {\n2216     \/\/ MutexLock to keep annotalysis happy.\n2217     \/\/\n2218     \/\/ Note we use null for the thread because Thread::Current can\n2219     \/\/ return garbage since (is_started_ == true) and\n2220     \/\/ Thread::pthread_key_self_ is not yet initialized.\n2221     \/\/ This was seen on glibc.\n2222     MutexLock mu(nullptr, *Locks::thread_suspend_count_lock_);\n2223     resume_cond_ = new ConditionVariable(&quot;Thread resumption condition variable&quot;,\n2224                                          *Locks::thread_suspend_count_lock_);\n2225   }\n2226 \n2227   \/\/ Allocate a TLS slot.\n2228   CHECK_PTHREAD_CALL(pthread_key_create, (&amp;Thread::pthread_key_self_, Thread::ThreadExitCallback),\n2229                      &quot;self key&quot;);\n2230 \n2231   \/\/ Double-check the TLS slot allocation.\n2232   if (pthread_getspecific(pthread_key_self_) != nullptr) {\n2233     LOG(FATAL) &lt;&lt; &quot;Newly-created pthread TLS slot is not nullptr&quot;;\n2234   }\n2235 }<\/code><\/pre>\n<p>\u88abRuntime\u5b9e\u4f8b\u7684Init\u65b9\u6cd5\u8c03\u7528,\u8be6\u89c1\uff1a<a href=\"http:\/\/xinyiworld.top\/wordpress_it\/?p=14578\">http:\/\/xinyiworld.top\/wordpress_it\/?p=14578<\/a><\/p>\n<blockquote>\n<p>\u4ee3\u7801\u89e3\u91ca<\/p>\n<\/blockquote>\n<pre><code class=\"language-cpp\">2228   CHECK_PTHREAD_CALL(pthread_key_create, (&amp;Thread::pthread_key_self_, Thread::ThreadExitCallback),\n2229                      &quot;self key&quot;);<\/code><\/pre>\n<p>CHECK_PTHREAD_CALL\u5b8f\u5b9a\u4e49\u5728<code>system\/core\/base\/include\/android-base\/logging.h<\/code> <\/p>\n<pre><code class=\"language-cpp\">325 \/\/ Perform the pthread function call(args), LOG(FATAL) on error.\n326 #define CHECK_PTHREAD_CALL(call, args, what)                           \\\n327   do {                                                                 \\\n328     int rc = call args;                                                \\\n329     if (rc != 0) {                                                     \\\n330       errno = rc;                                                      \\\n331       ABORT_AFTER_LOG_FATAL                                            \\\n332       PLOG(FATAL) &lt;&lt; #call &lt;&lt; &quot; failed for &quot; &lt;&lt; (what);                \\\n333     }                                                                  \\\n334   } while (false)<\/code><\/pre>\n<p>\u90a3\u4e48\u4ee5\u4e0a\u4ee3\u7801\u5c31\u7b49\u4e8e\u662f\u6267\u884c<code>pthread_key_create(&amp;Thread::pthread_key_self_, Thread::ThreadExitCallback)<\/code>\u65b9\u6cd5<\/p>\n<ul>\n<li>Current\uff08\u83b7\u53d6\u5f53\u524d\u7ebf\u7a0b\u5b9e\u4f8b\uff09<\/li>\n<\/ul>\n<p>\u5b9e\u73b0\u65b9\u6cd5\u4f4d\u4e8e<code>art\/runtime\/thread-current-inl.h<\/code><\/p>\n<pre><code class=\"language-cpp\"> 30 inline Thread* Thread::Current() {\n 31   \/\/ We rely on Thread::Current returning null for a detached thread, so it&#039;s not obvious\n 32   \/\/ that we can replace this with a direct %fs access on x86.\n 33   if (!is_started_) {\n 34     return nullptr;\n 35   } else {\n 36 #ifdef ART_TARGET_ANDROID\n 37     void* thread = __get_tls()[TLS_SLOT_ART_THREAD_SELF];\n 38 #else\n 39     void* thread = pthread_getspecific(Thread::pthread_key_self_);\n 40 #endif\n 41     return reinterpret_cast&lt;Thread*&gt;(thread);\n 42   }\n 43 }<\/code><\/pre>\n<ul>\n<li>Init<\/li>\n<\/ul>\n<blockquote>\n<p>\u5c06\u7ebf\u7a0b\u5b9e\u4f8b\u4e0e\u7ebf\u7a0b\u6570\u636e\u952e\u5173\u8054<\/p>\n<\/blockquote>\n<p>TLS_SLOT_ART_THREAD_SELF\u5b8f\u5b9a\u4e49\u5728<code>bionic\/libc\/private\/bionic_asm_tls.h:92:#define TLS_SLOT_ART_THREAD_SELF  7<\/code><\/p>\n<pre><code class=\"language-cpp\"> 935 #ifdef ART_TARGET_ANDROID\n 936   __get_tls()[TLS_SLOT_ART_THREAD_SELF] = this;\n 937 #else\n 938   CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, this), &quot;attach self&quot;);\n 939 #endif<\/code><\/pre>\n<p><code>__get_tls()<\/code>\u4e3a\u6c47\u7f16\u65b9\u6cd5\uff0c\u5b9a\u4e49\u5728<code>bionic\/libc\/private\/__get_tls.h<\/code>\u4e2d\u3002<\/p>\n<blockquote>\n<p>\u521b\u5efaJNIEnvExt\u5b9e\u4f8b<\/p>\n<\/blockquote>\n<p>1\uff09<br \/>\n\u5bf9tlsPtr_.jni_env\u8fdb\u884c\u4e86\u8d4b\u503c<code>tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm, &amp;error_msg);<\/code><br \/>\n2\uff09<br \/>\nInit\u65b9\u6cd5\u4f1a\u88ab <code>void* Thread::CreateCallback(void* arg) <\/code>\u548c<code>Thread* Thread::Attach(const char* thread_name, bool as_daemon, PeerAction peer_action) <\/code>\u65b9\u6cd5\u6240\u8c03\u7528\u3002<br \/>\n3\uff09<br \/>\nJNIEnvExt\u7c7b\u89c1 <a href=\"http:\/\/xinyiworld.top\/wordpress_it\/?p=14639\">http:\/\/xinyiworld.top\/wordpress_it\/?p=14639<\/a><\/p>\n<ul>\n<li>Attach<br \/>\n\u521b\u5efa\u8fd4\u56de\u4e00\u4e2a\u4e0e\u5f53\u524dart\u5173\u8054\u7684Thread\u5b9e\u4f8b<\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">\n962 template &lt;typename PeerAction&gt;\n 963 Thread* Thread::Attach(const char* thread_name, bool as_daemon, PeerAction peer_action) {\n 964   Runtime* runtime = Runtime::Current();\n...\n        \/\/\u521b\u5efaThread\u5b9e\u4f8b\uff08\u6ce8\u610f\u8fd9\u91cc\u5e76\u4e0d\u662f\u771f\u7684\u521b\u5efa\u4e86\u4e00\u4e2a\u7ebf\u7a0b\uff0c\u800c\u662f\u521b\u5efa\u4e86\u4e00\u4e2a\u7c7b\uff0c\u7528\u4e8e\u5c01\u88c5\u63cf\u8ff0\u5f53\u524d\u7ebf\u7a0b\u800c\u5df2\uff01\uff01\uff01\uff01\uff09\n 981       self = new Thread(as_daemon);\n 982       bool init_success = self-&gt;Init(runtime-&gt;GetThreadList(), runtime-&gt;GetJavaVM());\n\n 996   \/\/ Run the action that is acting on the peer.\n 997   if (!peer_action(self)) {\n 998     runtime-&gt;GetThreadList()-&gt;Unregister(self);\n 999     \/\/ Unregister deletes self, no need to do this here.\n1000     return nullptr;\n1001   }\n...\n1018   return self;\n1019 }\n\n1021 Thread* Thread::Attach(const char* thread_name,\n1022                        bool as_daemon,\n1023                        jobject thread_group,\n1024                        bool create_peer) {\n        \/\/\u533f\u540d\u51fd\u6570\n1025   auto create_peer_action = [&amp;](Thread* self) {\n1026     \/\/ If we&#039;re the main thread, ClassLinker won&#039;t be created until after we&#039;re attached,\n1027     \/\/ so that thread needs a two-stage attach. Regular threads don&#039;t need this hack.\n1028     \/\/ In the compiler, all threads need this hack, because no-one&#039;s going to be getting\n1029     \/\/ a native peer!\n1030     if (create_peer) {\n1031       self-&gt;CreatePeer(thread_name, as_daemon, thread_group);\n1032       if (self-&gt;IsExceptionPending()) {\n1033         \/\/ We cannot keep the exception around, as we&#039;re deleting self. Try to be helpful and log\n1034         \/\/ it.\n1035         {\n1036           ScopedObjectAccess soa(self);\n1037           LOG(ERROR) &lt;&lt; &quot;Exception creating thread peer:&quot;;\n1038           LOG(ERROR) &lt;&lt; self-&gt;GetException()-&gt;Dump();\n1039           self-&gt;ClearException();\n1040         }\n1041         return false;\n1042       }\n1043     } else {\n1044       \/\/ These aren&#039;t necessary, but they improve diagnostics for unit tests &amp; command-line tools.\n1045       if (thread_name != nullptr) {\n1046         self-&gt;tlsPtr_.name-&gt;assign(thread_name);\n1047         ::art::SetThreadName(thread_name);\n1048       } else if (self-&gt;GetJniEnv()-&gt;IsCheckJniEnabled()) {\n1049         LOG(WARNING) &lt;&lt; *Thread::Current() &lt;&lt; &quot; attached without supplying a name&quot;;\n1050       }\n1051     }\n1052     return true;\n1053   };\n1054   return Attach(thread_name, as_daemon, create_peer_action);\n1055 }<\/code><\/pre>\n<p>\u89c1<a href=\"http:\/\/xinyiworld.top\/wordpress_it\/?p=14578\">http:\/\/xinyiworld.top\/wordpress_it\/?p=14578<\/a>\uff0cAttach\u65b9\u6cd5\u4f1a\u88abRuntime\u7684Init\u65b9\u6cd5\u8c03\u7528\u3002<\/p>\n<button class=\"simplefavorite-button\" data-postid=\"14590\" data-siteid=\"1\" data-groupid=\"1\" data-favoritecount=\"0\" style=\"\">\u6536\u85cf <i class=\"sf-icon-star-empty\"><\/i><\/button>","protected":false},"excerpt":{"rendered":"<p>\u5934\u6587\u4ef6\uff1a art\/runtime\/thread.h art\/runtime\/thread-curre [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1123],"tags":[],"_links":{"self":[{"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=\/wp\/v2\/posts\/14590"}],"collection":[{"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=14590"}],"version-history":[{"count":30,"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=\/wp\/v2\/posts\/14590\/revisions"}],"predecessor-version":[{"id":14743,"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=\/wp\/v2\/posts\/14590\/revisions\/14743"}],"wp:attachment":[{"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14590"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14590"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/xinyiworld.top\/wordpress_it\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14590"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}