adb: HACK: (linux only) allow temp mitigation for multithreaded issues

There are serious multithreading issues between the fdevent and transport
subsystems which both manipulate struct asocket and struct fde concurrently.
The prevalent symptom being around multiple socket closures which stomp
 on each other, typically causing:
   "glibc detected *** adb: double free or corruption ..."

This HACK allows forcing CPU affinity via an env var. E.g.:
  export ADB_CPU_AFFINITY_BUG6558362=0
which will cause ONLY the adb server and all its threads to be pegged
to CPU 0.

The result is visible in valgrind's helgrind: no *socket_close() related
data races. But tons of other races are still there.

Bug: 6558362
Change-Id: I0f112390a6a921c64b2a783297be9e99ce27fd56
diff --git a/adb/Android.mk b/adb/Android.mk
index d6b0146..1fca684 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -17,6 +17,7 @@
   USB_SRCS := usb_linux.c
   EXTRA_SRCS := get_my_path_linux.c
   LOCAL_LDLIBS += -lrt -lncurses -lpthread
+  LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
 endif
 
 ifeq ($(HOST_OS),darwin)
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);