diff options
-rw-r--r-- | libusbmuxd/CMakeLists.txt | 2 | ||||
-rw-r--r-- | libusbmuxd/libusbmuxd.c | 98 | ||||
-rw-r--r-- | libusbmuxd/thread.c | 108 | ||||
-rw-r--r-- | libusbmuxd/thread.h | 55 |
4 files changed, 208 insertions, 55 deletions
diff --git a/libusbmuxd/CMakeLists.txt b/libusbmuxd/CMakeLists.txt index 737eb02..238d6c3 100644 --- a/libusbmuxd/CMakeLists.txt +++ b/libusbmuxd/CMakeLists.txt @@ -10,7 +10,7 @@ if (INOTIFY_FOUND) endif() endif(WANT_INOTIFY) -add_library (libusbmuxd SHARED libusbmuxd.c sock_stuff.c ${CMAKE_SOURCE_DIR}/common/utils.c) +add_library (libusbmuxd SHARED libusbmuxd.c sock_stuff.c thread.c ${CMAKE_SOURCE_DIR}/common/utils.c) find_library (PTHREAD pthread) if (HAVE_PLIST) diff --git a/libusbmuxd/libusbmuxd.c b/libusbmuxd/libusbmuxd.c index 952e680..904f1ed 100644 --- a/libusbmuxd/libusbmuxd.c +++ b/libusbmuxd/libusbmuxd.c @@ -35,7 +35,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #else #include <sys/socket.h> #include <arpa/inet.h> -#include <pthread.h> #endif #ifdef HAVE_INOTIFY @@ -62,6 +61,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "usbmuxd-proto.h" // socket utility functions #include "sock_stuff.h" +// threads and mutexes +#include "thread.h" // misc utility functions #include "utils.h" @@ -75,23 +76,25 @@ static int handle_events = 0; static usbmuxd_event_cb_t event_cb = NULL; static void* event_user_data = NULL; -#ifdef WIN32 -HANDLE devmon = NULL; -CRITICAL_SECTION mutex; -static int mutex_initialized = 0; -#define LOCK if (!mutex_initialized) { InitializeCriticalSection(&mutex); mutex_initialized = 1; } EnterCriticalSection(&mutex); -#define UNLOCK LeaveCriticalSection(&mutex); -#else -pthread_t devmon = 0; -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -#define LOCK pthread_mutex_lock(&mutex) -#define UNLOCK pthread_mutex_unlock(&mutex) -#endif + +static thread_t devmon = NULL; +static mutex_t mutex; + static int listenfd = -1; static int use_tag = 0; static int proto_version = 0; +static __attribute__((constructor)) void libusbmuxd_library_init() +{ + mutex_init(&mutex); +} + +static __attribute__((destructor)) void libusbmuxd_library_deinit() +{ + mutex_destroy(&mutex); +} + /** * Finds a device info record by its handle. * if the record is not found, NULL is returned. @@ -510,15 +513,15 @@ retry: } use_tag++; - LOCK; + mutex_lock(&mutex); if (send_listen_packet(sfd, use_tag) <= 0) { - UNLOCK; + mutex_unlock(&mutex); DEBUG(1, "%s: ERROR: could not send listen packet\n", __func__); close_socket(sfd); return -1; } if (usbmuxd_get_result(sfd, use_tag, &res) && (res != 0)) { - UNLOCK; + mutex_unlock(&mutex); close_socket(sfd); #ifdef HAVE_PLIST if ((res == RESULT_BADVERSION) && (proto_version != 1)) { @@ -529,7 +532,7 @@ retry: DEBUG(1, "%s: ERROR: did not get OK but %d\n", __func__, res); return -1; } - UNLOCK; + mutex_unlock(&mutex); return sfd; } @@ -621,8 +624,8 @@ static void *device_monitor(void *data) { collection_init(&devices); -#ifndef WIN32 - pthread_cleanup_push(device_monitor_cleanup, NULL); +#ifdef THREAD_CLEANUP_SUPPORTED + thread_cleanup_push(device_monitor_cleanup, NULL); #endif while (handle_events) { @@ -639,8 +642,8 @@ static void *device_monitor(void *data) } } -#ifndef WIN32 - pthread_cleanup_pop(1); +#ifdef THREAD_CLEANUP_SUPPORTED + thread_cleanup_pop(1); #else device_monitor_cleanup(NULL); #endif @@ -650,48 +653,35 @@ static void *device_monitor(void *data) int usbmuxd_init() { int res = 0; - LOCK; + mutex_lock(&mutex); handle_events = 1; -#ifdef WIN32 - devmon = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)device_monitor, NULL, 0, NULL); - if (devmon == NULL) { - res = GetLastError(); - } -#else - res = pthread_create(&devmon, NULL, device_monitor, NULL); -#endif + res = thread_create(&devmon, device_monitor, NULL); if (res != 0) { DEBUG(1, "%s: ERROR: Could not start device watcher thread!\n", __func__); handle_events = 0; - UNLOCK; + mutex_unlock(&mutex); return res; } struct timespec ts = {0, 250000000}; nanosleep(&ts, NULL); libusbmuxd_initialized = 1; - UNLOCK; + mutex_unlock(&mutex); return 0; } int usbmuxd_deinit() { - LOCK; + mutex_lock(&mutex); handle_events = 0; shutdown_socket(listenfd, SHUT_RDWR); -#ifdef WIN32 - if (devmon != NULL) { - WaitForSingleObject(devmon, INFINITE); - } -#else - if (pthread_kill(devmon, 0) == 0) { - pthread_cancel(devmon); - pthread_join(devmon, NULL); + if (thread_valid(devmon)) { + thread_cancel(devmon); + thread_join(devmon); } -#endif libusbmuxd_initialized = 0; - UNLOCK; + mutex_unlock(&mutex); return 0; } @@ -704,9 +694,9 @@ int usbmuxd_subscribe(usbmuxd_event_cb_t callback, void *user_data) event_user_data = user_data; int is_initialized = 0; - LOCK; + mutex_lock(&mutex); is_initialized = libusbmuxd_initialized; - UNLOCK; + mutex_unlock(&mutex); if (!is_initialized) { usbmuxd_init(); @@ -751,14 +741,14 @@ retry: } use_tag++; - //LOCK; + //mutex_lock(&mutex); if (send_listen_packet(sfd, use_tag) > 0) { res = -1; // get response if (usbmuxd_get_result(sfd, use_tag, &res) && (res == 0)) { listen_success = 1; } else { - //UNLOCK; + //mutex_unlock(&mutex); close_socket(sfd); #ifdef HAVE_PLIST if ((res == RESULT_BADVERSION) && (proto_version != 1)) { @@ -766,13 +756,13 @@ retry: goto retry; } #endif - DEBUG(1, "%s: Did not get response to scan request (with result=0)...\n", __func__); - return res; + DEBUG(1, "%s: Did not get response to scan request with result 0, instead got result %d ...\n", __func__, res); + return -1; } } if (!listen_success) { - //UNLOCK; + //mutex_unlock(&mutex); DEBUG(1, "%s: Could not send listen request!\n", __func__); return -1; } @@ -786,7 +776,7 @@ retry: dev = payload; usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t)); if (!devinfo) { - //UNLOCK; + //mutex_unlock(&mutex); DEBUG(1, "%s: Out of memory!\n", __func__); free(payload); return -1; @@ -830,7 +820,7 @@ retry: break; } } - //UNLOCK; + //mutex_unlock(&mutex); // explicitly close connection close_socket(sfd); @@ -871,9 +861,9 @@ int usbmuxd_get_device_by_udid(const char *udid, usbmuxd_device_info_t *device) } int is_initialized = 0; - LOCK; + mutex_lock(&mutex); is_initialized = libusbmuxd_initialized; - UNLOCK; + mutex_unlock(&mutex); if (!is_initialized) { usbmuxd_init(); diff --git a/libusbmuxd/thread.c b/libusbmuxd/thread.c new file mode 100644 index 0000000..d25a4cf --- /dev/null +++ b/libusbmuxd/thread.c @@ -0,0 +1,108 @@ +/* + * thread.c + * + * Copyright (c) 2012 Martin Szulecki All Rights Reserved. + * Copyright (c) 2012 Nikias Bassen All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "thread.h" + +int thread_create(thread_t *thread, thread_func_t thread_func, void* data) +{ +#ifdef WIN32 + HANDLE th = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL); + if (th == NULL) { + return -1; + } + *thread = th; + return 0; +#else + int res = pthread_create(thread, NULL, thread_func, data); + return res; +#endif +} + +void thread_join(thread_t thread) +{ + /* wait for thread to complete */ +#ifdef WIN32 + WaitForSingleObject(thread, INFINITE); +#else + pthread_join(thread, NULL); +#endif +} + +int thread_valid(thread_t thread) +{ +#ifdef WIN32 + if (!thread) { + return 0; + } + if (WaitForSingleObject(thread, 0) == WAIT_OBJECT_0) { + return 0; + } else { + return 1; + } +#else + return (pthread_kill(thread, 0) == 0); +#endif +} + +void thread_cancel(thread_t thread) +{ +#ifdef WIN32 + // FIXME? +#else + pthread_cancel(thread); +#endif +} + +void mutex_init(mutex_t* mutex) +{ +#ifdef WIN32 + InitializeCriticalSection(mutex); +#else + pthread_mutex_init(mutex, NULL); +#endif +} + +void mutex_destroy(mutex_t* mutex) +{ +#ifdef WIN32 + DeleteCriticalSection(mutex); +#else + pthread_mutex_destroy(mutex); +#endif +} + +void mutex_lock(mutex_t* mutex) +{ +#ifdef WIN32 + EnterCriticalSection(mutex); +#else + pthread_mutex_lock(mutex); +#endif +} + +void mutex_unlock(mutex_t* mutex) +{ +#ifdef WIN32 + LeaveCriticalSection(mutex); +#else + pthread_mutex_unlock(mutex); +#endif +} diff --git a/libusbmuxd/thread.h b/libusbmuxd/thread.h new file mode 100644 index 0000000..af0436b --- /dev/null +++ b/libusbmuxd/thread.h @@ -0,0 +1,55 @@ +/* + * thread.h + * + * Copyright (c) 2012 Martin Szulecki All Rights Reserved. + * Copyright (c) 2012 Nikias Bassen All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __THREAD_H +#define __THREAD_H + +#ifdef WIN32 +#include <windows.h> +typedef HANDLE thread_t; +typedef CRITICAL_SECTION mutex_t; +#else +#include <pthread.h> +typedef pthread_t thread_t; +typedef pthread_mutex_t mutex_t; +#endif + +typedef void* (*thread_func_t)(void* data); + +int thread_create(thread_t* thread, thread_func_t thread_func, void* data); +void thread_join(thread_t thread); +int thread_valid(thread_t thread); +void thread_cancel(thread_t thread); + +#ifdef WIN32 +#undef THREAD_CLEANUP_SUPPORTED +#else +#define THREAD_CLEANUP_SUPPORTED 1 +#define thread_cleanup_push(r, a) pthread_cleanup_push(r, a) +#define thread_cleanup_pop(e) pthread_cleanup_pop(e) +#endif + +void mutex_init(mutex_t* mutex); +void mutex_destroy(mutex_t* mutex); +void mutex_lock(mutex_t* mutex); +void mutex_unlock(mutex_t* mutex); + +#endif |