Updated to arc-runtime-45.5021.433.7
diff --git a/mods/android/bionic/config.py b/mods/android/bionic/config.py
index 49c68cd..de8d08f 100755
--- a/mods/android/bionic/config.py
+++ b/mods/android/bionic/config.py
@@ -133,6 +133,8 @@
   if OPTIONS.is_bare_metal_build():
     # For direct syscalls used internally.
     sources.append('android/bionic/libc/arch-x86/bionic/syscall.S')
+    # For saving register context for waiting threads.
+    sources.append('android/bionic/libc/arch-x86/bionic/save_reg_context.S')
   else:
     # See the comment in _filter_libc_common_for_arm.
     # TODO(crbug.com/318433): Use order-only dependencies.
@@ -158,7 +160,7 @@
       # As we support ARM NDKs even on NaCl x86-64, we provide legacy
       # APIs.
       'android/bionic/libc/bionic/legacy_32_bit_support.cpp'])
-  sources.append('android/bionic/libc/arch-amd64/bionic/save_reg_context.S')
+  sources.append('android/bionic/libc/arch-x86_64/bionic/save_reg_context.S')
 
 
 def _remove_unnecessary_defines(vars):
@@ -1472,7 +1474,7 @@
       _BIONIC_TEST_LIB_MODULES + ['no-elf-hash-table-library']]
 
   test_binary = n.link(variables={'ldflags': ldflags})
-  n.add_disabled_tests('pthread_thread_context.*')
+  n.add_disabled_tests('PthreadThreadContext*.*')
   n.run(test_binary, implicit=test_deps)
 
   # pthread_context_test should run only with a single thread. As
@@ -1480,7 +1482,7 @@
   # result of this test, we use a separate TestNinjaGenerator for this
   # test.
   n = ninja_generator.TestNinjaGenerator('bionic_pthread_context_test')
-  n.add_enabled_tests('pthread_thread_context.*')
+  n.add_enabled_tests('PthreadThreadContext*.*')
   n.run(test_binary, implicit=test_deps)
 
   # Build the shared object for dlfcn.dlopen_library_with_only_gnu_hash.
diff --git a/mods/android/bionic/libc/arch-nacl/syscalls/thread_context.h b/mods/android/bionic/libc/arch-nacl/syscalls/thread_context.h
index a2d92ab..b3fc0a3 100644
--- a/mods/android/bionic/libc/arch-nacl/syscalls/thread_context.h
+++ b/mods/android/bionic/libc/arch-nacl/syscalls/thread_context.h
@@ -40,6 +40,18 @@
     __pthread_save_context_regs(regs_tmp, sizeof(regs_tmp));    \
   }
 
+#elif defined(__i386__) && !defined(__native_client__)
+
+extern void BionicInternalSaveRegContext(uint32_t*);
+
+#define SAVE_CONTEXT_REGS()                                     \
+  {                                                             \
+    uint32_t regs_tmp[15];                                      \
+    BionicInternalSaveRegContext(regs_tmp);                     \
+    __pthread_save_context_regs(regs_tmp, sizeof(regs_tmp));    \
+  }
+
+
 #elif defined(__arm__)
 
 #ifndef __thumb__
diff --git a/mods/android/bionic/libc/arch-x86/bionic/save_reg_context.S b/mods/android/bionic/libc/arch-x86/bionic/save_reg_context.S
new file mode 100644
index 0000000..895e0e7
--- /dev/null
+++ b/mods/android/bionic/libc/arch-x86/bionic/save_reg_context.S
@@ -0,0 +1,58 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+.macro store_reg x, y
+  movl \x, \y(%edi)
+.endm
+
+// void BionicInternalSaveRegContext(uint32_t[15])
+// Saves register context necessary for traversing the stack in a minidump.
+.global BionicInternalSaveRegContext
+.type BionicInternalSaveRegContext, @function
+BionicInternalSaveRegContext:
+  .cfi_startproc
+  pushl %edi
+  .cfi_adjust_cfa_offset 4
+  mov 8(%esp), %edi
+
+  // The ordering matches the one specified in ucontext.h.
+  // We're not efficient here because first four registers are segment registers.
+  store_reg %esi,  0x14
+  store_reg %ebp,  0x18
+  store_reg %ebx,  0x20
+  store_reg %edx,  0x24
+  store_reg %ecx,  0x28
+  store_reg %eax,  0x2c
+
+  // edi
+  mov 0(%esp), %eax
+  store_reg %eax,  0x10
+
+  // Store caller's ESP.
+  // Hmm... really?
+  leal 8(%esp), %eax
+  store_reg %eax, 0x1c
+
+  // Store caller's EIP.
+  movl 4(%esp), %eax
+  store_reg %eax, 0x38
+
+  popl %edi
+  .cfi_adjust_cfa_offset -4
+  ret
+
+  .cfi_endproc
+  .size BionicInternalSaveRegContext, . - BionicInternalSaveRegContext
+
+.section .note.GNU-stack, "", @progbits
diff --git a/mods/android/bionic/libc/arch-amd64/bionic/save_reg_context.S b/mods/android/bionic/libc/arch-x86_64/bionic/save_reg_context.S
similarity index 100%
rename from mods/android/bionic/libc/arch-amd64/bionic/save_reg_context.S
rename to mods/android/bionic/libc/arch-x86_64/bionic/save_reg_context.S
diff --git a/mods/android/bionic/libc/bionic/pthread_context.cpp b/mods/android/bionic/libc/bionic/pthread_context.cpp
index 1f036e6..26fc429 100644
--- a/mods/android/bionic/libc/bionic/pthread_context.cpp
+++ b/mods/android/bionic/libc/bionic/pthread_context.cpp
@@ -25,16 +25,24 @@
 extern "C" {
 
 void __pthread_save_context_regs(void* regs, int size) {
+  // Not yet supported for nacl-i686.
+#if defined(__x86_64__) || defined(__arm__) ||          \
+  (defined(__i386__) && !defined(__native_client__))
     pthread_internal_t* thread = __get_thread();
     memcpy(thread->context_regs, regs, size);
     thread->has_context_regs = 1;
     ANDROID_MEMBAR_FULL();
+#endif
 }
 
 void __pthread_clear_context_regs() {
+  // Not yet supported for nacl-i686.
+#if defined(__x86_64__) || defined(__arm__) || \
+  (defined(__i386__) && !defined(__native_client__))
     pthread_internal_t* thread = __get_thread();
     thread->has_context_regs = 0;
     ANDROID_MEMBAR_FULL();
+#endif
 }
 
 static bool obtain_lock(bool try_lock) {
@@ -87,15 +95,18 @@
     dst->stack_base = src->stack_end_from_irt - kIrtStackSize;
     dst->stack_size = kIrtStackSize;
   }
-  #else
+#else
   if (src->attr.stack_base) {
             dst->stack_base =
                 reinterpret_cast<char*>(src->attr.stack_base) +
                 src->attr.guard_size;
             dst->stack_size = src->attr.stack_size - src->attr.guard_size;
   }
-  #endif
+#endif
 
+  // Not yet supported for nacl-i686.
+#if defined(__x86_64__) || defined(__arm__) || \
+  (defined(__i386__) && !defined(__native_client__))
   // Copy registers, then do a second (racy) read of has_context_regs.
   if (src->has_context_regs) {
     memcpy(dst->context_regs, src->context_regs,
@@ -103,6 +114,7 @@
     ANDROID_MEMBAR_FULL();
     dst->has_context_regs = src->has_context_regs;
   }
+#endif
 }
 
 void __pthread_get_current_thread_info(__pthread_context_info_t* info) {
diff --git a/mods/android/bionic/libc/bionic/pthread_internal.h b/mods/android/bionic/libc/bionic/pthread_internal.h
index f617c5e..a0fa25b 100644
--- a/mods/android/bionic/libc/bionic/pthread_internal.h
+++ b/mods/android/bionic/libc/bionic/pthread_internal.h
@@ -96,7 +96,10 @@
   // ARC MOD BEGIN bionic-thread-info
   // Storage for thread context at the time of invoking a blocking call.
   volatile bool has_context_regs;
+#if defined(__x86_64__) || defined(__arm__) || \
+  (defined(__i386__) && !defined(__native_client__))
   greg_t context_regs[NGREG];
+#endif
   // ARC MOD END
 
   pthread_mutex_t startup_handshake_mutex;
diff --git a/mods/android/bionic/tests/pthread_context_test.cpp b/mods/android/bionic/tests/pthread_context_test.cpp
index 0a8bb73..0fc6508 100644
--- a/mods/android/bionic/tests/pthread_context_test.cpp
+++ b/mods/android/bionic/tests/pthread_context_test.cpp
@@ -20,80 +20,135 @@
 #include <private/pthread_context.h>
 #include <thread_context.h>
 
-struct Args {
-  Args()
-      : has_started(false),
-        should_exit(false) {
-    pthread_mutex_init(&mu, NULL);
-    pthread_cond_init(&cond, NULL);
-  }
-  ~Args() {
-    pthread_cond_destroy(&cond);
-    pthread_mutex_destroy(&mu);
+namespace {
+
+// Tests that need to create a thread and be cleaned up later.
+class PthreadThreadContextThreadTest : public testing::Test {
+ public:
+  PthreadThreadContextThreadTest()
+      : thread_(), thread_has_started_(false),
+        thread_should_exit_(false) {
+    pthread_mutex_init(&mu_, NULL);
+    pthread_cond_init(&cond_, NULL);
   }
 
-  bool has_started;
-  bool should_exit;
-  pthread_mutex_t mu;
-  pthread_cond_t cond;
+  virtual ~PthreadThreadContextThreadTest() {
+    pthread_cond_destroy(&cond_);
+    pthread_mutex_destroy(&mu_);
+  }
+
+  virtual void SetUp() {
+    ASSERT_EQ(1, __pthread_get_thread_count(true));
+
+    // Create a new thread and wait until it goes into futex_wait loop,
+    // which is instrumented to export thread context information.
+    {
+      ScopedPthreadMutexLocker lock(&mu_);
+      ASSERT_EQ(0, pthread_create(&thread_, NULL, WaitFn, this));
+      while (!thread_has_started_)
+        pthread_cond_wait(&cond_, &mu_);
+    }
+  }
+
+  virtual void TearDown() {
+    // Let the thread finish.
+    {
+      ScopedPthreadMutexLocker lock(&mu_);
+      thread_should_exit_ = true;
+      pthread_cond_signal(&cond_);
+    }
+    pthread_join(thread_, NULL);
+  }
+
+
+  static void* WaitFn(void* arg) {
+    PthreadThreadContextThreadTest* self =
+        static_cast<PthreadThreadContextThreadTest*>(arg);
+    {
+      ScopedPthreadMutexLocker lock(&self->mu_);
+      self->thread_has_started_ = true;
+      pthread_cond_signal(&self->cond_);
+
+      while (!self->thread_should_exit_)
+        pthread_cond_wait(&self->cond_, &self->mu_);
+    }
+    return NULL;
+  }
+
+  static bool HasContextRegs() {
+    __pthread_context_info_t info;
+    info.has_context_regs = true;
+    __pthread_get_current_thread_info(&info);
+    return info.has_context_regs;
+  }
+
+ protected:
+  pthread_t thread_;
+  bool thread_has_started_;
+  bool thread_should_exit_;
+  pthread_mutex_t mu_;
+  pthread_cond_t cond_;
 };
 
-static void* WaitFn(void* arg) {
-  Args* args = static_cast<Args*>(arg);
-  {
-    ScopedPthreadMutexLocker lock(&args->mu);
-    args->has_started = true;
-    pthread_cond_signal(&args->cond);
-
-    while (!args->should_exit)
-      pthread_cond_wait(&args->cond, &args->mu);
+TEST_F(PthreadThreadContextThreadTest, get_thread_infos) {
+  // Verify data in the thread list.
+  __pthread_context_info_t infos[100];
+  int thread_count = __pthread_get_thread_infos(true, true, 100, infos);
+  ASSERT_EQ(2, thread_count);
+  for (int i = 0; i < thread_count; ++i) {
+    SCOPED_TRACE(i);
+    ASSERT_TRUE(infos[i].stack_base != NULL);
+    EXPECT_GT(infos[i].stack_size, 0);
+#if defined(BARE_METAL_BIONIC)
+    ASSERT_EQ(infos[i].stack_size, 1024 * 1024);
+#endif
   }
-  return NULL;
 }
 
-TEST(pthread_thread_context, get_thread_infos) {
-  ASSERT_EQ(1, __pthread_get_thread_count(true));
+TEST_F(PthreadThreadContextThreadTest, get_thread_contexts) {
+  // We want the other thread to be inside futex call inside
+  // pthread_cond_wait(). The other option is to let the other thread
+  // __nanosleep.  This is not reliable but better than nothing.
+  //
+  // This might turn out to be flaky, if so we should wait longer here.
+  usleep(100000);
 
-  Args args;
-  // Create a new thread and wait until it finishes its
-  // initialization.
-  // TODO(crbug.com/372248): Remove the wait. This synchronization is
-  // only for Bare Metal mode. On Bare Metal mode, pthread_context
-  // uses |stack_end_from_irt| in pthread_internal_t to find the
-  // location of a stack. Unlike other pthread attributes, this is
-  // filled by the created thread, not by the creator. So, there is a
-  // race. pthread_context may read an uninitialized value in
-  // |stack_end_from_irt|.
-  pthread_t thread;
-  {
-    ScopedPthreadMutexLocker lock(&args.mu);
-    ASSERT_EQ(0, pthread_create(&thread, NULL, WaitFn, &args));
-    while (!args.has_started)
-      pthread_cond_wait(&args.cond, &args.mu);
-  }
+  // __nanosleep call would clear the context_regs.
+  ASSERT_FALSE(HasContextRegs());
+  SAVE_CONTEXT_REGS();
+#if defined(__x86_64__) || defined(__arm__) ||          \
+  (defined(__i386__) && !defined(__native_client__))
+  ASSERT_TRUE(HasContextRegs());
+#else
+  ASSERT_FALSE(HasContextRegs());
+#endif
 
   // Verify data in the thread list.
   __pthread_context_info_t infos[100];
   int thread_count = __pthread_get_thread_infos(true, true, 100, infos);
   ASSERT_EQ(2, thread_count);
   for (int i = 0; i < thread_count; ++i) {
+    SCOPED_TRACE(i);
     ASSERT_TRUE(infos[i].stack_base != NULL);
-    ASSERT_GT(infos[i].stack_size, 0);
-#if defined(BARE_METAL_BIONIC)
-    ASSERT_EQ(infos[i].stack_size, 1024 * 1024);
+    EXPECT_GT(infos[i].stack_size, 0);
+#if defined(__x86_64__)
+    ASSERT_TRUE(infos[i].has_context_regs);
+    EXPECT_NE(0, infos[i].context_regs[REG_RIP]);
+#elif defined(__i386__) && !defined(__native_client__)
+    ASSERT_TRUE(infos[i].has_context_regs);
+    EXPECT_NE(0, infos[i].context_regs[REG_EIP]);
+#elif defined(__arm__)
+    ASSERT_TRUE(infos[i].has_context_regs);
+    EXPECT_NE(0, infos[i].context_regs[15]);
+#else
+    EXPECT_FALSE(infos[i].has_context_regs);
 #endif
   }
-
-  // Let the thread finish.
-  {
-    ScopedPthreadMutexLocker lock(&args.mu);
-    args.should_exit = true;
-    pthread_cond_signal(&args.cond);
-  }
-  pthread_join(thread, NULL);
+  CLEAR_CONTEXT_REGS();
 }
 
-TEST(pthread_thread_context, get_cur_thread_context) {
+
+TEST(PthreadThreadContextSinglethreadTest, get_cur_thread_context) {
   __pthread_context_info_t info;
   info.has_context_regs = true;
   __pthread_get_current_thread_info(&info);
@@ -104,12 +159,15 @@
   __pthread_get_current_thread_info(&info);
 #if defined(__x86_64__)
   ASSERT_TRUE(info.has_context_regs);
-  ASSERT_NE(0, info.context_regs[REG_RIP]);
+  EXPECT_NE(0, info.context_regs[REG_RIP]);
+#elif defined(__i386__) && !defined(__native_client__)
+  ASSERT_TRUE(info.has_context_regs);
+  EXPECT_NE(0, info.context_regs[REG_EIP]);
 #elif defined(__arm__)
   ASSERT_TRUE(info.has_context_regs);
-  ASSERT_NE(0, info.context_regs[15]);
+  EXPECT_NE(0, info.context_regs[15]);
 #else
-  ASSERT_FALSE(info.has_context_regs);
+  EXPECT_FALSE(info.has_context_regs);
 #endif
 
   CLEAR_CONTEXT_REGS();
@@ -117,3 +175,5 @@
   __pthread_get_current_thread_info(&info);
   ASSERT_FALSE(info.has_context_regs);
 }
+
+}  // anonymous namespace
diff --git a/mods/native_client/src/untrusted/minidump_generator/minidump_generator.cc b/mods/native_client/src/untrusted/minidump_generator/minidump_generator.cc
index 50cba8f..04c54d1 100644
--- a/mods/native_client/src/untrusted/minidump_generator/minidump_generator.cc
+++ b/mods/native_client/src/untrusted/minidump_generator/minidump_generator.cc
@@ -417,6 +417,27 @@
   COPY_REG(rip, REG_RIP);
   stack_start = regs.get()->rsp;
 #undef COPY_REG
+#elif defined(__i386__) && !defined(__native_client__)
+#define COPY_REG(REG, src_idx)     \
+    regs.get()->REG = info.context_regs[src_idx]
+  TypedMDRVA<MDRawContextX86> regs(minidump_writer);
+  if (!regs.Allocate())
+    return;
+  thread->thread_context = regs.location();
+  regs.get()->context_flags =
+      MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_INTEGER;
+  regs.get()->eflags = 0;
+  COPY_REG(edi, REG_EDI);
+  COPY_REG(esi, REG_ESI);
+  COPY_REG(ebp, REG_EBP);
+  COPY_REG(ebx, REG_EBX);
+  COPY_REG(edx, REG_EDX);
+  COPY_REG(ecx, REG_ECX);
+  COPY_REG(eax, REG_EAX);
+  COPY_REG(esp, REG_ESP);
+  COPY_REG(eip, REG_EIP);
+  stack_start = regs.get()->esp;
+#undef COPY_REG
 #elif defined(__arm__)
   TypedMDRVA<MDRawContextARM> regs(minidump_writer);
   if (!regs.Allocate())
@@ -428,7 +449,7 @@
   regs.get()->cpsr = 0;
   stack_start = regs.get()->iregs[13];
 #else
-  // TODO(igorc): Support stack traces in 32-bit mode.
+  // TODO(igorc): Support stack traces in NaCl x86 mode.
   return;
 #endif