Merge "cutils: add simple reference counter"
diff --git a/adb/Android.mk b/adb/Android.mk
index d6b0146..a803978 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -16,7 +16,8 @@
 ifeq ($(HOST_OS),linux)
   USB_SRCS := usb_linux.c
   EXTRA_SRCS := get_my_path_linux.c
-  LOCAL_LDLIBS += -lrt -lncurses -lpthread
+  LOCAL_LDLIBS += -lrt -ldl -lpthread
+  LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
 endif
 
 ifeq ($(HOST_OS),darwin)
@@ -140,7 +141,7 @@
 ifneq ($(SDK_ONLY),true)
 include $(CLEAR_VARS)
 
-LOCAL_LDLIBS := -lrt -lncurses -lpthread
+LOCAL_LDLIBS := -lrt -ldl -lpthread
 
 LOCAL_SRC_FILES := \
 	adb.c \
diff --git a/adb/adb.c b/adb/adb.c
index 4c3364f..8be5765 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -983,6 +983,33 @@
 #endif
 
 #if ADB_HOST
+
+#ifdef WORKAROUND_BUG6558362
+#include <sched.h>
+#define AFFINITY_ENVVAR "ADB_CPU_AFFINITY_BUG6558362"
+void adb_set_affinity(void)
+{
+   cpu_set_t cpu_set;
+   const char* cpunum_str = getenv(AFFINITY_ENVVAR);
+   char* strtol_res;
+   int cpu_num;
+
+   if (!cpunum_str || !*cpunum_str)
+       return;
+   cpu_num = strtol(cpunum_str, &strtol_res, 0);
+   if (*strtol_res != '\0')
+     fatal("bad number (%s) in env var %s. Expecting 0..n.\n", cpunum_str, AFFINITY_ENVVAR);
+
+   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+   D("orig cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+   CPU_ZERO(&cpu_set);
+   CPU_SET(cpu_num, &cpu_set);
+   sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+   D("new cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+}
+#endif
+
 int launch_server(int server_port)
 {
 #ifdef HAVE_WIN32_PROC
@@ -1186,6 +1213,10 @@
 
 #if ADB_HOST
     HOST = 1;
+
+#ifdef WORKAROUND_BUG6558362
+    if(is_daemon) adb_set_affinity();
+#endif
     usb_vendors_init();
     usb_init();
     local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
index 6893985..eb44236 100644
--- a/include/cutils/bitops.h
+++ b/include/cutils/bitops.h
@@ -17,6 +17,7 @@
 #ifndef __CUTILS_BITOPS_H
 #define __CUTILS_BITOPS_H
 
+#include <stdbool.h>
 #include <string.h>
 #include <strings.h>
 #include <sys/cdefs.h>
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index 3b876d4..dd777c0 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -35,14 +35,17 @@
 
 void usage() {
     fatal(
-        "Usage: logwrapper BINARY [ARGS ...]\n"
+        "Usage: logwrapper [-d] BINARY [ARGS ...]\n"
         "\n"
         "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
         "the Android logging system. Tag is set to BINARY, priority is\n"
-        "always LOG_INFO.\n");
+        "always LOG_INFO.\n"
+        "\n"
+        "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n"
+        "    fault address is set to the status of wait()\n");
 }
 
-void parent(const char *tag, int parent_read) {
+void parent(const char *tag, int seg_fault_on_exit, int parent_read) {
     int status;
     char buffer[4096];
 
@@ -102,6 +105,8 @@
     } else
         ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
                 strerror(errno), errno);
+    if (seg_fault_on_exit)
+        *(int *)status = 0;  // causes SIGSEGV with fault_address = status
 }
 
 void child(int argc, char* argv[]) {
@@ -119,6 +124,7 @@
 
 int main(int argc, char* argv[]) {
     pid_t pid;
+    int seg_fault_on_exit = 0;
 
     int parent_ptty;
     int child_ptty;
@@ -128,6 +134,16 @@
         usage();
     }
 
+    if (strncmp(argv[1], "-d", 2) == 0) {
+        seg_fault_on_exit = 1;
+        argc--;
+        argv++;
+    }
+
+    if (argc < 2) {
+        usage();
+    }
+
     /* Use ptty instead of socketpair so that STDOUT is not buffered */
     parent_ptty = open("/dev/ptmx", O_RDWR);
     if (parent_ptty < 0) {
@@ -163,7 +179,7 @@
         setgid(AID_LOG);
         setuid(AID_LOG);
 
-        parent(argv[1], parent_ptty);
+        parent(argv[1], seg_fault_on_exit, parent_ptty);
     }
 
     return 0;