adb: make adb_thread_func_t return void, add adb_thread_exit.

Windows restricts the return value of threads to 32-bits, even on 64-bit
platforms. Since we don't actually return meaningful values from thread,
resolve this inconsistency with POSIX by making adb's thread abstraction
only take void functions.

Change-Id: I5c23b4432314f13bf16d606fd5e6b6b7b6ef98b5
diff --git a/commandline.cpp b/commandline.cpp
index 85ab4d1..8e76168 100644
--- a/commandline.cpp
+++ b/commandline.cpp
@@ -482,7 +482,7 @@
 // Loops to read from stdin and push the data to the given FD.
 // The argument should be a pointer to a StdinReadArgs object. This function
 // will take ownership of the object and delete it when finished.
-static void* stdin_read_thread_loop(void* x) {
+static void stdin_read_thread_loop(void* x) {
     std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
 
 #if !defined(_WIN32)
@@ -586,8 +586,6 @@
             }
         }
     }
-
-    return nullptr;
 }
 
 // Returns a shell service string with the indicated arguments and command.
diff --git a/services.cpp b/services.cpp
index 9cbf787..75cbe5d 100644
--- a/services.cpp
+++ b/services.cpp
@@ -57,13 +57,11 @@
     void *cookie;
 };
 
-void *service_bootstrap_func(void *x)
-{
+static void service_bootstrap_func(void* x) {
     stinfo* sti = reinterpret_cast<stinfo*>(x);
     adb_thread_setname(android::base::StringPrintf("service %d", sti->fd));
     sti->func(sti->fd, sti->cookie);
     free(sti);
-    return 0;
 }
 
 #if !ADB_HOST
diff --git a/shell_service.cpp b/shell_service.cpp
index d080e09..f84447f 100644
--- a/shell_service.cpp
+++ b/shell_service.cpp
@@ -198,7 +198,7 @@
     // Opens the file at |pts_name|.
     int OpenPtyChildFd(const char* pts_name, ScopedFd* error_sfd);
 
-    static void* ThreadHandler(void* userdata);
+    static void ThreadHandler(void* userdata);
     void PassDataStreams();
     void WaitForExit();
 
@@ -465,7 +465,7 @@
     return child_fd;
 }
 
-void* Subprocess::ThreadHandler(void* userdata) {
+void Subprocess::ThreadHandler(void* userdata) {
     Subprocess* subprocess = reinterpret_cast<Subprocess*>(userdata);
 
     adb_thread_setname(android::base::StringPrintf(
@@ -475,8 +475,6 @@
 
     D("deleting Subprocess for PID %d", subprocess->pid());
     delete subprocess;
-
-    return nullptr;
 }
 
 void Subprocess::PassDataStreams() {
diff --git a/sysdeps.h b/sysdeps.h
index 761a4c7..f9f6f69 100644
--- a/sysdeps.h
+++ b/sysdeps.h
@@ -115,25 +115,26 @@
     LeaveCriticalSection( lock );
 }
 
-typedef void* (*adb_thread_func_t)(void* arg);
+typedef void (*adb_thread_func_t)(void* arg);
 typedef HANDLE adb_thread_t;
 
-struct win_thread_args {
+struct adb_winthread_args {
     adb_thread_func_t func;
     void* arg;
 };
 
-static unsigned __stdcall win_thread_wrapper(void* args) {
-    win_thread_args thread_args = *static_cast<win_thread_args*>(args);
-    delete static_cast<win_thread_args*>(args);
-    void* result = thread_args.func(thread_args.arg);
-    return reinterpret_cast<unsigned>(result);
+static unsigned __stdcall adb_winthread_wrapper(void* heap_args) {
+    // Move the arguments from the heap onto the thread's stack.
+    adb_winthread_args thread_args = *static_cast<adb_winthread_args*>(heap_args);
+    delete static_cast<adb_winthread_args*>(heap_args);
+    thread_args.func(thread_args.arg);
+    return 0;
 }
 
 static __inline__ bool adb_thread_create(adb_thread_func_t func, void* arg,
                                          adb_thread_t* thread = nullptr) {
-    win_thread_args* args = new win_thread_args{.func = func, .arg = arg};
-    uintptr_t handle = _beginthreadex(nullptr, 0, win_thread_wrapper, args, 0, nullptr);
+    adb_winthread_args* args = new adb_winthread_args{.func = func, .arg = arg};
+    uintptr_t handle = _beginthreadex(nullptr, 0, adb_winthread_wrapper, args, 0, nullptr);
     if (handle != static_cast<uintptr_t>(0)) {
         if (thread) {
             *thread = reinterpret_cast<HANDLE>(handle);
@@ -168,6 +169,10 @@
     return true;
 }
 
+static __inline__ void __attribute__((noreturn)) adb_thread_exit() {
+    ExitThread(0);
+}
+
 static __inline__ int adb_thread_setname(const std::string& name) {
     // TODO: See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx for how to set
     // the thread name in Windows. Unfortunately, it only works during debugging, but
@@ -701,17 +706,32 @@
 #define  unix_write  adb_write
 #define  unix_close  adb_close
 
-typedef void*  (*adb_thread_func_t)( void*  arg );
-
+// Win32 is limited to DWORDs for thread return values; limit the POSIX systems to this as well to
+// ensure compatibility.
+typedef void (*adb_thread_func_t)(void* arg);
 typedef pthread_t adb_thread_t;
 
+struct adb_pthread_args {
+    adb_thread_func_t func;
+    void* arg;
+};
+
+static void* adb_pthread_wrapper(void* heap_args) {
+    // Move the arguments from the heap onto the thread's stack.
+    adb_pthread_args thread_args = *reinterpret_cast<adb_pthread_args*>(heap_args);
+    delete static_cast<adb_pthread_args*>(heap_args);
+    thread_args.func(thread_args.arg);
+    return nullptr;
+}
+
 static __inline__ bool adb_thread_create(adb_thread_func_t start, void* arg,
                                          adb_thread_t* thread = nullptr) {
     pthread_t temp;
     pthread_attr_t attr;
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, thread ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
-    errno = pthread_create(&temp, &attr, start, arg);
+    auto* pthread_args = new adb_pthread_args{.func = start, .arg = arg};
+    errno = pthread_create(&temp, &attr, adb_pthread_wrapper, pthread_args);
     if (errno == 0) {
         if (thread) {
             *thread = temp;
@@ -731,6 +751,10 @@
     return errno == 0;
 }
 
+static __inline__ void __attribute__((noreturn)) adb_thread_exit() {
+    pthread_exit(nullptr);
+}
+
 static __inline__ int adb_thread_setname(const std::string& name) {
 #ifdef __APPLE__
     return pthread_setname_np(name.c_str());
diff --git a/sysdeps_test.cpp b/sysdeps_test.cpp
index 24a0d6f..e6037d7 100644
--- a/sysdeps_test.cpp
+++ b/sysdeps_test.cpp
@@ -20,10 +20,9 @@
 
 #include "sysdeps.h"
 
-static void* increment_atomic_int(void* c) {
+static void increment_atomic_int(void* c) {
     sleep(1);
     reinterpret_cast<std::atomic<int>*>(c)->fetch_add(1);
-    return nullptr;
 }
 
 TEST(sysdeps_thread, smoke) {
@@ -57,3 +56,14 @@
 
     ASSERT_EQ(500, counter.load());
 }
+
+TEST(sysdeps_thread, exit) {
+    adb_thread_t thread;
+    ASSERT_TRUE(adb_thread_create(
+        [](void*) {
+            adb_thread_exit();
+            for (;;) continue;
+        },
+        nullptr, &thread));
+    ASSERT_TRUE(adb_thread_join(thread));
+}
diff --git a/transport.cpp b/transport.cpp
index 6020ad5..d9180bc 100644
--- a/transport.cpp
+++ b/transport.cpp
@@ -190,8 +190,7 @@
 //
 // read_transport thread reads data from a transport (representing a usb/tcp connection),
 // and makes the main thread call handle_packet().
-static void *read_transport_thread(void *_t)
-{
+static void read_transport_thread(void* _t) {
     atransport *t = reinterpret_cast<atransport*>(_t);
     apacket *p;
 
@@ -244,13 +243,11 @@
     D("%s: read_transport thread is exiting", t->serial);
     kick_transport(t);
     transport_unref(t);
-    return 0;
 }
 
 // write_transport thread gets packets sent by the main thread (through send_packet()),
 // and writes to a transport (representing a usb/tcp connection).
-static void *write_transport_thread(void *_t)
-{
+static void write_transport_thread(void* _t) {
     atransport *t = reinterpret_cast<atransport*>(_t);
     apacket *p;
     int active = 0;
@@ -295,7 +292,6 @@
     D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
     kick_transport(t);
     transport_unref(t);
-    return 0;
 }
 
 static void kick_transport_locked(atransport* t) {
diff --git a/transport_local.cpp b/transport_local.cpp
index d2a375a..e6e699b 100644
--- a/transport_local.cpp
+++ b/transport_local.cpp
@@ -121,8 +121,7 @@
 }
 
 #if ADB_HOST
-static void *client_socket_thread(void *x)
-{
+static void client_socket_thread(void* x) {
     adb_thread_setname("client_socket_thread");
     D("transport: client_socket_thread() starting");
     while (true) {
@@ -135,13 +134,11 @@
         }
         sleep(1);
     }
-    return 0;
 }
 
 #else // ADB_HOST
 
-static void *server_socket_thread(void * arg)
-{
+static void server_socket_thread(void* arg) {
     int serverfd, fd;
     sockaddr_storage ss;
     sockaddr *addrp = reinterpret_cast<sockaddr*>(&ss);
@@ -174,7 +171,6 @@
         }
     }
     D("transport: server_socket_thread() exiting");
-    return 0;
 }
 
 /* This is relevant only for ADB daemon running inside the emulator. */
@@ -220,14 +216,13 @@
  *   the transport registration is completed. That's why we need to send the
  *   'start' request after the transport is registered.
  */
-static void *qemu_socket_thread(void * arg)
-{
-/* 'accept' request to the adb QEMUD service. */
-static const char _accept_req[] = "accept";
-/* 'start' request to the adb QEMUD service. */
-static const char _start_req[]  = "start";
-/* 'ok' reply from the adb QEMUD service. */
-static const char _ok_resp[]    = "ok";
+static void qemu_socket_thread(void* arg) {
+    /* 'accept' request to the adb QEMUD service. */
+    static const char _accept_req[] = "accept";
+    /* 'start' request to the adb QEMUD service. */
+    static const char _start_req[] = "start";
+    /* 'ok' reply from the adb QEMUD service. */
+    static const char _ok_resp[] = "ok";
 
     const int port = (int) (uintptr_t) arg;
     int res, fd;
@@ -247,7 +242,7 @@
          * implement adb QEMUD service. Fall back to the old TCP way. */
         D("adb service is not available. Falling back to TCP socket.");
         adb_thread_create(server_socket_thread, arg);
-        return 0;
+        return;
     }
 
     for(;;) {
@@ -275,21 +270,21 @@
             fd = qemu_pipe_open(con_name);
             if (fd < 0) {
                 D("adb service become unavailable.");
-                return 0;
+                return;
             }
         } else {
             D("Unable to send the '%s' request to ADB service.", _accept_req);
-            return 0;
+            return;
         }
     }
     D("transport: qemu_socket_thread() exiting");
-    return 0;
+    return;
 }
 #endif  // !ADB_HOST
 
 void local_init(int port)
 {
-    void* (*func)(void *);
+    adb_thread_func_t func;
     const char* debug_name = "";
 
 #if ADB_HOST
diff --git a/usb_linux.cpp b/usb_linux.cpp
index ed5d2d6..500898a 100644
--- a/usb_linux.cpp
+++ b/usb_linux.cpp
@@ -571,7 +571,7 @@
     register_usb_transport(done_usb, serial.c_str(), dev_path, done_usb->writeable);
 }
 
-static void* device_poll_thread(void* unused) {
+static void device_poll_thread(void*) {
     adb_thread_setname("device poll");
     D("Created device thread");
     while (true) {
@@ -580,7 +580,6 @@
         kick_disconnected_devices();
         sleep(1);
     }
-    return nullptr;
 }
 
 void usb_init() {
diff --git a/usb_linux_client.cpp b/usb_linux_client.cpp
index a4f1a70..c863ed2 100644
--- a/usb_linux_client.cpp
+++ b/usb_linux_client.cpp
@@ -232,10 +232,7 @@
     },
 };
 
-
-
-static void *usb_adb_open_thread(void *x)
-{
+static void usb_adb_open_thread(void* x) {
     struct usb_handle *usb = (struct usb_handle *)x;
     int fd;
 
@@ -270,7 +267,7 @@
     }
 
     // never gets here
-    return 0;
+    abort();
 }
 
 static int usb_adb_write(usb_handle *h, const void *data, int len)
@@ -434,8 +431,7 @@
     return;
 }
 
-static void *usb_ffs_open_thread(void *x)
-{
+static void usb_ffs_open_thread(void* x) {
     struct usb_handle *usb = (struct usb_handle *)x;
 
     adb_thread_setname("usb ffs open");
@@ -462,7 +458,7 @@
     }
 
     // never gets here
-    return 0;
+    abort();
 }
 
 static int usb_ffs_write(usb_handle* h, const void* data, int len) {
diff --git a/usb_osx.cpp b/usb_osx.cpp
index 148be1d..54d4c6c 100644
--- a/usb_osx.cpp
+++ b/usb_osx.cpp
@@ -400,9 +400,7 @@
     return NULL;
 }
 
-
-void* RunLoopThread(void* unused)
-{
+static void RunLoopThread(void* unused) {
     adb_thread_setname("RunLoop");
     InitUSB();
 
@@ -420,7 +418,6 @@
     IONotificationPortDestroy(notificationPort);
 
     LOG(DEBUG) << "RunLoopThread done";
-    return NULL;
 }
 
 static void usb_cleanup() {
diff --git a/usb_windows.cpp b/usb_windows.cpp
index e79008f..8ecca37 100644
--- a/usb_windows.cpp
+++ b/usb_windows.cpp
@@ -97,7 +97,7 @@
 
 /// Entry point for thread that polls (every second) for new usb interfaces.
 /// This routine calls find_devices in infinite loop.
-void* device_poll_thread(void* unused);
+static void device_poll_thread(void*);
 
 /// Initializes this module
 void usb_init();
@@ -172,7 +172,7 @@
   return 1;
 }
 
-void* device_poll_thread(void* unused) {
+void device_poll_thread(void*) {
   adb_thread_setname("Device Poll");
   D("Created device thread");
 
@@ -180,8 +180,6 @@
     find_devices();
     adb_sleep_ms(1000);
   }
-
-  return NULL;
 }
 
 static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam,
@@ -203,7 +201,7 @@
   return DefWindowProcW(hwnd, uMsg, wParam, lParam);
 }
 
-static void* _power_notification_thread(void* unused) {
+static void _power_notification_thread(void*) {
   // This uses a thread with its own window message pump to get power
   // notifications. If adb runs from a non-interactive service account, this
   // might not work (not sure). If that happens to not work, we could use
@@ -255,8 +253,6 @@
   // shutting down. Not a big deal since the whole process will be going away
   // soon anyway.
   D("Power notification thread exiting");
-
-  return NULL;
 }
 
 void usb_init() {