Merge "Scan all descriptors when checking for fastboot"
diff --git a/debuggerd/arm/machine.cpp b/debuggerd/arm/machine.cpp
index 8270066..50e78c5 100644
--- a/debuggerd/arm/machine.cpp
+++ b/debuggerd/arm/machine.cpp
@@ -82,13 +82,13 @@
 
   user_vfp vfp_regs;
   if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
-    _LOG(log, logtype::REGISTERS, "cannot get registers: %s\n", strerror(errno));
+    _LOG(log, logtype::FP_REGISTERS, "cannot get FP registers: %s\n", strerror(errno));
     return;
   }
 
   for (size_t i = 0; i < 32; i += 2) {
-    _LOG(log, logtype::REGISTERS, "    d%-2d %016llx  d%-2d %016llx\n",
+    _LOG(log, logtype::FP_REGISTERS, "    d%-2d %016llx  d%-2d %016llx\n",
          i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
   }
-  _LOG(log, logtype::REGISTERS, "    scr %08lx\n", vfp_regs.fpscr);
+  _LOG(log, logtype::FP_REGISTERS, "    scr %08lx\n", vfp_regs.fpscr);
 }
diff --git a/debuggerd/arm64/machine.cpp b/debuggerd/arm64/machine.cpp
index ec664bd..8b17d53 100644
--- a/debuggerd/arm64/machine.cpp
+++ b/debuggerd/arm64/machine.cpp
@@ -15,17 +15,14 @@
  * limitations under the License.
  */
 
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
+#include <elf.h>
 #include <errno.h>
+#include <inttypes.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <sys/user.h>
 #include <sys/uio.h>
-#include <linux/elf.h>
 
 #include "../utility.h"
 #include "../machine.h"
@@ -79,19 +76,18 @@
 
   for (int i = 0; i < 28; i += 4) {
     _LOG(log, logtype::REGISTERS,
-         "    x%-2d  %016lx  x%-2d  %016lx  x%-2d  %016lx  x%-2d  %016lx\n",
-         i, (uint64_t)r.regs[i],
-         i+1, (uint64_t)r.regs[i+1],
-         i+2, (uint64_t)r.regs[i+2],
-         i+3, (uint64_t)r.regs[i+3]);
+         "    x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx\n",
+         i, r.regs[i],
+         i+1, r.regs[i+1],
+         i+2, r.regs[i+2],
+         i+3, r.regs[i+3]);
   }
 
-  _LOG(log, logtype::REGISTERS, "    x28  %016lx  x29  %016lx  x30  %016lx\n",
-       (uint64_t)r.regs[28], (uint64_t)r.regs[29], (uint64_t)r.regs[30]);
+  _LOG(log, logtype::REGISTERS, "    x28  %016llx  x29  %016llx  x30  %016llx\n",
+       r.regs[28], r.regs[29], r.regs[30]);
 
-  _LOG(log, logtype::REGISTERS, "    sp   %016lx  pc   %016lx\n",
-       (uint64_t)r.sp, (uint64_t)r.pc);
-
+  _LOG(log, logtype::REGISTERS, "    sp   %016llx  pc   %016llx  pstate %016llx\n",
+       r.sp, r.pc, r.pstate);
 
   struct user_fpsimd_state f;
   io.iov_base = &f;
@@ -102,11 +98,15 @@
     return;
   }
 
-  for (int i = 0; i < 32; i += 4) {
-    _LOG(log, logtype::REGISTERS, "    v%-2d  %016lx  v%-2d  %016lx  v%-2d  %016lx  v%-2d  %016lx\n",
-         i, (uint64_t)f.vregs[i],
-         i+1, (uint64_t)f.vregs[i+1],
-         i+2, (uint64_t)f.vregs[i+2],
-         i+3, (uint64_t)f.vregs[i+3]);
+  for (int i = 0; i < 32; i += 2) {
+    _LOG(log, logtype::FP_REGISTERS,
+         "    v%-2d  %016" PRIx64 "%016" PRIx64 "  v%-2d  %016" PRIx64 "%016" PRIx64 "\n",
+         i,
+         static_cast<uint64_t>(f.vregs[i] >> 64),
+         static_cast<uint64_t>(f.vregs[i]),
+         i+1,
+         static_cast<uint64_t>(f.vregs[i+1] >> 64),
+         static_cast<uint64_t>(f.vregs[i+1]));
   }
+  _LOG(log, logtype::FP_REGISTERS, "    fpsr %08x  fpcr %08x\n", f.fpsr, f.fpcr);
 }
diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c
index 9df3c64..d315ee5 100644
--- a/debuggerd/crasher.c
+++ b/debuggerd/crasher.c
@@ -141,11 +141,14 @@
     } else if (!strcmp(arg, "assert")) {
         __assert("some_file.c", 123, "false");
     } else if (!strcmp(arg, "assert2")) {
-      __assert2("some_file.c", 123, "some_function", "false");
+        __assert2("some_file.c", 123, "some_function", "false");
     } else if (!strcmp(arg, "LOG_ALWAYS_FATAL")) {
         LOG_ALWAYS_FATAL("hello %s", "world");
     } else if (!strcmp(arg, "LOG_ALWAYS_FATAL_IF")) {
         LOG_ALWAYS_FATAL_IF(true, "hello %s", "world");
+    } else if (!strcmp(arg, "SIGFPE")) {
+        raise(SIGFPE);
+        return EXIT_SUCCESS;
     } else if (!strcmp(arg, "SIGPIPE")) {
         int pipe_fds[2];
         pipe(pipe_fds);
@@ -177,6 +180,7 @@
     fprintf(stderr, "  assert2               call assert() with a function\n");
     fprintf(stderr, "  LOG_ALWAYS_FATAL      call LOG_ALWAYS_FATAL\n");
     fprintf(stderr, "  LOG_ALWAYS_FATAL_IF   call LOG_ALWAYS_FATAL\n");
+    fprintf(stderr, "  SIGFPE                cause a SIGFPE\n");
     fprintf(stderr, "  SIGPIPE               cause a SIGPIPE\n");
     fprintf(stderr, "  SIGSEGV               cause a SIGSEGV at address 0x0 (synonym: crash)\n");
     fprintf(stderr, "  SIGSEGV-non-null      cause a SIGSEGV at a non-zero address\n");
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index f2e2d29..518305d 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -2,16 +2,16 @@
 **
 ** Copyright 2008, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -54,6 +54,7 @@
   HEADER,
   THREAD,
   REGISTERS,
+  FP_REGISTERS,
   BACKTRACE,
   MAPS,
   MEMORY,
diff --git a/include/cutils/atomic.h b/include/cutils/atomic.h
index 1787e34..b9b18c4 100644
--- a/include/cutils/atomic.h
+++ b/include/cutils/atomic.h
@@ -25,8 +25,20 @@
 #endif
 
 /*
- * A handful of basic atomic operations.  The appropriate pthread
- * functions should be used instead of these whenever possible.
+ * A handful of basic atomic operations.
+ * THESE ARE HERE FOR LEGACY REASONS ONLY.  AVOID.
+ *
+ * PREFERRED ALTERNATIVES:
+ * - Use C++/C/pthread locks/mutexes whenever there is not a
+ *   convincing reason to do otherwise.  Note that very clever and
+ *   complicated, but correct, lock-free code is often slower than
+ *   using locks, especially where nontrivial data structures
+ *   are involved.
+ * - C11 stdatomic.h.
+ * - Where supported, C++11 std::atomic<T> .
+ *
+ * PLEASE STOP READING HERE UNLESS YOU ARE TRYING TO UNDERSTAND
+ * OR UPDATE OLD CODE.
  *
  * The "acquire" and "release" terms can be defined intuitively in terms
  * of the placement of memory barriers in a simple lock implementation:
@@ -74,6 +86,17 @@
 /*
  * Perform an atomic load with "acquire" or "release" ordering.
  *
+ * Note that the notion of a "release" ordering for a load does not
+ * really fit into the C11 or C++11 memory model.  The extra ordering
+ * is normally observable only by code using memory_order_relaxed
+ * atomics, or data races.  In the rare cases in which such ordering
+ * is called for, use memory_order_relaxed atomics and a leading
+ * atomic_thread_fence (typically with memory_order_acquire,
+ * not memory_order_release!) instead.  If you do not understand
+ * this comment, you are in the vast majority, and should not be
+ * using release loads or replacing them with anything other than
+ * locks or default sequentially consistent atomics.
+ *
  * This is only necessary if you need the memory barrier.  A 32-bit read
  * from a 32-bit aligned address is atomic on all supported platforms.
  */
@@ -88,6 +111,14 @@
 /*
  * Perform an atomic store with "acquire" or "release" ordering.
  *
+ * Note that the notion of a "acquire" ordering for a store does not
+ * really fit into the C11 or C++11 memory model.  The extra ordering
+ * is normally observable only by code using memory_order_relaxed
+ * atomics, or data races.  In the rare cases in which such ordering
+ * is called for, use memory_order_relaxed atomics and a trailing
+ * atomic_thread_fence (typically with memory_order_release,
+ * not memory_order_acquire!) instead.
+ *
  * This is only necessary if you need the memory barrier.  A 32-bit write
  * to a 32-bit aligned address is atomic on all supported platforms.
  */
diff --git a/include/cutils/jstring.h b/include/cutils/jstring.h
index ee0018f..a342608 100644
--- a/include/cutils/jstring.h
+++ b/include/cutils/jstring.h
@@ -24,7 +24,10 @@
 extern "C" {
 #endif
 
-typedef uint16_t char16_t;
+#if __STDC_VERSION__ < 201112L && __cplusplus < 201103L
+  typedef uint16_t char16_t;
+#endif
+  // otherwise char16_t is a keyword with the right semantics
 
 extern char * strndup16to8 (const char16_t* s, size_t n);
 extern size_t strnlen16to8 (const char16_t* s, size_t n);
diff --git a/init/init.c b/init/init.c
index 74c0308..bd1db7a 100644
--- a/init/init.c
+++ b/init/init.c
@@ -817,27 +817,21 @@
      * that /data/local.prop cannot interfere with them.
      */
     start_property_service();
+    if (get_property_set_fd() < 0) {
+        ERROR("start_property_service() failed\n");
+        exit(1);
+    }
+
     return 0;
 }
 
 static int signal_init_action(int nargs, char **args)
 {
     signal_init();
-    return 0;
-}
-
-static int check_startup_action(int nargs, char **args)
-{
-    /* make sure we actually have all the pieces we need */
-    if ((get_property_set_fd() < 0) ||
-        (get_signal_fd() < 0)) {
-        ERROR("init startup failure\n");
+    if (get_signal_fd() < 0) {
+        ERROR("signal_init() failed\n");
         exit(1);
     }
-
-        /* signal that we hit this point */
-    unlink("/dev/.booting");
-
     return 0;
 }
 
@@ -1098,7 +1092,6 @@
     queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
     queue_builtin_action(property_service_init_action, "property_service_init");
     queue_builtin_action(signal_init_action, "signal_init");
-    queue_builtin_action(check_startup_action, "check_startup");
 
     /* Don't mount filesystems or start core system services if in charger mode. */
     if (is_charger) {
@@ -1107,7 +1100,7 @@
         action_for_each_trigger("late-init", action_add_queue_tail);
     }
 
-        /* run all property triggers based on current state of the properties */
+    /* run all property triggers based on current state of the properties */
     queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
 
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index e2bc5b3..3644219 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -164,6 +164,10 @@
 on load_all_props_action
     load_all_props
 
+# Indicate to fw loaders that the relevant mounts are up.
+on firmware_mounts_complete
+    rm /dev/.booting
+
 # Mount filesystems and start core system services.
 on late-init
     trigger early-fs
@@ -176,9 +180,13 @@
     # issued fs triggers have completed.
     trigger load_all_props_action
 
+    # Remove a file to wake up anything waiting for firmware.
+    trigger firmware_mounts_complete
+
     trigger early-boot
     trigger boot
 
+
 on post-fs
     # once everything is setup, no need to modify /
     mount rootfs rootfs / ro remount