Use common thread implementation as used in other libimobiledevice libraries
diff --git a/common/Makefile.am b/common/Makefile.am
index 8acf04b..ca8180c 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -5,8 +5,10 @@
 libinternalcommon_la_LIBADD =
 libinternalcommon_la_SOURCES =			\
 	socket.c				\
+	thread.c				\
 	collection.c				\
 	socket.h				\
+	thread.h				\
 	collection.h
 
 if WIN32
diff --git a/common/thread.c b/common/thread.c
new file mode 100644
index 0000000..da7eb21
--- /dev/null
+++ b/common/thread.c
@@ -0,0 +1,140 @@
+/*
+ * thread.c
+ *
+ * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
+ * Copyright (c) 2012 Martin Szulecki, 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "thread.h"
+
+int thread_new(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_detach(THREAD_T thread)
+{
+#ifdef WIN32
+	CloseHandle(thread);
+#else
+	pthread_detach(thread);
+#endif
+}
+
+void thread_free(THREAD_T thread)
+{
+#ifdef WIN32
+	CloseHandle(thread);
+#endif
+}
+
+int thread_join(THREAD_T thread)
+{
+	/* wait for thread to complete */
+#ifdef WIN32
+	return (int)WaitForSingleObject(thread, INFINITE);
+#else
+	return pthread_join(thread, NULL);
+#endif
+}
+
+int thread_alive(THREAD_T thread)
+{
+#ifdef WIN32
+	return WaitForSingleObject(thread, 0) == WAIT_TIMEOUT;
+#else
+	return pthread_kill(thread, 0) == 0;
+#endif
+}
+
+int thread_cancel(THREAD_T thread)
+{
+#ifdef WIN32
+	return 0;
+#else
+#ifdef HAVE_PTHREAD_CANCEL
+	return pthread_cancel(thread);
+#else
+	return 0;
+#endif
+#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..23e4510
--- /dev/null
+++ b/common/thread.h
@@ -0,0 +1,76 @@
+/*
+ * thread.h
+ *
+ * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
+ * Copyright (c) 2012 Martin Szulecki, 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
+
+#include <stddef.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()
+#define THREAD_T_NULL (THREAD_T)NULL
+#else
+#include <pthread.h>
+#include <signal.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()
+#define THREAD_T_NULL (THREAD_T)NULL
+#endif
+
+typedef void* (*thread_func_t)(void* data);
+
+int thread_new(THREAD_T* thread, thread_func_t thread_func, void* data);
+void thread_detach(THREAD_T thread);
+void thread_free(THREAD_T thread);
+int thread_join(THREAD_T thread);
+int thread_alive(THREAD_T thread);
+
+int thread_cancel(THREAD_T thread);
+
+#ifdef WIN32
+#undef HAVE_THREAD_CLEANUP
+#else
+#ifdef HAVE_PTHREAD_CANCEL
+#define HAVE_THREAD_CLEANUP 1
+#define thread_cleanup_push(routine, arg) pthread_cleanup_push(routine, arg)
+#define thread_cleanup_pop(execute) pthread_cleanup_pop(execute)
+#endif
+#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);
+
+void thread_once(thread_once_t *once_control, void (*init_routine)(void));
+
+#endif
diff --git a/configure.ac b/configure.ac
index d64e116..55ba1cd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,20 +69,22 @@
 AC_CHECK_FUNCS([strcasecmp strdup strerror stpncpy sleep])
 
 # Check for operating system
-AC_MSG_CHECKING([whether we need platform-specific build settings])
+AC_MSG_CHECKING([for platform-specific build settings])
 case ${host_os} in
   *mingw32*|*cygwin*)
-    AC_MSG_RESULT([yes])
+    AC_MSG_RESULT([${host_os}])
     win32=true
     AC_DEFINE(WINVER, 0x0501, [minimum Windows version])
     ;;
   darwin*)
-    AC_MSG_RESULT([no])
+    AC_MSG_RESULT([${host_os}])
+    AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE])])
+    AC_CHECK_FUNCS([pthread_cancel])
     ;;
   *)
-    AC_MSG_RESULT([yes])
-    AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build libusbmuxd])])
-    AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [], [AC_MSG_ERROR([pthread is required to build libusbmuxd])])
+    AC_MSG_RESULT([${host_os}])
+    AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE])])
+    AC_CHECK_FUNCS([pthread_cancel])
     AC_CACHE_CHECK(for program_invocation_short_name, ac_cv_program_invocation_short_name,[
         AC_TRY_LINK([extern char* program_invocation_short_name;],[return program_invocation_short_name;],
             [ac_cv_program_invocation_short_name=yes],
@@ -105,7 +107,7 @@
 esac
 AM_CONDITIONAL(WIN32, test x$win32 = xtrue)
 
-AS_COMPILER_FLAGS(GLOBAL_CFLAGS, "-Wall -Wextra -Wmissing-declarations -Wredundant-decls -Wshadow -Wpointer-arith  -Wwrite-strings -Wswitch-default -Wno-unused-parameter -fvisibility=hidden $PTHREAD_CFLAGS")
+AS_COMPILER_FLAGS(GLOBAL_CFLAGS, "-Wall -Wextra -Wmissing-declarations -Wredundant-decls -Wshadow -Wpointer-arith -Wwrite-strings -Wswitch-default -Wno-unused-parameter -fvisibility=hidden $PTHREAD_CFLAGS")
 GLOBAL_LDFLAGS="$PTHREAD_LIBS"
 AC_SUBST(GLOBAL_CFLAGS)
 AC_SUBST(GLOBAL_LDFLAGS)
diff --git a/src/Makefile.am b/src/Makefile.am
index a8b4a7d..38b137b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,6 @@
 libusbmuxd_la_SOURCES = libusbmuxd.c
 
 if WIN32
-libusbmuxd_la_LDFLAGS += -avoid-version
+libusbmuxd_la_LDFLAGS += -avoid-version -static-libgcc
 libusbmuxd_la_LIBADD += -lws2_32
 endif
diff --git a/src/libusbmuxd.c b/src/libusbmuxd.c
index 0a0dc88..62af3e2 100644
--- a/src/libusbmuxd.c
+++ b/src/libusbmuxd.c
@@ -104,6 +104,8 @@
 #include "socket.h"
 // misc utility functions
 #include "collection.h"
+// threads
+#include "thread.h"
 
 static int libusbmuxd_debug = 0;
 #ifndef PACKAGE
@@ -114,11 +116,7 @@
 
 static struct collection devices;
 static usbmuxd_event_cb_t event_cb = NULL;
-#ifdef WIN32
-HANDLE devmon = NULL;
-#else
-pthread_t devmon;
-#endif
+static THREAD_T devmon = THREAD_T_NULL;
 static int listenfd = -1;
 
 static volatile int use_tag = 0;
@@ -1036,8 +1034,8 @@
 {
 	collection_init(&devices);
 
-#ifndef WIN32
-	pthread_cleanup_push(device_monitor_cleanup, NULL);
+#ifdef HAVE_THREAD_CLEANUP
+	thread_cleanup_push(device_monitor_cleanup, NULL);
 #endif
 	while (event_cb) {
 
@@ -1054,8 +1052,8 @@
 		}
 	}
 
-#ifndef WIN32
-	pthread_cleanup_pop(1);
+#ifdef HAVE_THREAD_CLEANUP
+	thread_cleanup_pop(1);
 #else
 	device_monitor_cleanup(NULL);
 #endif
@@ -1071,15 +1069,7 @@
 	}
 	event_cb = callback;
 
-#ifdef WIN32
-	res = 0;
-	devmon = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)device_monitor, user_data, 0, NULL);
-	if (devmon == NULL) {
-		res = GetLastError();
-	}
-#else
-	res = pthread_create(&devmon, NULL, device_monitor, user_data);
-#endif
+	res = thread_new(&devmon, device_monitor, user_data);
 	if (res != 0) {
 		LIBUSBMUXD_DEBUG(1, "%s: ERROR: Could not start device watcher thread!\n", __func__);
 		return res;
@@ -1089,28 +1079,19 @@
 
 USBMUXD_API int usbmuxd_unsubscribe()
 {
-	int res;
+	int res = 0;
 	event_cb = NULL;
 
 	socket_shutdown(listenfd, SHUT_RDWR);
 
-#ifdef WIN32
-	if (devmon != NULL) {
-		res = WaitForSingleObject(devmon, INFINITE);
-		if (res != 0) {
-			return res;
-		}
-	}
-#else
-	res = pthread_kill(devmon, 0);
-	if (res == 0) {
-		pthread_cancel(devmon);
-		res = pthread_join(devmon, NULL);
+	if (thread_alive(devmon)) {
+		thread_cancel(devmon);
+		res = thread_join(devmon);
+		thread_free(devmon);
 	}
 	if ((res != 0) && (res != ESRCH)) {
 		return res;
 	}
-#endif
 
 	return 0;
 }