adb: kill adb_thread_{create, join, detach, exit}.
am: 0f3312aa43

Change-Id: I5e0324b33d40f873d196946cee7591de0b7b949c
diff --git a/client/usb_linux.cpp b/client/usb_linux.cpp
index 13b7674..3a45dbd 100644
--- a/client/usb_linux.cpp
+++ b/client/usb_linux.cpp
@@ -574,7 +574,7 @@
     register_usb_transport(done_usb, serial.c_str(), dev_path, done_usb->writeable);
 }
 
-static void device_poll_thread(void*) {
+static void device_poll_thread() {
     adb_thread_setname("device poll");
     D("Created device thread");
     while (true) {
@@ -593,8 +593,6 @@
     actions.sa_handler = [](int) {};
     sigaction(SIGALRM, &actions, nullptr);
 
-    if (!adb_thread_create(device_poll_thread, nullptr)) {
-        fatal_errno("cannot create device_poll thread");
-    }
+    std::thread(device_poll_thread).detach();
 }
 } // namespace native
diff --git a/client/usb_osx.cpp b/client/usb_osx.cpp
index d4fc7c0..8713b2c 100644
--- a/client/usb_osx.cpp
+++ b/client/usb_osx.cpp
@@ -405,7 +405,7 @@
 
 std::mutex& operate_device_lock = *new std::mutex();
 
-static void RunLoopThread(void* unused) {
+static void RunLoopThread() {
     adb_thread_setname("RunLoop");
 
     VLOG(USB) << "RunLoopThread started";
@@ -436,9 +436,7 @@
 
         usb_inited_flag = false;
 
-        if (!adb_thread_create(RunLoopThread, nullptr)) {
-            fatal_errno("cannot create RunLoop thread");
-        }
+        std::thread(RunLoopThread).detach();
 
         // Wait for initialization to finish
         while (!usb_inited_flag) {
diff --git a/client/usb_windows.cpp b/client/usb_windows.cpp
index 640e91e..9e00a5d 100644
--- a/client/usb_windows.cpp
+++ b/client/usb_windows.cpp
@@ -103,7 +103,7 @@
 
 /// Entry point for thread that polls (every second) for new usb interfaces.
 /// This routine calls find_devices in infinite loop.
-static void device_poll_thread(void*);
+static void device_poll_thread();
 
 /// Initializes this module
 void usb_init();
@@ -174,7 +174,7 @@
   return 1;
 }
 
-void device_poll_thread(void*) {
+void device_poll_thread() {
   adb_thread_setname("Device Poll");
   D("Created device thread");
 
@@ -203,7 +203,7 @@
   return DefWindowProcW(hwnd, uMsg, wParam, lParam);
 }
 
-static void _power_notification_thread(void*) {
+static void _power_notification_thread() {
   // 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
@@ -258,12 +258,8 @@
 }
 
 void usb_init() {
-  if (!adb_thread_create(device_poll_thread, nullptr)) {
-    fatal_errno("cannot create device poll thread");
-  }
-  if (!adb_thread_create(_power_notification_thread, nullptr)) {
-    fatal_errno("cannot create power notification thread");
-  }
+  std::thread(device_poll_thread).detach();
+  std::thread(_power_notification_thread).detach();
 }
 
 usb_handle* do_usb_open(const wchar_t* interface_name) {
diff --git a/commandline.cpp b/commandline.cpp
index ed6693c..7702b0e 100644
--- a/commandline.cpp
+++ b/commandline.cpp
@@ -655,13 +655,8 @@
 #endif
 
     // TODO: combine read_and_dump with stdin_read_thread to make life simpler?
-    int exit_code = 1;
-    if (!adb_thread_create(stdin_read_thread_loop, args)) {
-        PLOG(ERROR) << "error starting stdin read thread";
-        delete args;
-    } else {
-        exit_code = read_and_dump(fd, use_shell_protocol);
-    }
+    std::thread(stdin_read_thread_loop, args).detach();
+    int exit_code = read_and_dump(fd, use_shell_protocol);
 
     // TODO: properly exit stdin_read_thread_loop and close |fd|.
 
diff --git a/daemon/mdns.cpp b/daemon/mdns.cpp
index 7811143..849378f 100644
--- a/daemon/mdns.cpp
+++ b/daemon/mdns.cpp
@@ -17,12 +17,14 @@
 #include "adb_mdns.h"
 #include "sysdeps.h"
 
-#include <chrono>
 #include <dns_sd.h>
 #include <endian.h>
-#include <mutex>
 #include <unistd.h>
 
+#include <chrono>
+#include <mutex>
+#include <thread>
+
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 
@@ -58,7 +60,7 @@
     }
 }
 
-static void setup_mdns_thread(void* /* unused */) {
+static void setup_mdns_thread() {
     start_mdns();
     std::lock_guard<std::mutex> lock(mdns_lock);
 
@@ -88,7 +90,7 @@
 
 void setup_mdns(int port_in) {
     port = port_in;
-    adb_thread_create(setup_mdns_thread, nullptr, nullptr);
+    std::thread(setup_mdns_thread).detach();
 
     // TODO: Make this more robust against a hard kill.
     atexit(teardown_mdns);
diff --git a/daemon/usb.cpp b/daemon/usb.cpp
index 92e9039..7e46b02 100644
--- a/daemon/usb.cpp
+++ b/daemon/usb.cpp
@@ -451,9 +451,7 @@
     h->close = usb_ffs_close;
 
     D("[ usb_init - starting thread ]");
-    if (!adb_thread_create(usb_ffs_open_thread, h)) {
-        fatal_errno("[ cannot create usb thread ]\n");
-    }
+    std::thread(usb_ffs_open_thread, h).detach();
 }
 
 void usb_init() {
diff --git a/fdevent_test.cpp b/fdevent_test.cpp
index c933ed5..bdb973a 100644
--- a/fdevent_test.cpp
+++ b/fdevent_test.cpp
@@ -21,6 +21,7 @@
 #include <limits>
 #include <queue>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include "adb_io.h"
@@ -77,9 +78,9 @@
 };
 
 TEST_F(FdeventTest, fdevent_terminate) {
-    adb_thread_t thread;
     PrepareThread();
-    ASSERT_TRUE(adb_thread_create([](void*) { fdevent_loop(); }, nullptr, &thread));
+
+    std::thread thread(fdevent_loop);
     TerminateThread(thread);
 }
 
@@ -112,7 +113,6 @@
     int fd_pair2[2];
     ASSERT_EQ(0, adb_socketpair(fd_pair1));
     ASSERT_EQ(0, adb_socketpair(fd_pair2));
-    adb_thread_t thread;
     ThreadArg thread_arg;
     thread_arg.first_read_fd = fd_pair1[0];
     thread_arg.last_write_fd = fd_pair2[1];
@@ -121,8 +121,7 @@
     int reader = fd_pair2[0];
 
     PrepareThread();
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(FdEventThreadFunc), &thread_arg,
-                                  &thread));
+    std::thread thread(FdEventThreadFunc, &thread_arg);
 
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
@@ -152,7 +151,7 @@
     }
 }
 
-static void InvalidFdThreadFunc(void*) {
+static void InvalidFdThreadFunc() {
     const int INVALID_READ_FD = std::numeric_limits<int>::max() - 1;
     size_t happened_event_count = 0;
     InvalidFdArg read_arg;
@@ -171,7 +170,6 @@
 }
 
 TEST_F(FdeventTest, invalid_fd) {
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(InvalidFdThreadFunc, nullptr, &thread));
-    ASSERT_TRUE(adb_thread_join(thread));
+    std::thread thread(InvalidFdThreadFunc);
+    thread.join();
 }
diff --git a/fdevent_test.h b/fdevent_test.h
index ef65b74..f4215ae 100644
--- a/fdevent_test.h
+++ b/fdevent_test.h
@@ -16,6 +16,8 @@
 
 #include <gtest/gtest.h>
 
+#include <thread>
+
 #include "socket.h"
 #include "sysdeps.h"
 
@@ -59,10 +61,10 @@
 #endif
     }
 
-    void TerminateThread(adb_thread_t thread) {
+    void TerminateThread(std::thread& thread) {
         fdevent_terminate_loop();
         ASSERT_TRUE(WriteFdExactly(dummy, "", 1));
-        ASSERT_TRUE(adb_thread_join(thread));
+        thread.join();
         ASSERT_EQ(0, adb_close(dummy));
     }
 };
diff --git a/services.cpp b/services.cpp
index 47f0a03..f764c52 100644
--- a/services.cpp
+++ b/services.cpp
@@ -31,6 +31,8 @@
 #include <unistd.h>
 #endif
 
+#include <thread>
+
 #include <android-base/file.h>
 #include <android-base/parsenetaddress.h>
 #include <android-base/stringprintf.h>
@@ -259,13 +261,7 @@
     sti->cookie = cookie;
     sti->fd = s[1];
 
-    if (!adb_thread_create(service_bootstrap_func, sti)) {
-        free(sti);
-        adb_close(s[0]);
-        adb_close(s[1]);
-        printf("cannot create service thread\n");
-        return -1;
-    }
+    std::thread(service_bootstrap_func, sti).detach();
 
     D("service thread started, %d:%d",s[0], s[1]);
     return s[0];
diff --git a/shell_service.cpp b/shell_service.cpp
index d4f334b..ee821f8 100644
--- a/shell_service.cpp
+++ b/shell_service.cpp
@@ -90,6 +90,7 @@
 
 #include <memory>
 #include <string>
+#include <thread>
 #include <unordered_map>
 #include <vector>
 
@@ -392,12 +393,7 @@
 
 bool Subprocess::StartThread(std::unique_ptr<Subprocess> subprocess, std::string* error) {
     Subprocess* raw = subprocess.release();
-    if (!adb_thread_create(ThreadHandler, raw)) {
-        *error =
-            android::base::StringPrintf("failed to create subprocess thread: %s", strerror(errno));
-        kill(raw->pid_, SIGKILL);
-        return false;
-    }
+    std::thread(ThreadHandler, raw).detach();
 
     return true;
 }
diff --git a/socket_test.cpp b/socket_test.cpp
index f56f7f7..f7c66db 100644
--- a/socket_test.cpp
+++ b/socket_test.cpp
@@ -42,10 +42,6 @@
 
 class LocalSocketTest : public FdeventTest {};
 
-static void FdEventThreadFunc(void*) {
-    fdevent_loop();
-}
-
 constexpr auto SLEEP_FOR_FDEVENT = 100ms;
 
 TEST_F(LocalSocketTest, smoke) {
@@ -88,8 +84,7 @@
     connect(prev_tail, end);
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(FdEventThreadFunc, nullptr, &thread));
+    std::thread thread(fdevent_loop);
 
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
@@ -152,9 +147,7 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
-                                  &arg, &thread));
+    std::thread thread(CloseWithPacketThreadFunc, &arg);
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
@@ -177,9 +170,7 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
-                                  &arg, &thread));
+    std::thread thread(CloseWithPacketThreadFunc, &arg);
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
@@ -211,10 +202,7 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
-                                  &arg, &thread));
-
+    std::thread thread(CloseWithPacketThreadFunc, &arg);
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(2u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
@@ -252,9 +240,7 @@
     int listen_fd = network_inaddr_any_server(5038, SOCK_STREAM, &error);
     ASSERT_GE(listen_fd, 0);
 
-    adb_thread_t client_thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(ClientThreadFunc), nullptr,
-                                  &client_thread));
+    std::thread client_thread(ClientThreadFunc);
 
     int accept_fd = adb_socket_accept(listen_fd, nullptr, nullptr);
     ASSERT_GE(accept_fd, 0);
@@ -262,16 +248,14 @@
     arg.socket_fd = accept_fd;
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseRdHupSocketThreadFunc),
-                                  &arg, &thread));
+    std::thread thread(CloseRdHupSocketThreadFunc, &arg);
 
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Wait until the client closes its socket.
-    ASSERT_TRUE(adb_thread_join(client_thread));
+    client_thread.join();
 
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
diff --git a/sysdeps.h b/sysdeps.h
index 5cd0cd1..49c7847 100644
--- a/sysdeps.h
+++ b/sysdeps.h
@@ -99,64 +99,6 @@
     return c == '\\' || c == '/';
 }
 
-typedef void (*adb_thread_func_t)(void* arg);
-typedef HANDLE adb_thread_t;
-
-struct adb_winthread_args {
-    adb_thread_func_t func;
-    void* arg;
-};
-
-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) {
-    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);
-        } else {
-            CloseHandle(thread);
-        }
-        return true;
-    }
-    return false;
-}
-
-static __inline__ bool adb_thread_join(adb_thread_t thread) {
-    switch (WaitForSingleObject(thread, INFINITE)) {
-        case WAIT_OBJECT_0:
-            CloseHandle(thread);
-            return true;
-
-        case WAIT_FAILED:
-            fprintf(stderr, "adb_thread_join failed: %s\n",
-                    android::base::SystemErrorCodeToString(GetLastError()).c_str());
-            break;
-
-        default:
-            abort();
-    }
-
-    return false;
-}
-
-static __inline__ bool adb_thread_detach(adb_thread_t thread) {
-    CloseHandle(thread);
-    return true;
-}
-
-static __inline__ void __attribute__((noreturn)) adb_thread_exit() {
-    _endthreadex(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
@@ -164,14 +106,6 @@
     return 0;
 }
 
-static __inline__ adb_thread_t adb_thread_self() {
-    return GetCurrentThread();
-}
-
-static __inline__ bool adb_thread_equal(adb_thread_t lhs, adb_thread_t rhs) {
-    return GetThreadId(lhs) == GetThreadId(rhs);
-}
-
 static __inline__  unsigned long adb_thread_id()
 {
     return GetCurrentThreadId();
@@ -644,55 +578,6 @@
 #define  unix_write  adb_write
 #define  unix_close  adb_close
 
-// 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);
-    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;
-        }
-        return true;
-    }
-    return false;
-}
-
-static __inline__ bool adb_thread_join(adb_thread_t thread) {
-    errno = pthread_join(thread, nullptr);
-    return errno == 0;
-}
-
-static __inline__ bool adb_thread_detach(adb_thread_t thread) {
-    errno = pthread_detach(thread);
-    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 9007e75..edb0fb3 100644
--- a/sysdeps_test.cpp
+++ b/sysdeps_test.cpp
@@ -25,54 +25,6 @@
 #include "sysdeps.h"
 #include "sysdeps/chrono.h"
 
-static void increment_atomic_int(void* c) {
-    std::this_thread::sleep_for(1s);
-    reinterpret_cast<std::atomic<int>*>(c)->fetch_add(1);
-}
-
-TEST(sysdeps_thread, smoke) {
-    std::atomic<int> counter(0);
-
-    for (int i = 0; i < 100; ++i) {
-        ASSERT_TRUE(adb_thread_create(increment_atomic_int, &counter));
-    }
-
-    std::this_thread::sleep_for(2s);
-    ASSERT_EQ(100, counter.load());
-}
-
-TEST(sysdeps_thread, join) {
-    std::atomic<int> counter(0);
-    std::vector<adb_thread_t> threads(500);
-    for (size_t i = 0; i < threads.size(); ++i) {
-        ASSERT_TRUE(adb_thread_create(increment_atomic_int, &counter, &threads[i]));
-    }
-
-    int current = counter.load();
-    ASSERT_GE(current, 0);
-    // Make sure that adb_thread_create actually creates threads, and doesn't do something silly
-    // like synchronously run the function passed in. The sleep in increment_atomic_int should be
-    // enough to keep this from being flakey.
-    ASSERT_LT(current, 500);
-
-    for (const auto& thread : threads) {
-        ASSERT_TRUE(adb_thread_join(thread));
-    }
-
-    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));
-}
-
 TEST(sysdeps_socketpair, smoke) {
     int fds[2];
     ASSERT_EQ(0, adb_socketpair(fds)) << strerror(errno);
@@ -254,13 +206,13 @@
     static std::mutex &m = *new std::mutex();
     m.lock();
     ASSERT_FALSE(m.try_lock());
-    adb_thread_create([](void*) {
+    std::thread thread([]() {
         ASSERT_FALSE(m.try_lock());
         m.lock();
         finished.store(true);
         std::this_thread::sleep_for(200ms);
         m.unlock();
-    }, nullptr);
+    });
 
     ASSERT_FALSE(finished.load());
     std::this_thread::sleep_for(100ms);
@@ -270,6 +222,8 @@
     m.lock();
     ASSERT_TRUE(finished.load());
     m.unlock();
+
+    thread.join();
 }
 
 TEST(sysdeps_mutex, recursive_mutex_smoke) {
@@ -279,12 +233,12 @@
     ASSERT_TRUE(m.try_lock());
     m.unlock();
 
-    adb_thread_create([](void*) {
+    std::thread thread([]() {
         ASSERT_FALSE(m.try_lock());
         m.lock();
         std::this_thread::sleep_for(500ms);
         m.unlock();
-    }, nullptr);
+    });
 
     std::this_thread::sleep_for(100ms);
     m.unlock();
@@ -292,6 +246,8 @@
     ASSERT_FALSE(m.try_lock());
     m.lock();
     m.unlock();
+
+    thread.join();
 }
 
 TEST(sysdeps_condition_variable, smoke) {
@@ -300,14 +256,16 @@
     static volatile bool flag = false;
 
     std::unique_lock<std::mutex> lock(m);
-    adb_thread_create([](void*) {
+    std::thread thread([]() {
         m.lock();
         flag = true;
         cond.notify_one();
         m.unlock();
-    }, nullptr);
+    });
 
     while (!flag) {
         cond.wait(lock);
     }
+
+    thread.join();
 }
diff --git a/transport.cpp b/transport.cpp
index c951f5b..4686841 100644
--- a/transport.cpp
+++ b/transport.cpp
@@ -29,6 +29,7 @@
 #include <algorithm>
 #include <list>
 #include <mutex>
+#include <thread>
 
 #include <android-base/logging.h>
 #include <android-base/parsenetaddress.h>
@@ -509,13 +510,8 @@
 
         fdevent_set(&(t->transport_fde), FDE_READ);
 
-        if (!adb_thread_create(write_transport_thread, t)) {
-            fatal_errno("cannot create write_transport thread");
-        }
-
-        if (!adb_thread_create(read_transport_thread, t)) {
-            fatal_errno("cannot create read_transport thread");
-        }
+        std::thread(write_transport_thread, t).detach();
+        std::thread(read_transport_thread, t).detach();
     }
 
     {
diff --git a/transport_local.cpp b/transport_local.cpp
index 4198a52..408f51f 100644
--- a/transport_local.cpp
+++ b/transport_local.cpp
@@ -199,7 +199,7 @@
 std::mutex &retry_ports_lock = *new std::mutex;
 std::condition_variable &retry_ports_cond = *new std::condition_variable;
 
-static void client_socket_thread(void* x) {
+static void client_socket_thread(int) {
     adb_thread_setname("client_socket_thread");
     D("transport: client_socket_thread() starting");
     PollAllLocalPortsForEmulator();
@@ -244,9 +244,8 @@
 
 #else // ADB_HOST
 
-static void server_socket_thread(void* arg) {
+static void server_socket_thread(int port) {
     int serverfd, fd;
-    int port = (int) (uintptr_t) arg;
 
     adb_thread_setname("server socket");
     D("transport: server_socket_thread() starting");
@@ -325,7 +324,7 @@
  *   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) {
+static void qemu_socket_thread(int port) {
     /* 'accept' request to the adb QEMUD service. */
     static const char _accept_req[] = "accept";
     /* 'start' request to the adb QEMUD service. */
@@ -333,7 +332,6 @@
     /* 'ok' reply from the adb QEMUD service. */
     static const char _ok_resp[] = "ok";
 
-    const int port = (int) (uintptr_t) arg;
     int fd;
     char tmp[256];
     char con_name[32];
@@ -350,7 +348,7 @@
         /* This could be an older version of the emulator, that doesn't
          * 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);
+        std::thread(server_socket_thread, port).detach();
         return;
     }
 
@@ -394,7 +392,7 @@
 
 void local_init(int port)
 {
-    adb_thread_func_t func;
+    void (*func)(int);
     const char* debug_name = "";
 
 #if ADB_HOST
@@ -414,9 +412,7 @@
 #endif // !ADB_HOST
 
     D("transport: local %s init", debug_name);
-    if (!adb_thread_create(func, (void *) (uintptr_t) port)) {
-        fatal_errno("cannot create local socket %s thread", debug_name);
-    }
+    std::thread(func, port).detach();
 }
 
 static void remote_kick(atransport *t)