diff options
author | Patrick Scott <phanna@android.com> | 2010-12-15 15:24:28 -0500 |
---|---|---|
committer | Patrick Scott <phanna@android.com> | 2010-12-16 09:45:03 -0500 |
commit | 6549a5990c7b8672bd9d216ffb55d8a7a5999cc2 (patch) | |
tree | 36fc199194840975d64adebada5e23ee871a01b5 /base | |
parent | 01ba86dc3bae37426ebafbdd93640dc50c45e3e0 (diff) | |
download | external_chromium-6549a5990c7b8672bd9d216ffb55d8a7a5999cc2.zip external_chromium-6549a5990c7b8672bd9d216ffb55d8a7a5999cc2.tar.gz external_chromium-6549a5990c7b8672bd9d216ffb55d8a7a5999cc2.tar.bz2 |
Guard startup_data_ to ensure it is set.
On SMP systems, instructions can be reordered such that the new thread executes
before startup_data_ has been written. Use a mutex to ensure instruction order
and to force startup_data_ to be flushed. This fixes spurious crashes when
starting the browser.
Bug: 3291265
Change-Id: Idb29cda6e03d01d42781284d5a9545486ee92bc8
Diffstat (limited to 'base')
-rw-r--r-- | base/thread.cc | 24 | ||||
-rw-r--r-- | base/thread.h | 6 |
2 files changed, 30 insertions, 0 deletions
diff --git a/base/thread.cc b/base/thread.cc index 41d78f0..e397be6 100644 --- a/base/thread.cc +++ b/base/thread.cc @@ -81,7 +81,16 @@ bool Thread::StartWithOptions(const Options& options) { SetThreadWasQuitProperly(false); StartupData startup_data(options); +#ifdef ANDROID + { + // Use a lock to issue a cpu barrier and force the new thread to load + // startup_data_. + AutoLock lock(startup_data_lock_); + startup_data_ = &startup_data; + } +#else startup_data_ = &startup_data; +#endif if (!PlatformThread::Create(options.stack_size, this, &thread_)) { DLOG(ERROR) << "failed to create thread"; @@ -142,8 +151,19 @@ void Thread::Run(MessageLoop* message_loop) { void Thread::ThreadMain() { { +#ifdef ANDROID + StartupData* startup_data = NULL; + { + // Use a lock to ensure startup_data_ has been written. + AutoLock lock(startup_data_lock_); + startup_data = startup_data_; + } + // The message loop for this thread. + MessageLoop message_loop(startup_data->options.message_loop_type); +#else // The message loop for this thread. MessageLoop message_loop(startup_data_->options.message_loop_type); +#endif // Complete the initialization of our Thread object. thread_id_ = PlatformThread::CurrentId(); @@ -157,7 +177,11 @@ void Thread::ThreadMain() { // Let's do this before signaling we are started. Init(); +#ifdef ANDROID + startup_data->event.Signal(); +#else startup_data_->event.Signal(); +#endif // startup_data_ can't be touched anymore since the starting thread is now // unlocked. diff --git a/base/thread.h b/base/thread.h index 572eb8a..870a985 100644 --- a/base/thread.h +++ b/base/thread.h @@ -8,6 +8,9 @@ #include <string> +#ifdef ANDROID +#include "base/lock.h" +#endif #include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/platform_thread.h" @@ -165,6 +168,9 @@ class Thread : PlatformThread::Delegate { bool stopping_; // Used to pass data to ThreadMain. +#ifdef ANDROID + Lock startup_data_lock_; // protects startup_data_ +#endif struct StartupData; StartupData* startup_data_; |