summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Scott <phanna@android.com>2010-12-15 15:24:28 -0500
committerPatrick Scott <phanna@android.com>2010-12-16 09:45:03 -0500
commit6549a5990c7b8672bd9d216ffb55d8a7a5999cc2 (patch)
tree36fc199194840975d64adebada5e23ee871a01b5
parent01ba86dc3bae37426ebafbdd93640dc50c45e3e0 (diff)
downloadexternal_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
-rw-r--r--base/thread.cc24
-rw-r--r--base/thread.h6
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_;