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
(cherry picked from commit b5fea14e13
)
This commit is contained in:
parent
7e76c89544
commit
d9db09c315
11 changed files with 77 additions and 70 deletions
|
@ -482,7 +482,7 @@ struct StdinReadArgs {
|
|||
// 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 @@ static void* stdin_read_thread_loop(void* x) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Returns a shell service string with the indicated arguments and command.
|
||||
|
|
|
@ -57,13 +57,11 @@ struct stinfo {
|
|||
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
|
||||
|
|
|
@ -198,7 +198,7 @@ class Subprocess {
|
|||
// 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 @@ int Subprocess::OpenPtyChildFd(const char* pts_name, ScopedFd* error_sfd) {
|
|||
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 @@ void* Subprocess::ThreadHandler(void* userdata) {
|
|||
|
||||
D("deleting Subprocess for PID %d", subprocess->pid());
|
||||
delete subprocess;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Subprocess::PassDataStreams() {
|
||||
|
|
|
@ -115,25 +115,26 @@ static __inline__ void adb_mutex_unlock( adb_mutex_t* lock )
|
|||
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 @@ static __inline__ bool adb_thread_detach(adb_thread_t thread) {
|
|||
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 @@ static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr,
|
|||
#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 @@ static __inline__ bool adb_thread_detach(adb_thread_t 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());
|
||||
|
|
|
@ -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 @@ TEST(sysdeps_thread, join) {
|
|||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -190,8 +190,7 @@ void send_packet(apacket *p, atransport *t)
|
|||
//
|
||||
// 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 @@ oops:
|
|||
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 @@ static void *write_transport_thread(void *_t)
|
|||
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) {
|
||||
|
|
|
@ -121,8 +121,7 @@ int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* e
|
|||
}
|
||||
|
||||
#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 @@ static void *client_socket_thread(void *x)
|
|||
}
|
||||
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 @@ static void *server_socket_thread(void * arg)
|
|||
}
|
||||
}
|
||||
D("transport: server_socket_thread() exiting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is relevant only for ADB daemon running inside the emulator. */
|
||||
|
@ -220,14 +216,13 @@ static void *server_socket_thread(void * arg)
|
|||
* 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 @@ static const char _ok_resp[] = "ok";
|
|||
* 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 @@ static const char _ok_resp[] = "ok";
|
|||
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
|
||||
|
|
|
@ -571,7 +571,7 @@ static void register_device(const char* dev_name, const char* dev_path,
|
|||
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 @@ static void* device_poll_thread(void* unused) {
|
|||
kick_disconnected_devices();
|
||||
sleep(1);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void usb_init() {
|
||||
|
|
|
@ -232,10 +232,7 @@ static const struct {
|
|||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
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 @@ static void *usb_adb_open_thread(void *x)
|
|||
}
|
||||
|
||||
// never gets here
|
||||
return 0;
|
||||
abort();
|
||||
}
|
||||
|
||||
static int usb_adb_write(usb_handle *h, const void *data, int len)
|
||||
|
@ -434,8 +431,7 @@ err:
|
|||
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 @@ static void *usb_ffs_open_thread(void *x)
|
|||
}
|
||||
|
||||
// never gets here
|
||||
return 0;
|
||||
abort();
|
||||
}
|
||||
|
||||
static int usb_ffs_write(usb_handle* h, const void* data, int len) {
|
||||
|
|
|
@ -400,9 +400,7 @@ err_get_num_ep:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* RunLoopThread(void* unused)
|
||||
{
|
||||
static void RunLoopThread(void* unused) {
|
||||
adb_thread_setname("RunLoop");
|
||||
InitUSB();
|
||||
|
||||
|
@ -420,7 +418,6 @@ void* RunLoopThread(void* unused)
|
|||
IONotificationPortDestroy(notificationPort);
|
||||
|
||||
LOG(DEBUG) << "RunLoopThread done";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usb_cleanup() {
|
||||
|
|
|
@ -97,7 +97,7 @@ static void kick_devices();
|
|||
|
||||
/// 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 @@ int register_new_device(usb_handle* handle) {
|
|||
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 @@ void* device_poll_thread(void* unused) {
|
|||
find_devices();
|
||||
adb_sleep_ms(1000);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||
|
@ -203,7 +201,7 @@ static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||
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 @@ static void* _power_notification_thread(void* unused) {
|
|||
// 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() {
|
||||
|
|
Loading…
Reference in a new issue