Merge "Call __cxa_thread_finalize for the main thread."
diff --git a/libc/Android.mk b/libc/Android.mk
index 0dc3db7..e06a860 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -1007,7 +1007,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(libc_thread_atexit_impl_src_files)
-LOCAL_CFLAGS := $(libc_common_cflags) -fno-data-sections -Wframe-larger-than=2048
+LOCAL_CFLAGS := $(libc_common_cflags) -Wframe-larger-than=2048
 
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
diff --git a/libc/arch-x86/bionic/__bionic_clone.S b/libc/arch-x86/bionic/__bionic_clone.S
index ef78aee..1a6f642 100644
--- a/libc/arch-x86/bionic/__bionic_clone.S
+++ b/libc/arch-x86/bionic/__bionic_clone.S
@@ -3,8 +3,14 @@
 // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
 ENTRY(__bionic_clone)
         pushl   %ebx
+        .cfi_adjust_cfa_offset 4
+        .cfi_rel_offset ebx, 0
         pushl   %esi
+        .cfi_adjust_cfa_offset 4
+        .cfi_rel_offset esi, 0
         pushl   %edi
+        .cfi_adjust_cfa_offset 4
+        .cfi_rel_offset edi, 0
 
         # Load system call arguments into registers.
         movl    16(%esp), %ebx   # flags
@@ -46,8 +52,14 @@
         # We're the parent; nothing to do.
 .L_bc_return:
         popl    %edi
+        .cfi_adjust_cfa_offset -4
+        .cfi_restore edi
         popl    %esi
+        .cfi_adjust_cfa_offset -4
+        .cfi_restore esi
         popl    %ebx
+        .cfi_adjust_cfa_offset -4
+        .cfi_restore ebx
         ret
 END(__bionic_clone)
 .hidden __bionic_clone
diff --git a/libc/arch-x86/bionic/syscall.S b/libc/arch-x86/bionic/syscall.S
index f85ec39..2a15102 100644
--- a/libc/arch-x86/bionic/syscall.S
+++ b/libc/arch-x86/bionic/syscall.S
@@ -15,9 +15,17 @@
 ENTRY(syscall)
     # Push the callee save registers.
     push    %ebx
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset ebx, 0
     push    %esi
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset esi, 0
     push    %edi
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset edi, 0
     push    %ebp
+    .cfi_adjust_cfa_offset 4
+    .cfi_rel_offset ebp, 0
 
     # Load all the arguments from the calling frame.
     # (Not all will be valid, depending on the syscall.)
@@ -43,8 +51,16 @@
 1:
     # Restore the callee save registers.
     pop    %ebp
+    .cfi_adjust_cfa_offset -4
+    .cfi_restore ebp
     pop    %edi
+    .cfi_adjust_cfa_offset -4
+    .cfi_restore edi
     pop    %esi
+    .cfi_adjust_cfa_offset -4
+    .cfi_restore esi
     pop    %ebx
+    .cfi_adjust_cfa_offset -4
+    .cfi_restore ebx
     ret
 END(syscall)
diff --git a/libc/arch-x86/bionic/vfork.S b/libc/arch-x86/bionic/vfork.S
index 6c02910..ca7af0f 100644
--- a/libc/arch-x86/bionic/vfork.S
+++ b/libc/arch-x86/bionic/vfork.S
@@ -32,6 +32,8 @@
 
 ENTRY(vfork)
   popl    %ecx  // Grab the return address.
+  .cfi_adjust_cfa_offset 4
+  .cfi_rel_offset ecx, 0
   movl    $__NR_vfork, %eax
   int     $0x80
   cmpl    $-MAX_ERRNO, %eax
diff --git a/libc/bionic/__cxa_thread_atexit_impl.cpp b/libc/bionic/__cxa_thread_atexit_impl.cpp
index 9ae6dfd..0e427d3 100644
--- a/libc/bionic/__cxa_thread_atexit_impl.cpp
+++ b/libc/bionic/__cxa_thread_atexit_impl.cpp
@@ -22,7 +22,7 @@
   thread_local_dtor* next;
 };
 
-__thread thread_local_dtor* thread_local_dtors = nullptr;
+static __thread thread_local_dtor* thread_local_dtors = nullptr;
 
 extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
   thread_local_dtor* dtor = new thread_local_dtor();
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index 9991573..bc3aeb2 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -26,14 +26,15 @@
  * SUCH DAMAGE.
  */
 
-#include "pthread_internal.h"
-#include "private/bionic_futex.h"
 #include "private/kernel_sigset_t.h"
 
 #include <errno.h>
 #include <malloc.h>
+#include <pthread.h>
+#include <stdatomic.h>
 #include <stdio.h>
 #include <string.h>
+#include <time.h>
 
 // System calls.
 extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const struct timespec*, size_t);
@@ -59,11 +60,11 @@
 
   int sigev_notify;
 
-  // These fields are only needed for a SIGEV_THREAD timer.
+  // The fields below are only needed for a SIGEV_THREAD timer.
   pthread_t callback_thread;
   void (*callback)(sigval_t);
   sigval_t callback_argument;
-  volatile bool armed;
+  atomic_bool deleted;  // Set when the timer is deleted, to prevent further calling of callback.
 };
 
 static __kernel_timer_t to_kernel_timer_id(timer_t timer) {
@@ -85,8 +86,13 @@
       continue;
     }
 
-    if (si.si_code == SI_TIMER && timer->armed) {
+    if (si.si_code == SI_TIMER) {
       // This signal was sent because a timer fired, so call the callback.
+
+      // All events to the callback will be ignored when the timer is deleted.
+      if (atomic_load(&timer->deleted) == true) {
+        continue;
+      }
       timer->callback(timer->callback_argument);
     } else if (si.si_code == SI_TKILL) {
       // This signal was sent because someone wants us to exit.
@@ -97,9 +103,7 @@
 }
 
 static void __timer_thread_stop(PosixTimer* timer) {
-  // Immediately mark the timer as disarmed so even if some events
-  // continue to happen, the callback won't be called.
-  timer->armed = false;
+  atomic_store(&timer->deleted, true);
   pthread_kill(timer->callback_thread, TIMER_SIGNAL);
 }
 
@@ -126,7 +130,7 @@
   // Otherwise, this must be SIGEV_THREAD timer...
   timer->callback = evp->sigev_notify_function;
   timer->callback_argument = evp->sigev_value;
-  timer->armed = false;
+  atomic_init(&timer->deleted, false);
 
   // Check arguments that the kernel doesn't care about but we do.
   if (timer->callback == NULL) {
@@ -199,25 +203,19 @@
   return 0;
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
+// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html
 int timer_gettime(timer_t id, itimerspec* ts) {
   return __timer_gettime(to_kernel_timer_id(id), ts);
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
+// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html
+// When using timer_settime to disarm a repeatable SIGEV_THREAD timer with a very small
+// period (like below 1ms), the kernel may continue to send events to the callback thread
+// for a few extra times. This behavior is fine because in POSIX standard: The effect of
+// disarming or resetting a timer with pending expiration notifications is unspecified.
 int timer_settime(timer_t id, int flags, const itimerspec* ts, itimerspec* ots) {
   PosixTimer* timer= reinterpret_cast<PosixTimer*>(id);
-  int rc = __timer_settime(timer->kernel_timer_id, flags, ts, ots);
-  if (rc == 0) {
-    // Mark the timer as either being armed or disarmed. This avoids the
-    // callback being called after the disarm for SIGEV_THREAD timers only.
-    if (ts->it_value.tv_sec != 0 || ts->it_value.tv_nsec != 0) {
-      timer->armed = true;
-    } else {
-      timer->armed = false;
-    }
-  }
-  return rc;
+  return __timer_settime(timer->kernel_timer_id, flags, ts, ots);
 }
 
 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 414d171..30dc0eb 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -97,14 +97,8 @@
 #define LIBC_PTHREAD_KEY_RESERVED_COUNT 12
 
 #if defined(USE_JEMALLOC)
-/* Following are current pthread keys used internally by jemalloc:
- * je_thread_allocated_tsd jemalloc
- * je_arenas_tsd           jemalloc
- * je_tcache_tsd           jemalloc
- * je_tcache_enabled_tsd   jemalloc
- * je_quarantine_tsd       jemalloc
- */
-#define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 5
+/* Internally, jemalloc uses a single key for per thread data. */
+#define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 1
 #define BIONIC_PTHREAD_KEY_RESERVED_COUNT (LIBC_PTHREAD_KEY_RESERVED_COUNT + JEMALLOC_PTHREAD_KEY_RESERVED_COUNT)
 #else
 #define BIONIC_PTHREAD_KEY_RESERVED_COUNT LIBC_PTHREAD_KEY_RESERVED_COUNT
diff --git a/tests/__cxa_thread_atexit_test.cpp b/tests/__cxa_thread_atexit_test.cpp
index 59d2efd..e388f3b 100644
--- a/tests/__cxa_thread_atexit_test.cpp
+++ b/tests/__cxa_thread_atexit_test.cpp
@@ -35,7 +35,7 @@
   std::string message;
 };
 
-thread_local ClassWithDtor class_with_dtor;
+static thread_local ClassWithDtor class_with_dtor;
 
 static void* thread_nop(void* arg) {
   class_with_dtor.set_message(*static_cast<std::string*>(arg));
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 691d8ff..a0b0209 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <atomic>
 
 #include "ScopedSignalHandler.h"
 
@@ -197,7 +198,7 @@
   ASSERT_EQ(0, timer_delete(timer_id));
 }
 
-static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
+static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
 static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
   ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
   ASSERT_EQ(SIGUSR1, signal_number);
@@ -212,6 +213,7 @@
   timer_t timer_id;
   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
 
+  timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
   ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
 
   ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
@@ -228,25 +230,26 @@
 }
 
 struct Counter {
-  volatile int value;
+ private:
+  std::atomic<int> value;
   timer_t timer_id;
   sigevent_t se;
   bool timer_valid;
 
-  Counter(void (*fn)(sigval_t)) : value(0), timer_valid(false) {
-    memset(&se, 0, sizeof(se));
-    se.sigev_notify = SIGEV_THREAD;
-    se.sigev_notify_function = fn;
-    se.sigev_value.sival_ptr = this;
-    Create();
-  }
-
   void Create() {
     ASSERT_FALSE(timer_valid);
     ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
     timer_valid = true;
   }
 
+ public:
+  Counter(void (*fn)(sigval_t)) : value(0), timer_valid(false) {
+    memset(&se, 0, sizeof(se));
+    se.sigev_notify = SIGEV_THREAD;
+    se.sigev_notify_function = fn;
+    se.sigev_value.sival_ptr = this;
+    Create();
+  }
   void DeleteTimer() {
     ASSERT_TRUE(timer_valid);
     ASSERT_EQ(0, timer_delete(timer_id));
@@ -259,12 +262,16 @@
     }
   }
 
+  int Value() const {
+    return value;
+  }
+
   void SetTime(time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
     ::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns);
   }
 
   bool ValueUpdated() {
-    volatile int current_value = value;
+    int current_value = value;
     time_t start = time(NULL);
     while (current_value == value && (time(NULL) - start) < 5) {
     }
@@ -287,30 +294,29 @@
 
 TEST(time, timer_settime_0) {
   Counter counter(Counter::CountAndDisarmNotifyFunction);
-  ASSERT_TRUE(counter.timer_valid);
-
-  ASSERT_EQ(0, counter.value);
+  ASSERT_EQ(0, counter.Value());
 
   counter.SetTime(0, 1, 1, 0);
   usleep(500000);
 
   // The count should just be 1 because we disarmed the timer the first time it fired.
-  ASSERT_EQ(1, counter.value);
+  ASSERT_EQ(1, counter.Value());
 }
 
 TEST(time, timer_settime_repeats) {
   Counter counter(Counter::CountNotifyFunction);
-  ASSERT_TRUE(counter.timer_valid);
-
-  ASSERT_EQ(0, counter.value);
+  ASSERT_EQ(0, counter.Value());
 
   counter.SetTime(0, 1, 0, 10);
   ASSERT_TRUE(counter.ValueUpdated());
   ASSERT_TRUE(counter.ValueUpdated());
   ASSERT_TRUE(counter.ValueUpdated());
+  counter.DeleteTimer();
+  // Add a sleep as other threads may be calling the callback function when the timer is deleted.
+  usleep(500000);
 }
 
-static int timer_create_NULL_signal_handler_invocation_count = 0;
+static int timer_create_NULL_signal_handler_invocation_count;
 static void timer_create_NULL_signal_handler(int signal_number) {
   ++timer_create_NULL_signal_handler_invocation_count;
   ASSERT_EQ(SIGALRM, signal_number);
@@ -321,6 +327,7 @@
   timer_t timer_id;
   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
 
+  timer_create_NULL_signal_handler_invocation_count = 0;
   ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
 
   ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
@@ -367,22 +374,59 @@
 
 TEST(time, timer_create_multiple) {
   Counter counter1(Counter::CountNotifyFunction);
-  ASSERT_TRUE(counter1.timer_valid);
   Counter counter2(Counter::CountNotifyFunction);
-  ASSERT_TRUE(counter2.timer_valid);
   Counter counter3(Counter::CountNotifyFunction);
-  ASSERT_TRUE(counter3.timer_valid);
 
-  ASSERT_EQ(0, counter1.value);
-  ASSERT_EQ(0, counter2.value);
-  ASSERT_EQ(0, counter3.value);
+  ASSERT_EQ(0, counter1.Value());
+  ASSERT_EQ(0, counter2.Value());
+  ASSERT_EQ(0, counter3.Value());
 
   counter2.SetTime(0, 1, 0, 0);
   usleep(500000);
 
-  EXPECT_EQ(0, counter1.value);
-  EXPECT_EQ(1, counter2.value);
-  EXPECT_EQ(0, counter3.value);
+  EXPECT_EQ(0, counter1.Value());
+  EXPECT_EQ(1, counter2.Value());
+  EXPECT_EQ(0, counter3.Value());
+}
+
+// Test to verify that disarming a repeatable timer disables the callbacks.
+TEST(time, timer_disarm_terminates) {
+  Counter counter(Counter::CountNotifyFunction);
+  ASSERT_EQ(0, counter.Value());
+
+  counter.SetTime(0, 1, 0, 1);
+  ASSERT_TRUE(counter.ValueUpdated());
+  ASSERT_TRUE(counter.ValueUpdated());
+  ASSERT_TRUE(counter.ValueUpdated());
+
+  counter.SetTime(0, 0, 0, 0);
+  // Add a sleep as the kernel may have pending events when the timer is disarmed.
+  usleep(500000);
+  int value = counter.Value();
+  usleep(500000);
+
+  // Verify the counter has not been incremented.
+  ASSERT_EQ(value, counter.Value());
+}
+
+// Test to verify that deleting a repeatable timer disables the callbacks.
+TEST(time, timer_delete_terminates) {
+  Counter counter(Counter::CountNotifyFunction);
+  ASSERT_EQ(0, counter.Value());
+
+  counter.SetTime(0, 1, 0, 1);
+  ASSERT_TRUE(counter.ValueUpdated());
+  ASSERT_TRUE(counter.ValueUpdated());
+  ASSERT_TRUE(counter.ValueUpdated());
+
+  counter.DeleteTimer();
+  // Add a sleep as other threads may be calling the callback function when the timer is deleted.
+  usleep(500000);
+  int value = counter.Value();
+  usleep(500000);
+
+  // Verify the counter has not been incremented.
+  ASSERT_EQ(value, counter.Value());
 }
 
 struct TimerDeleteData {
@@ -499,45 +543,3 @@
   timespec out;
   ASSERT_EQ(EINVAL, clock_nanosleep(-1, 0, &in, &out));
 }
-
-// Test to verify that disarming a repeatable timer disables the
-// callbacks.
-TEST(time, timer_disarm_terminates) {
-  Counter counter(Counter::CountNotifyFunction);
-  ASSERT_TRUE(counter.timer_valid);
-
-  ASSERT_EQ(0, counter.value);
-
-  counter.SetTime(0, 1, 0, 1);
-  ASSERT_TRUE(counter.ValueUpdated());
-  ASSERT_TRUE(counter.ValueUpdated());
-  ASSERT_TRUE(counter.ValueUpdated());
-
-  counter.SetTime(0, 0, 1, 0);
-  volatile int value = counter.value;
-  usleep(500000);
-
-  // Verify the counter has not been incremented.
-  ASSERT_EQ(value, counter.value);
-}
-
-// Test to verify that deleting a repeatable timer disables the
-// callbacks.
-TEST(time, timer_delete_terminates) {
-  Counter counter(Counter::CountNotifyFunction);
-  ASSERT_TRUE(counter.timer_valid);
-
-  ASSERT_EQ(0, counter.value);
-
-  counter.SetTime(0, 1, 0, 1);
-  ASSERT_TRUE(counter.ValueUpdated());
-  ASSERT_TRUE(counter.ValueUpdated());
-  ASSERT_TRUE(counter.ValueUpdated());
-
-  counter.DeleteTimer();
-  volatile int value = counter.value;
-  usleep(500000);
-
-  // Verify the counter has not been incremented.
-  ASSERT_EQ(value, counter.value);
-}