summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/Makefile.am1
-rw-r--r--common/thread.c110
-rw-r--r--common/thread.h57
-rw-r--r--src/client.c33
-rw-r--r--src/device.c66
-rw-r--r--src/preflight.c14
6 files changed, 223 insertions, 58 deletions
diff --git a/common/Makefile.am b/common/Makefile.am
index b4a65b9..fee26ca 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -7,4 +7,5 @@ noinst_LTLIBRARIES = libinternalcommon.la
libinternalcommon_la_LIBADD =
libinternalcommon_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined
libinternalcommon_la_SOURCES = \
+ thread.c thread.h \
utils.c utils.h
diff --git a/common/thread.c b/common/thread.c
new file mode 100644
index 0000000..a40929b
--- /dev/null
+++ b/common/thread.c
@@ -0,0 +1,110 @@
+/*
+ * 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
+}
+
+int thread_detach(thread_t thread)
+{
+#ifdef WIN32
+ CloseHandle(thread);
+ return 0;
+#else
+ int res = pthread_detach(thread);
+ 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
+}
+
+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
+}
+
+void thread_once(thread_once_t *once_control, void (*init_routine)(void))
+{
+#ifdef WIN32
+ while (InterlockedExchange(&(once_control->lock), 1) != 0) {
+ Sleep(1);
+ }
+ if (!once_control->state) {
+ once_control->state = 1;
+ init_routine();
+ }
+ InterlockedExchange(&(once_control->lock), 0);
+#else
+ pthread_once(once_control, init_routine);
+#endif
+}
diff --git a/common/thread.h b/common/thread.h
new file mode 100644
index 0000000..a271b45
--- /dev/null
+++ b/common/thread.h
@@ -0,0 +1,57 @@
+/*
+ * 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;
+typedef volatile struct {
+ LONG lock;
+ int state;
+} thread_once_t;
+#define THREAD_ONCE_INIT {0, 0}
+#define THREAD_ID GetCurrentThreadId()
+#else
+#include <pthread.h>
+typedef pthread_t thread_t;
+typedef pthread_mutex_t mutex_t;
+typedef pthread_once_t thread_once_t;
+#define THREAD_ONCE_INIT PTHREAD_ONCE_INIT
+#define THREAD_ID pthread_self()
+#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_detach(thread_t thread);
+
+void mutex_init(mutex_t* mutex);
+void mutex_destroy(mutex_t* mutex);
+void mutex_lock(mutex_t* mutex);
+void mutex_unlock(mutex_t* mutex);
+
+void thread_once(thread_once_t *once_control, void (*init_routine)(void));
+
+#endif
diff --git a/src/client.c b/src/client.c
index 4ec4025..baef4c8 100644
--- a/src/client.c
+++ b/src/client.c
@@ -32,7 +32,6 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
-#include <pthread.h>
#include <fcntl.h>
#include <plist/plist.h>
@@ -43,6 +42,8 @@
#include "device.h"
#include "conf.h"
+#include "common/thread.h"
+
#define CMD_BUF_SIZE 0x10000
#define REPLY_BUF_SIZE 0x10000
@@ -71,7 +72,7 @@ struct mux_client {
};
static struct collection client_list;
-pthread_mutex_t client_list_mutex;
+mutex_t client_list_mutex;
/**
* Receive raw data from the client socket.
@@ -185,9 +186,9 @@ int client_accept(int listenfd)
client->state = CLIENT_COMMAND;
client->events = POLLIN;
- pthread_mutex_lock(&client_list_mutex);
+ mutex_lock(&client_list_mutex);
collection_add(&client_list, client);
- pthread_mutex_unlock(&client_list_mutex);
+ mutex_unlock(&client_list_mutex);
#ifdef SO_PEERCRED
if (log_level >= LL_INFO) {
@@ -220,19 +221,19 @@ void client_close(struct mux_client *client)
free(client->ob_buf);
if(client->ib_buf)
free(client->ib_buf);
- pthread_mutex_lock(&client_list_mutex);
+ mutex_lock(&client_list_mutex);
collection_remove(&client_list, client);
- pthread_mutex_unlock(&client_list_mutex);
+ mutex_unlock(&client_list_mutex);
free(client);
}
void client_get_fds(struct fdlist *list)
{
- pthread_mutex_lock(&client_list_mutex);
+ mutex_lock(&client_list_mutex);
FOREACH(struct mux_client *client, &client_list) {
fdlist_add(list, FD_CLIENT, client->fd, client->events);
} ENDFOREACH
- pthread_mutex_unlock(&client_list_mutex);
+ mutex_unlock(&client_list_mutex);
}
static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length)
@@ -758,14 +759,14 @@ static void process_recv(struct mux_client *client)
void client_process(int fd, short events)
{
struct mux_client *client = NULL;
- pthread_mutex_lock(&client_list_mutex);
+ mutex_lock(&client_list_mutex);
FOREACH(struct mux_client *lc, &client_list) {
if(lc->fd == fd) {
client = lc;
break;
}
} ENDFOREACH
- pthread_mutex_unlock(&client_list_mutex);
+ mutex_unlock(&client_list_mutex);
if(!client) {
usbmuxd_log(LL_INFO, "client_process: fd %d not found in client list", fd);
@@ -787,33 +788,33 @@ void client_process(int fd, short events)
void client_device_add(struct device_info *dev)
{
- pthread_mutex_lock(&client_list_mutex);
+ mutex_lock(&client_list_mutex);
usbmuxd_log(LL_DEBUG, "client_device_add: id %d, location 0x%x, serial %s", dev->id, dev->location, dev->serial);
device_set_visible(dev->id);
FOREACH(struct mux_client *client, &client_list) {
if(client->state == CLIENT_LISTEN)
notify_device_add(client, dev);
} ENDFOREACH
- pthread_mutex_unlock(&client_list_mutex);
+ mutex_unlock(&client_list_mutex);
}
void client_device_remove(int device_id)
{
- pthread_mutex_lock(&client_list_mutex);
+ mutex_lock(&client_list_mutex);
uint32_t id = device_id;
usbmuxd_log(LL_DEBUG, "client_device_remove: id %d", device_id);
FOREACH(struct mux_client *client, &client_list) {
if(client->state == CLIENT_LISTEN)
notify_device_remove(client, id);
} ENDFOREACH
- pthread_mutex_unlock(&client_list_mutex);
+ mutex_unlock(&client_list_mutex);
}
void client_init(void)
{
usbmuxd_log(LL_DEBUG, "client_init");
collection_init(&client_list);
- pthread_mutex_init(&client_list_mutex, NULL);
+ mutex_init(&client_list_mutex);
}
void client_shutdown(void)
@@ -822,6 +823,6 @@ void client_shutdown(void)
FOREACH(struct mux_client *client, &client_list) {
client_close(client);
} ENDFOREACH
- pthread_mutex_destroy(&client_list_mutex);
+ mutex_destroy(&client_list_mutex);
collection_free(&client_list);
}
diff --git a/src/device.c b/src/device.c
index ddd1d4a..4188b95 100644
--- a/src/device.c
+++ b/src/device.c
@@ -31,12 +31,12 @@
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
-#include <pthread.h>
#include "device.h"
#include "client.h"
#include "preflight.h"
#include "usb.h"
#include "log.h"
+#include "common/thread.h"
int next_device_id;
@@ -125,19 +125,19 @@ struct mux_device
};
static struct collection device_list;
-pthread_mutex_t device_list_mutex;
+mutex_t device_list_mutex;
static struct mux_device* get_mux_device_for_id(int device_id)
{
struct mux_device *dev = NULL;
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *cdev, &device_list) {
if(cdev->id == device_id) {
dev = cdev;
break;
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
return dev;
}
@@ -145,7 +145,7 @@ static struct mux_device* get_mux_device_for_id(int device_id)
static struct mux_connection* get_mux_connection(int device_id, struct mux_client *client)
{
struct mux_connection *conn = NULL;
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
if(dev->id == device_id) {
FOREACH(struct mux_connection *lconn, &dev->connections) {
@@ -157,7 +157,7 @@ static struct mux_connection* get_mux_connection(int device_id, struct mux_clien
break;
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
return conn;
}
@@ -166,7 +166,7 @@ static int get_next_device_id(void)
{
while(1) {
int ok = 1;
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
if(dev->id == next_device_id) {
next_device_id++;
@@ -174,7 +174,7 @@ static int get_next_device_id(void)
break;
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
if(ok)
return next_device_id++;
}
@@ -552,9 +552,9 @@ static void device_version_input(struct mux_device *dev, struct version_header *
vh->minor = ntohl(vh->minor);
if(vh->major != 2 && vh->major != 1) {
usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d", dev->id, vh->major, vh->minor);
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
collection_remove(&device_list, dev);
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
free(dev);
return;
}
@@ -709,14 +709,14 @@ static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned
void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length)
{
struct mux_device *dev = NULL;
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *tdev, &device_list) {
if(tdev->usbdev == usbdev) {
dev = tdev;
break;
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
if(!dev) {
usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev));
return;
@@ -832,15 +832,15 @@ int device_add(struct usb_device *usbdev)
free(dev);
return res;
}
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
collection_add(&device_list, dev);
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
return 0;
}
void device_remove(struct usb_device *usbdev)
{
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
if(dev->usbdev == usbdev) {
usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev));
@@ -856,48 +856,48 @@ void device_remove(struct usb_device *usbdev)
preflight_device_remove_cb(dev->preflight_cb_data);
}
collection_remove(&device_list, dev);
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
free(dev->pktbuf);
free(dev);
return;
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev));
}
void device_set_visible(int device_id)
{
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
if(dev->id == device_id) {
dev->visible = 1;
break;
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
}
void device_set_preflight_cb_data(int device_id, void* data)
{
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
if(dev->id == device_id) {
dev->preflight_cb_data = data;
break;
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
}
int device_get_count(int include_hidden)
{
int count = 0;
struct collection dev_list = {NULL, 0};
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
collection_copy(&dev_list, &device_list);
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
FOREACH(struct mux_device *dev, &dev_list) {
if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible))
@@ -912,9 +912,9 @@ int device_get_list(int include_hidden, struct device_info **devices)
{
int count = 0;
struct collection dev_list = {NULL, 0};
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
collection_copy(&dev_list, &device_list);
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
*devices = malloc(sizeof(struct device_info) * dev_list.capacity);
struct device_info *p = *devices;
@@ -939,7 +939,7 @@ int device_get_list(int include_hidden, struct device_info **devices)
int device_get_timeout(void)
{
uint64_t oldest = (uint64_t)-1LL;
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
if(dev->state == MUXDEV_ACTIVE) {
FOREACH(struct mux_connection *conn, &dev->connections) {
@@ -948,7 +948,7 @@ int device_get_timeout(void)
} ENDFOREACH
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
uint64_t ct = mstime64();
if((int64_t)oldest == -1LL)
return 100000; //meh
@@ -960,7 +960,7 @@ int device_get_timeout(void)
void device_check_timeouts(void)
{
uint64_t ct = mstime64();
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
if(dev->state == MUXDEV_ACTIVE) {
FOREACH(struct mux_connection *conn, &dev->connections) {
@@ -973,14 +973,14 @@ void device_check_timeouts(void)
} ENDFOREACH
}
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
}
void device_init(void)
{
usbmuxd_log(LL_DEBUG, "device_init");
collection_init(&device_list);
- pthread_mutex_init(&device_list_mutex, NULL);
+ mutex_init(&device_list_mutex);
next_device_id = 1;
}
@@ -1001,7 +1001,7 @@ void device_kill_connections(void)
void device_shutdown(void)
{
usbmuxd_log(LL_DEBUG, "device_shutdown");
- pthread_mutex_lock(&device_list_mutex);
+ mutex_lock(&device_list_mutex);
FOREACH(struct mux_device *dev, &device_list) {
FOREACH(struct mux_connection *conn, &dev->connections) {
connection_teardown(conn);
@@ -1010,7 +1010,7 @@ void device_shutdown(void)
collection_remove(&device_list, dev);
free(dev);
} ENDFOREACH
- pthread_mutex_unlock(&device_list_mutex);
- pthread_mutex_destroy(&device_list_mutex);
+ mutex_unlock(&device_list_mutex);
+ mutex_destroy(&device_list_mutex);
collection_free(&device_list);
}
diff --git a/src/preflight.c b/src/preflight.c
index c74e49d..f83c8b6 100644
--- a/src/preflight.c
+++ b/src/preflight.c
@@ -26,8 +26,6 @@
#include <unistd.h>
#include <errno.h>
-#include <pthread.h>
-
#include <sys/time.h>
#ifdef HAVE_LIBIMOBILEDEVICE
@@ -42,6 +40,8 @@
#include "conf.h"
#include "log.h"
+#include "common/thread.h"
+
#ifdef HAVE_LIBIMOBILEDEVICE
enum connection_type {
CONNECTION_USBMUXD = 1
@@ -344,18 +344,14 @@ void preflight_worker_device_add(struct device_info* info)
memcpy(infocopy, info, sizeof(struct device_info));
- pthread_t th;
- pthread_attr_t attr;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- int perr = pthread_create(&th, &attr, preflight_worker_handle_device_add, infocopy);
+ thread_t th;
+ int perr = thread_create(&th, preflight_worker_handle_device_add, infocopy);
if (perr != 0) {
free(infocopy);
usbmuxd_log(LL_ERROR, "ERROR: failed to start preflight worker thread for device %s: %s (%d). Invoking client_device_add() directly but things might not work as expected.", info->serial, strerror(perr), perr);
client_device_add(info);
}
+ thread_detach(th);
#else
client_device_add(info);
#endif