[PATCH 5/9] libs: Import winpthreads from MinGW 8.0.0.

Zebediah Figura zfigura at codeweavers.com
Mon Nov 29 11:01:18 CST 2021


We need this for PE libvkd3d.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
As an alternative, we could define a minimal, probably not perfectly conforming,
replacement, which would at least mean adding less code...

 configure.ac                                 |    2 +
 libs/winpthreads/Makefile.in                 |   11 +
 libs/winpthreads/include/pthread.h           |  692 +++++++
 libs/winpthreads/include/pthread_compat.h    |   86 +
 libs/winpthreads/include/pthread_signal.h    |   29 +
 libs/winpthreads/include/pthread_time.h      |   98 +
 libs/winpthreads/include/pthread_unistd.h    |  192 ++
 libs/winpthreads/include/sched.h             |   79 +
 libs/winpthreads/include/semaphore.h         |   81 +
 libs/winpthreads/src/barrier.c               |  246 +++
 libs/winpthreads/src/barrier.h               |   49 +
 libs/winpthreads/src/clock.c                 |  240 +++
 libs/winpthreads/src/cond.c                  |  755 +++++++
 libs/winpthreads/src/cond.h                  |   61 +
 libs/winpthreads/src/libgcc/dll_dependency.S |   90 +
 libs/winpthreads/src/libgcc/dll_math.c       |  579 ++++++
 libs/winpthreads/src/misc.c                  |  158 ++
 libs/winpthreads/src/misc.h                  |  114 ++
 libs/winpthreads/src/mutex.c                 |  385 ++++
 libs/winpthreads/src/nanosleep.c             |   71 +
 libs/winpthreads/src/ref.c                   |   34 +
 libs/winpthreads/src/ref.h                   |   29 +
 libs/winpthreads/src/rwlock.c                |  533 +++++
 libs/winpthreads/src/rwlock.h                |   52 +
 libs/winpthreads/src/sched.c                 |  218 ++
 libs/winpthreads/src/sem.c                   |  354 ++++
 libs/winpthreads/src/sem.h                   |   40 +
 libs/winpthreads/src/spinlock.c              |   81 +
 libs/winpthreads/src/thread.c                | 1865 ++++++++++++++++++
 libs/winpthreads/src/thread.h                |   79 +
 libs/winpthreads/src/version.rc              |   62 +
 libs/winpthreads/src/winpthread_internal.h   |   27 +
 libs/winpthreads/src/wpth_ver.h              |   29 +
 33 files changed, 7421 insertions(+)
 create mode 100644 libs/winpthreads/Makefile.in
 create mode 100644 libs/winpthreads/include/pthread.h
 create mode 100644 libs/winpthreads/include/pthread_compat.h
 create mode 100644 libs/winpthreads/include/pthread_signal.h
 create mode 100644 libs/winpthreads/include/pthread_time.h
 create mode 100644 libs/winpthreads/include/pthread_unistd.h
 create mode 100644 libs/winpthreads/include/sched.h
 create mode 100644 libs/winpthreads/include/semaphore.h
 create mode 100644 libs/winpthreads/src/barrier.c
 create mode 100644 libs/winpthreads/src/barrier.h
 create mode 100644 libs/winpthreads/src/clock.c
 create mode 100644 libs/winpthreads/src/cond.c
 create mode 100644 libs/winpthreads/src/cond.h
 create mode 100644 libs/winpthreads/src/libgcc/dll_dependency.S
 create mode 100644 libs/winpthreads/src/libgcc/dll_math.c
 create mode 100644 libs/winpthreads/src/misc.c
 create mode 100644 libs/winpthreads/src/misc.h
 create mode 100644 libs/winpthreads/src/mutex.c
 create mode 100644 libs/winpthreads/src/nanosleep.c
 create mode 100644 libs/winpthreads/src/ref.c
 create mode 100644 libs/winpthreads/src/ref.h
 create mode 100644 libs/winpthreads/src/rwlock.c
 create mode 100644 libs/winpthreads/src/rwlock.h
 create mode 100644 libs/winpthreads/src/sched.c
 create mode 100644 libs/winpthreads/src/sem.c
 create mode 100644 libs/winpthreads/src/sem.h
 create mode 100644 libs/winpthreads/src/spinlock.c
 create mode 100644 libs/winpthreads/src/thread.c
 create mode 100644 libs/winpthreads/src/thread.h
 create mode 100644 libs/winpthreads/src/version.rc
 create mode 100644 libs/winpthreads/src/winpthread_internal.h
 create mode 100644 libs/winpthreads/src/wpth_ver.h

diff --git a/configure.ac b/configure.ac
index 20f08be0063..ff393285c0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1159,6 +1159,7 @@ WINE_EXTLIB_FLAGS(JXR, jxr, jxr, "-I\$(top_srcdir)/libs/jxr/jxrgluelib -I\$(top_
 WINE_EXTLIB_FLAGS(LCMS2, lcms2, lcms2, "-I\$(top_srcdir)/libs/lcms2/include")
 WINE_EXTLIB_FLAGS(MPG123, mpg123, mpg123, "-I\$(top_srcdir)/libs/mpg123/src/libmpg123")
 WINE_EXTLIB_FLAGS(PNG, png, "png \$(ZLIB_PE_LIBS)", "-I\$(top_srcdir)/libs/png")
+WINE_EXTLIB_FLAGS(PTHREAD, pthread, pthread, "-I\$(top_srcdir)/libs/winpthreads/include")
 WINE_EXTLIB_FLAGS(TIFF, tiff, tiff, "-I\$(top_srcdir)/libs/tiff/libtiff")
 WINE_EXTLIB_FLAGS(XML2, xml2, xml2, "-I\$(top_srcdir)/libs/xml2/include -DLIBXML_STATIC")
 WINE_EXTLIB_FLAGS(XSLT, xslt, xslt, "-I\$(top_srcdir)/libs/xslt -DLIBXSLT_STATIC")
@@ -3705,6 +3706,7 @@ WINE_CONFIG_MAKEFILE(libs/tiff)
 WINE_CONFIG_MAKEFILE(libs/uuid)
 WINE_CONFIG_MAKEFILE(libs/wbemuuid)
 WINE_CONFIG_MAKEFILE(libs/wine)
+WINE_CONFIG_MAKEFILE(libs/winpthreads)
 WINE_CONFIG_MAKEFILE(libs/wmcodecdspuuid)
 WINE_CONFIG_MAKEFILE(libs/xml2)
 WINE_CONFIG_MAKEFILE(libs/xslt)
diff --git a/libs/winpthreads/Makefile.in b/libs/winpthreads/Makefile.in
new file mode 100644
index 00000000000..4e3b4fba682
--- /dev/null
+++ b/libs/winpthreads/Makefile.in
@@ -0,0 +1,11 @@
+EXTLIB    = libpthread.a
+
+C_SRCS = \
+	src/clock.c \
+	src/cond.c \
+	src/misc.c \
+	src/mutex.c \
+	src/rwlock.c \
+	src/sched.c \
+	src/spinlock.c \
+	src/thread.c
diff --git a/libs/winpthreads/include/pthread.h b/libs/winpthreads/include/pthread.h
new file mode 100644
index 00000000000..4c2affd36c3
--- /dev/null
+++ b/libs/winpthreads/include/pthread.h
@@ -0,0 +1,692 @@
+/*
+   Copyright (c) 2011-2016 mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+ * Parts of this library are derived by:
+ *
+ * Posix Threads library for Microsoft Windows
+ *
+ * Use at own risk, there is no implied warranty to this code.
+ * It uses undocumented features of Microsoft Windows that can change
+ * at any time in the future.
+ *
+ * (C) 2010 Lockless Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of Lockless Inc. nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef WIN_PTHREADS_H
+#define WIN_PTHREADS_H
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <process.h>
+#include <limits.h>
+#include <signal.h>
+
+#include <sys/timeb.h>
+
+#include "pthread_compat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __WINPTHREADS_VERSION_MAJOR 0
+#define __WINPTHREADS_VERSION_MINOR 5
+#define __WINPTHREADS_VERSION_PATCHLEVEL 0
+
+/* MSB 8-bit major version, 8-bit minor version, 16-bit patch level.  */
+#define __WINPTHREADS_VERSION 0x00050000
+
+#if defined DLL_EXPORT
+#ifdef IN_WINPTHREAD
+#define WINPTHREAD_API __declspec(dllexport)
+#else
+#define WINPTHREAD_API __declspec(dllimport)
+#endif
+#else
+#define WINPTHREAD_API
+#endif
+
+/* #define WINPTHREAD_DBG 1 */
+
+/* Compatibility stuff: */
+#define RWLS_PER_THREAD						8
+
+/* Error-codes.  */
+#ifndef ETIMEDOUT
+#define ETIMEDOUT	138
+#endif
+#ifndef ENOTSUP
+#define ENOTSUP		129
+#endif
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK	140
+#endif
+
+/* pthread specific defines.  */
+
+#define PTHREAD_CANCEL_DISABLE 0
+#define PTHREAD_CANCEL_ENABLE 0x01
+
+#define PTHREAD_CANCEL_DEFERRED 0
+#define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
+
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_CREATE_DETACHED 0x04
+
+#define PTHREAD_EXPLICIT_SCHED 0
+#define PTHREAD_INHERIT_SCHED 0x08
+
+#define PTHREAD_SCOPE_PROCESS 0
+#define PTHREAD_SCOPE_SYSTEM 0x10
+
+#define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE)
+
+#define PTHREAD_CANCELED ((void *) (intptr_t) 0xDEADBEEF)
+
+#define _PTHREAD_NULL_THREAD ((pthread_t) 0)
+
+#define PTHREAD_ONCE_INIT 0
+
+#define PTHREAD_DESTRUCTOR_ITERATIONS 256
+#define PTHREAD_KEYS_MAX (1<<20)
+
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_ERRORCHECK 1
+#define PTHREAD_MUTEX_RECURSIVE 2
+#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
+
+#define PTHREAD_MUTEX_SHARED 1
+#define PTHREAD_MUTEX_PRIVATE 0
+
+#define PTHREAD_PRIO_NONE 0
+#define PTHREAD_PRIO_INHERIT 8
+#define PTHREAD_PRIO_PROTECT 16
+#define PTHREAD_PRIO_MULT 32
+#define PTHREAD_PROCESS_SHARED 1
+#define PTHREAD_PROCESS_PRIVATE 0
+
+#define PTHREAD_MUTEX_FAST_NP		PTHREAD_MUTEX_NORMAL
+#define PTHREAD_MUTEX_TIMED_NP		PTHREAD_MUTEX_FAST_NP
+#define PTHREAD_MUTEX_ADAPTIVE_NP	PTHREAD_MUTEX_FAST_NP
+#define PTHREAD_MUTEX_ERRORCHECK_NP	PTHREAD_MUTEX_ERRORCHECK
+#define PTHREAD_MUTEX_RECURSIVE_NP	PTHREAD_MUTEX_RECURSIVE
+
+void * WINPTHREAD_API pthread_timechange_handler_np(void * dummy);
+int    WINPTHREAD_API pthread_delay_np (const struct timespec *interval);
+int    WINPTHREAD_API pthread_num_processors_np(void);
+int    WINPTHREAD_API pthread_set_num_processors_np(int n);
+
+#define PTHREAD_BARRIER_SERIAL_THREAD 1
+
+/* maximum number of times a read lock may be obtained */
+#define	MAX_READ_LOCKS		(INT_MAX - 1)
+
+/* No fork() in windows - so ignore this */
+#define pthread_atfork(F1,F2,F3) 0
+
+/* unsupported stuff: */
+#define pthread_mutex_getprioceiling(M, P) ENOTSUP
+#define pthread_mutex_setprioceiling(M, P) ENOTSUP
+#define pthread_getcpuclockid(T, C) ENOTSUP
+#define pthread_attr_getguardsize(A, S) ENOTSUP
+#define pthread_attr_setgaurdsize(A, S) ENOTSUP
+
+typedef long pthread_once_t;
+typedef unsigned pthread_mutexattr_t;
+typedef unsigned pthread_key_t;
+typedef void *pthread_barrierattr_t;
+typedef int pthread_condattr_t;
+typedef int pthread_rwlockattr_t;
+
+/*
+struct _pthread_v;
+
+typedef struct pthread_t {
+  struct _pthread_v *p;
+  int x;
+} pthread_t;
+*/
+
+typedef uintptr_t pthread_t;
+
+typedef struct _pthread_cleanup _pthread_cleanup;
+struct _pthread_cleanup
+{
+    void (*func)(void *);
+    void *arg;
+    _pthread_cleanup *next;
+};
+
+#define pthread_cleanup_push(F, A)\
+{\
+    const _pthread_cleanup _pthread_cup = {(F), (A), *pthread_getclean()};\
+    __sync_synchronize();\
+    *pthread_getclean() = (_pthread_cleanup *) &_pthread_cup;\
+    __sync_synchronize()
+
+/* Note that if async cancelling is used, then there is a race here */
+#define pthread_cleanup_pop(E)\
+    (*pthread_getclean() = _pthread_cup.next, ((E) ? (_pthread_cup.func((pthread_once_t *)_pthread_cup.arg)) : (void)0));}
+
+/* Windows doesn't have this, so declare it ourselves. */
+#ifndef _TIMESPEC_DEFINED
+#define _TIMESPEC_DEFINED
+struct timespec {
+  time_t  tv_sec;   /* Seconds */
+  long    tv_nsec;  /* Nanoseconds */
+};
+
+struct itimerspec {
+  struct timespec  it_interval;  /* Timer period */
+  struct timespec  it_value;     /* Timer expiration */
+};
+#endif
+
+#ifndef SCHED_OTHER
+/* Some POSIX realtime extensions, mostly stubbed */
+#define SCHED_OTHER     0
+#define SCHED_FIFO      1
+#define SCHED_RR        2
+#define SCHED_MIN       SCHED_OTHER
+#define SCHED_MAX       SCHED_RR
+
+struct sched_param {
+  int sched_priority;
+};
+
+int WINPTHREAD_API sched_yield(void);
+int WINPTHREAD_API sched_get_priority_min(int pol);
+int WINPTHREAD_API sched_get_priority_max(int pol);
+int WINPTHREAD_API sched_getscheduler(pid_t pid);
+int WINPTHREAD_API sched_setscheduler(pid_t pid, int pol, const struct sched_param *param);
+
+#endif
+
+typedef struct pthread_attr_t pthread_attr_t;
+struct pthread_attr_t
+{
+    unsigned p_state;
+    void *stack;
+    size_t s_size;
+    struct sched_param param;
+};
+
+int WINPTHREAD_API pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
+int WINPTHREAD_API pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
+int WINPTHREAD_API pthread_getschedparam(pthread_t thread, int *pol, struct sched_param *param);
+int WINPTHREAD_API pthread_setschedparam(pthread_t thread, int pol, const struct sched_param *param);
+int WINPTHREAD_API pthread_attr_setschedpolicy (pthread_attr_t *attr, int pol);
+int WINPTHREAD_API pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *pol);
+
+/* synchronization objects */
+typedef intptr_t pthread_spinlock_t;
+typedef intptr_t pthread_mutex_t;
+typedef intptr_t pthread_cond_t;
+typedef intptr_t pthread_rwlock_t;
+typedef void	*pthread_barrier_t;
+
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_ERRORCHECK 1
+#define PTHREAD_MUTEX_RECURSIVE 2
+
+#define GENERIC_INITIALIZER				-1
+#define GENERIC_ERRORCHECK_INITIALIZER			-2
+#define GENERIC_RECURSIVE_INITIALIZER			-3
+#define GENERIC_NORMAL_INITIALIZER			-1
+#define PTHREAD_MUTEX_INITIALIZER			(pthread_mutex_t)GENERIC_INITIALIZER
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER		(pthread_mutex_t)GENERIC_RECURSIVE_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER		(pthread_mutex_t)GENERIC_ERRORCHECK_INITIALIZER
+#define PTHREAD_NORMAL_MUTEX_INITIALIZER		(pthread_mutex_t)GENERIC_NORMAL_INITIALIZER
+#define PTHREAD_DEFAULT_MUTEX_INITIALIZER		PTHREAD_NORMAL_MUTEX_INITIALIZER
+#define PTHREAD_COND_INITIALIZER			(pthread_cond_t)GENERIC_INITIALIZER
+#define PTHREAD_RWLOCK_INITIALIZER			(pthread_rwlock_t)GENERIC_INITIALIZER
+#define PTHREAD_SPINLOCK_INITIALIZER			(pthread_spinlock_t)GENERIC_INITIALIZER
+
+extern void WINPTHREAD_API (**_pthread_key_dest)(void *);
+int         WINPTHREAD_API pthread_key_create(pthread_key_t *key, void (* dest)(void *));
+int         WINPTHREAD_API pthread_key_delete(pthread_key_t key);
+void *      WINPTHREAD_API pthread_getspecific(pthread_key_t key);
+int         WINPTHREAD_API pthread_setspecific(pthread_key_t key, const void *value);
+
+pthread_t WINPTHREAD_API pthread_self(void);
+int       WINPTHREAD_API pthread_once(pthread_once_t *o, void (*func)(void));
+void      WINPTHREAD_API pthread_testcancel(void);
+int       WINPTHREAD_API pthread_equal(pthread_t t1, pthread_t t2);
+void      WINPTHREAD_API pthread_tls_init(void);
+void      WINPTHREAD_API _pthread_cleanup_dest(pthread_t t);
+int       WINPTHREAD_API pthread_get_concurrency(int *val);
+int       WINPTHREAD_API pthread_set_concurrency(int val);
+void      WINPTHREAD_API pthread_exit(void *res);
+void      WINPTHREAD_API _pthread_invoke_cancel(void);
+int       WINPTHREAD_API pthread_cancel(pthread_t t);
+int       WINPTHREAD_API pthread_kill(pthread_t t, int sig);
+unsigned  WINPTHREAD_API _pthread_get_state(const pthread_attr_t *attr, unsigned flag);
+int       WINPTHREAD_API _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val);
+int       WINPTHREAD_API pthread_setcancelstate(int state, int *oldstate);
+int       WINPTHREAD_API pthread_setcanceltype(int type, int *oldtype);
+int       WINPTHREAD_API pthread_create_wrapper(void *args);
+int       WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);
+int       WINPTHREAD_API pthread_join(pthread_t t, void **res);
+int       WINPTHREAD_API pthread_detach(pthread_t t);
+int       WINPTHREAD_API pthread_setname_np(pthread_t thread, const char *name);
+int       WINPTHREAD_API pthread_getname_np(pthread_t thread, char *name, size_t len);
+
+
+int WINPTHREAD_API pthread_rwlock_init(pthread_rwlock_t *rwlock_, const pthread_rwlockattr_t *attr);
+int WINPTHREAD_API pthread_rwlock_wrlock(pthread_rwlock_t *l);
+int WINPTHREAD_API pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *ts);
+int WINPTHREAD_API pthread_rwlock_rdlock(pthread_rwlock_t *l);
+int WINPTHREAD_API pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts);
+int WINPTHREAD_API pthread_rwlock_unlock(pthread_rwlock_t *l);
+int WINPTHREAD_API pthread_rwlock_tryrdlock(pthread_rwlock_t *l);
+int WINPTHREAD_API pthread_rwlock_trywrlock(pthread_rwlock_t *l);
+int WINPTHREAD_API pthread_rwlock_destroy (pthread_rwlock_t *l);
+
+int WINPTHREAD_API pthread_cond_init(pthread_cond_t *cv, const pthread_condattr_t *a);
+int WINPTHREAD_API pthread_cond_destroy(pthread_cond_t *cv);
+int WINPTHREAD_API pthread_cond_signal (pthread_cond_t *cv);
+int WINPTHREAD_API pthread_cond_broadcast (pthread_cond_t *cv);
+int WINPTHREAD_API pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex);
+int WINPTHREAD_API pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *external_mutex, const struct timespec *t);
+int WINPTHREAD_API pthread_cond_timedwait_relative_np(pthread_cond_t *cv, pthread_mutex_t *external_mutex, const struct timespec *t);
+
+int WINPTHREAD_API pthread_mutex_lock(pthread_mutex_t *m);
+int WINPTHREAD_API pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec *ts);
+int WINPTHREAD_API pthread_mutex_unlock(pthread_mutex_t *m);
+int WINPTHREAD_API pthread_mutex_trylock(pthread_mutex_t *m);
+int WINPTHREAD_API pthread_mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a);
+int WINPTHREAD_API pthread_mutex_destroy(pthread_mutex_t *m);
+
+int WINPTHREAD_API pthread_barrier_destroy(pthread_barrier_t *b);
+int WINPTHREAD_API pthread_barrier_init(pthread_barrier_t *b, const void *attr, unsigned int count);
+int WINPTHREAD_API pthread_barrier_wait(pthread_barrier_t *b);
+
+int WINPTHREAD_API pthread_spin_init(pthread_spinlock_t *l, int pshared);
+int WINPTHREAD_API pthread_spin_destroy(pthread_spinlock_t *l);
+/* No-fair spinlock due to lack of knowledge of thread number.  */
+int WINPTHREAD_API pthread_spin_lock(pthread_spinlock_t *l);
+int WINPTHREAD_API pthread_spin_trylock(pthread_spinlock_t *l);
+int WINPTHREAD_API pthread_spin_unlock(pthread_spinlock_t *l);
+
+int WINPTHREAD_API pthread_attr_init(pthread_attr_t *attr);
+int WINPTHREAD_API pthread_attr_destroy(pthread_attr_t *attr);
+int WINPTHREAD_API pthread_attr_setdetachstate(pthread_attr_t *a, int flag);
+int WINPTHREAD_API pthread_attr_getdetachstate(const pthread_attr_t *a, int *flag);
+int WINPTHREAD_API pthread_attr_setinheritsched(pthread_attr_t *a, int flag);
+int WINPTHREAD_API pthread_attr_getinheritsched(const pthread_attr_t *a, int *flag);
+int WINPTHREAD_API pthread_attr_setscope(pthread_attr_t *a, int flag);
+int WINPTHREAD_API pthread_attr_getscope(const pthread_attr_t *a, int *flag);
+int WINPTHREAD_API pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stack);
+int WINPTHREAD_API pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack);
+int WINPTHREAD_API pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *size);
+int WINPTHREAD_API pthread_attr_setstacksize(pthread_attr_t *attr, size_t size);
+
+int WINPTHREAD_API pthread_mutexattr_init(pthread_mutexattr_t *a);
+int WINPTHREAD_API pthread_mutexattr_destroy(pthread_mutexattr_t *a);
+int WINPTHREAD_API pthread_mutexattr_gettype(const pthread_mutexattr_t *a, int *type);
+int WINPTHREAD_API pthread_mutexattr_settype(pthread_mutexattr_t *a, int type);
+int WINPTHREAD_API pthread_mutexattr_getpshared(const pthread_mutexattr_t *a, int *type);
+int WINPTHREAD_API pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type);
+int WINPTHREAD_API pthread_mutexattr_getprotocol(const pthread_mutexattr_t *a, int *type);
+int WINPTHREAD_API pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type);
+int WINPTHREAD_API pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *a, int * prio);
+int WINPTHREAD_API pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio);
+int WINPTHREAD_API pthread_getconcurrency(void);
+int WINPTHREAD_API pthread_setconcurrency(int new_level);
+
+int WINPTHREAD_API pthread_condattr_destroy(pthread_condattr_t *a);
+int WINPTHREAD_API pthread_condattr_init(pthread_condattr_t *a);
+int WINPTHREAD_API pthread_condattr_getpshared(const pthread_condattr_t *a, int *s);
+int WINPTHREAD_API pthread_condattr_setpshared(pthread_condattr_t *a, int s);
+
+#ifndef __clockid_t_defined
+typedef int clockid_t;
+#define __clockid_t_defined 1
+#endif  /* __clockid_t_defined */
+
+int WINPTHREAD_API pthread_condattr_getclock (const pthread_condattr_t *attr,
+       clockid_t *clock_id);
+int WINPTHREAD_API pthread_condattr_setclock(pthread_condattr_t *attr,
+       clockid_t clock_id);
+int WINPTHREAD_API __pthread_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp);
+
+int WINPTHREAD_API pthread_barrierattr_init(void **attr);
+int WINPTHREAD_API pthread_barrierattr_destroy(void **attr);
+int WINPTHREAD_API pthread_barrierattr_setpshared(void **attr, int s);
+int WINPTHREAD_API pthread_barrierattr_getpshared(void **attr, int *s);
+
+/* Private extensions for analysis and internal use.  */
+struct _pthread_cleanup ** WINPTHREAD_API pthread_getclean (void);
+void *                     WINPTHREAD_API pthread_gethandle (pthread_t t);
+void *                     WINPTHREAD_API pthread_getevent ();
+
+unsigned long long         WINPTHREAD_API _pthread_rel_time_in_ms(const struct timespec *ts);
+unsigned long long         WINPTHREAD_API _pthread_time_in_ms(void);
+unsigned long long         WINPTHREAD_API _pthread_time_in_ms_from_timespec(const struct timespec *ts);
+int                        WINPTHREAD_API _pthread_tryjoin (pthread_t t, void **res);
+int                        WINPTHREAD_API pthread_rwlockattr_destroy(pthread_rwlockattr_t *a);
+int                        WINPTHREAD_API pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s);
+int                        WINPTHREAD_API pthread_rwlockattr_init(pthread_rwlockattr_t *a);
+int                        WINPTHREAD_API pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s);
+
+#ifndef SIG_BLOCK
+#define SIG_BLOCK 0
+#endif
+#ifndef SIG_UNBLOCK
+#define SIG_UNBLOCK 1
+#endif
+#ifndef SIG_SETMASK
+#define SIG_SETMASK 2
+#endif
+
+#include <pthread_unistd.h>
+
+#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS     PTHREAD_DESTRUCTOR_ITERATIONS
+
+#undef _POSIX_THREAD_KEYS_MAX
+#define _POSIX_THREAD_KEYS_MAX                  PTHREAD_KEYS_MAX
+
+#undef PTHREAD_THREADS_MAX
+#define PTHREAD_THREADS_MAX                     2019
+
+#undef _POSIX_SEM_NSEMS_MAX
+#define _POSIX_SEM_NSEMS_MAX                    256
+
+#undef SEM_NSEMS_MAX
+#define SEM_NSEMS_MAX                           1024
+
+/* Wrap cancellation points.  */
+#ifdef __WINPTRHEAD_ENABLE_WRAP_API
+#define accept(...) (pthread_testcancel(), accept(__VA_ARGS__))
+#define aio_suspend(...) (pthread_testcancel(), aio_suspend(__VA_ARGS__))
+#define clock_nanosleep(...) (pthread_testcancel(), clock_nanosleep(__VA_ARGS__))
+#define close(...) (pthread_testcancel(), close(__VA_ARGS__))
+#define connect(...) (pthread_testcancel(), connect(__VA_ARGS__))
+#define creat(...) (pthread_testcancel(), creat(__VA_ARGS__))
+#define fcntl(...) (pthread_testcancel(), fcntl(__VA_ARGS__))
+#define fdatasync(...) (pthread_testcancel(), fdatasync(__VA_ARGS__))
+#define fsync(...) (pthread_testcancel(), fsync(__VA_ARGS__))
+#define getmsg(...) (pthread_testcancel(), getmsg(__VA_ARGS__))
+#define getpmsg(...) (pthread_testcancel(), getpmsg(__VA_ARGS__))
+#define lockf(...) (pthread_testcancel(), lockf(__VA_ARGS__))
+#define mg_receive(...) (pthread_testcancel(), mg_receive(__VA_ARGS__))
+#define mg_send(...) (pthread_testcancel(), mg_send(__VA_ARGS__))
+#define mg_timedreceive(...) (pthread_testcancel(), mg_timedreceive(__VA_ARGS__))
+#define mg_timessend(...) (pthread_testcancel(), mg_timedsend(__VA_ARGS__))
+#define msgrcv(...) (pthread_testcancel(), msgrecv(__VA_ARGS__))
+#define msgsnd(...) (pthread_testcancel(), msgsnd(__VA_ARGS__))
+#define msync(...) (pthread_testcancel(), msync(__VA_ARGS__))
+#define nanosleep(...) (pthread_testcancel(), nanosleep(__VA_ARGS__))
+#define open(...) (pthread_testcancel(), open(__VA_ARGS__))
+#define pause(...) (pthread_testcancel(), pause(__VA_ARGS__))
+#define poll(...) (pthread_testcancel(), poll(__VA_ARGS__))
+#define pread(...) (pthread_testcancel(), pread(__VA_ARGS__))
+#define pselect(...) (pthread_testcancel(), pselect(__VA_ARGS__))
+#define putmsg(...) (pthread_testcancel(), putmsg(__VA_ARGS__))
+#define putpmsg(...) (pthread_testcancel(), putpmsg(__VA_ARGS__))
+#define pwrite(...) (pthread_testcancel(), pwrite(__VA_ARGS__))
+#define read(...) (pthread_testcancel(), read(__VA_ARGS__))
+#define readv(...) (pthread_testcancel(), readv(__VA_ARGS__))
+#define recv(...) (pthread_testcancel(), recv(__VA_ARGS__))
+#define recvfrom(...) (pthread_testcancel(), recvfrom(__VA_ARGS__))
+#define recvmsg(...) (pthread_testcancel(), recvmsg(__VA_ARGS__))
+#define select(...) (pthread_testcancel(), select(__VA_ARGS__))
+#define sem_timedwait(...) (pthread_testcancel(), sem_timedwait(__VA_ARGS__))
+#define sem_wait(...) (pthread_testcancel(), sem_wait(__VA_ARGS__))
+#define send(...) (pthread_testcancel(), send(__VA_ARGS__))
+#define sendmsg(...) (pthread_testcancel(), sendmsg(__VA_ARGS__))
+#define sendto(...) (pthread_testcancel(), sendto(__VA_ARGS__))
+#define sigpause(...) (pthread_testcancel(), sigpause(__VA_ARGS__))
+#define sigsuspend(...) (pthread_testcancel(), sigsuspend(__VA_ARGS__))
+#define sigwait(...) (pthread_testcancel(), sigwait(__VA_ARGS__))
+#define sigwaitinfo(...) (pthread_testcancel(), sigwaitinfo(__VA_ARGS__))
+#define sleep(...) (pthread_testcancel(), sleep(__VA_ARGS__))
+//#define Sleep(...) (pthread_testcancel(), Sleep(__VA_ARGS__))
+#define system(...) (pthread_testcancel(), system(__VA_ARGS__))
+#define access(...) (pthread_testcancel(), access(__VA_ARGS__))
+#define asctime(...) (pthread_testcancel(), asctime(__VA_ARGS__))
+#define catclose(...) (pthread_testcancel(), catclose(__VA_ARGS__))
+#define catgets(...) (pthread_testcancel(), catgets(__VA_ARGS__))
+#define catopen(...) (pthread_testcancel(), catopen(__VA_ARGS__))
+#define closedir(...) (pthread_testcancel(), closedir(__VA_ARGS__))
+#define closelog(...) (pthread_testcancel(), closelog(__VA_ARGS__))
+#define ctermid(...) (pthread_testcancel(), ctermid(__VA_ARGS__))
+#define ctime(...) (pthread_testcancel(), ctime(__VA_ARGS__))
+#define dbm_close(...) (pthread_testcancel(), dbm_close(__VA_ARGS__))
+#define dbm_delete(...) (pthread_testcancel(), dbm_delete(__VA_ARGS__))
+#define dbm_fetch(...) (pthread_testcancel(), dbm_fetch(__VA_ARGS__))
+#define dbm_nextkey(...) (pthread_testcancel(), dbm_nextkey(__VA_ARGS__))
+#define dbm_open(...) (pthread_testcancel(), dbm_open(__VA_ARGS__))
+#define dbm_store(...) (pthread_testcancel(), dbm_store(__VA_ARGS__))
+#define dlclose(...) (pthread_testcancel(), dlclose(__VA_ARGS__))
+#define dlopen(...) (pthread_testcancel(), dlopen(__VA_ARGS__))
+#define endgrent(...) (pthread_testcancel(), endgrent(__VA_ARGS__))
+#define endhostent(...) (pthread_testcancel(), endhostent(__VA_ARGS__))
+#define endnetent(...) (pthread_testcancel(), endnetent(__VA_ARGS__))
+#define endprotoent(...) (pthread_testcancel(), endprotoend(__VA_ARGS__))
+#define endpwent(...) (pthread_testcancel(), endpwent(__VA_ARGS__))
+#define endservent(...) (pthread_testcancel(), endservent(__VA_ARGS__))
+#define endutxent(...) (pthread_testcancel(), endutxent(__VA_ARGS__))
+#define fclose(...) (pthread_testcancel(), fclose(__VA_ARGS__))
+#define fflush(...) (pthread_testcancel(), fflush(__VA_ARGS__))
+#define fgetc(...) (pthread_testcancel(), fgetc(__VA_ARGS__))
+#define fgetpos(...) (pthread_testcancel(), fgetpos(__VA_ARGS__))
+#define fgets(...) (pthread_testcancel(), fgets(__VA_ARGS__))
+#define fgetwc(...) (pthread_testcancel(), fgetwc(__VA_ARGS__))
+#define fgetws(...) (pthread_testcancel(), fgetws(__VA_ARGS__))
+#define fmtmsg(...) (pthread_testcancel(), fmtmsg(__VA_ARGS__))
+#define fopen(...) (pthread_testcancel(), fopen(__VA_ARGS__))
+#define fpathconf(...) (pthread_testcancel(), fpathconf(__VA_ARGS__))
+#define fprintf(...) (pthread_testcancel(), fprintf(__VA_ARGS__))
+#define fputc(...) (pthread_testcancel(), fputc(__VA_ARGS__))
+#define fputs(...) (pthread_testcancel(), fputs(__VA_ARGS__))
+#define fputwc(...) (pthread_testcancel(), fputwc(__VA_ARGS__))
+#define fputws(...) (pthread_testcancel(), fputws(__VA_ARGS__))
+#define fread(...) (pthread_testcancel(), fread(__VA_ARGS__))
+#define freopen(...) (pthread_testcancel(), freopen(__VA_ARGS__))
+#define fscanf(...) (pthread_testcancel(), fscanf(__VA_ARGS__))
+#define fseek(...) (pthread_testcancel(), fseek(__VA_ARGS__))
+#define fseeko(...) (pthread_testcancel(), fseeko(__VA_ARGS__))
+#define fsetpos(...) (pthread_testcancel(), fsetpos(__VA_ARGS__))
+#define fstat(...) (pthread_testcancel(), fstat(__VA_ARGS__))
+#define ftell(...) (pthread_testcancel(), ftell(__VA_ARGS__))
+#define ftello(...) (pthread_testcancel(), ftello(__VA_ARGS__))
+#define ftw(...) (pthread_testcancel(), ftw(__VA_ARGS__))
+#define fwprintf(...) (pthread_testcancel(), fwprintf(__VA_ARGS__))
+#define fwrite(...) (pthread_testcancel(), fwrite(__VA_ARGS__))
+#define fwscanf(...) (pthread_testcancel(), fwscanf(__VA_ARGS__))
+#define getaddrinfo(...) (pthread_testcancel(), getaddrinfo(__VA_ARGS__))
+#define getc(...) (pthread_testcancel(), getc(__VA_ARGS__))
+#define getc_unlocked(...) (pthread_testcancel(), getc_unlocked(__VA_ARGS__))
+#define getchar(...) (pthread_testcancel(), getchar(__VA_ARGS__))
+#define getchar_unlocked(...) (pthread_testcancel(), getchar_unlocked(__VA_ARGS__))
+#define getcwd(...) (pthread_testcancel(), getcwd(__VA_ARGS__))
+#define getdate(...) (pthread_testcancel(), getdate(__VA_ARGS__))
+#define getgrent(...) (pthread_testcancel(), getgrent(__VA_ARGS__))
+#define getgrgid(...) (pthread_testcancel(), getgrgid(__VA_ARGS__))
+#define getgrgid_r(...) (pthread_testcancel(), getgrgid_r(__VA_ARGS__))
+#define gergrnam(...) (pthread_testcancel(), getgrnam(__VA_ARGS__))
+#define getgrnam_r(...) (pthread_testcancel(), getgrnam_r(__VA_ARGS__))
+#define gethostbyaddr(...) (pthread_testcancel(), gethostbyaddr(__VA_ARGS__))
+#define gethostbyname(...) (pthread_testcancel(), gethostbyname(__VA_ARGS__))
+#define gethostent(...) (pthread_testcancel(), gethostent(__VA_ARGS__))
+#define gethostid(...) (pthread_testcancel(), gethostid(__VA_ARGS__))
+#define gethostname(...) (pthread_testcancel(), gethostname(__VA_ARGS__))
+#define getlogin(...) (pthread_testcancel(), getlogin(__VA_ARGS__))
+#define getlogin_r(...) (pthread_testcancel(), getlogin_r(__VA_ARGS__))
+#define getnameinfo(...) (pthread_testcancel(), getnameinfo(__VA_ARGS__))
+#define getnetbyaddr(...) (pthread_testcancel(), getnetbyaddr(__VA_ARGS__))
+#define getnetbyname(...) (pthread_testcancel(), getnetbyname(__VA_ARGS__))
+#define getnetent(...) (pthread_testcancel(), getnetent(__VA_ARGS__))
+#define getopt(...) (pthread_testcancel(), getopt(__VA_ARGS__))
+#define getprotobyname(...) (pthread_testcancel(), getprotobyname(__VA_ARGS__))
+#define getprotobynumber(...) (pthread_testcancel(), getprotobynumber(__VA_ARGS__))
+#define getprotoent(...) (pthread_testcancel(), getprotoent(__VA_ARGS__))
+#define getpwent(...) (pthread_testcancel(), getpwent(__VA_ARGS__))
+#define getpwnam(...) (pthread_testcancel(), getpwnam(__VA_ARGS__))
+#define getpwnam_r(...) (pthread_testcancel(), getpwnam_r(__VA_ARGS__))
+#define getpwuid(...) (pthread_testcancel(), getpwuid(__VA_ARGS__))
+#define getpwuid_r(...) (pthread_testcancel(), getpwuid_r(__VA_ARGS__))
+#define gets(...) (pthread_testcancel(), gets(__VA_ARGS__))
+#define getservbyname(...) (pthread_testcancel(), getservbyname(__VA_ARGS__))
+#define getservbyport(...) (pthread_testcancel(), getservbyport(__VA_ARGS__))
+#define getservent(...) (pthread_testcancel(), getservent(__VA_ARGS__))
+#define getutxent(...) (pthread_testcancel(), getutxent(__VA_ARGS__))
+#define getutxid(...) (pthread_testcancel(), getutxid(__VA_ARGS__))
+#define getutxline(...) (pthread_testcancel(), getutxline(__VA_ARGS__))
+#undef getwc
+#define getwc(...) (pthread_testcancel(), getwc(__VA_ARGS__))
+#undef getwchar
+#define getwchar(...) (pthread_testcancel(), getwchar(__VA_ARGS__))
+#define getwd(...) (pthread_testcancel(), getwd(__VA_ARGS__))
+#define glob(...) (pthread_testcancel(), glob(__VA_ARGS__))
+#define iconv_close(...) (pthread_testcancel(), iconv_close(__VA_ARGS__))
+#define iconv_open(...) (pthread_testcancel(), iconv_open(__VA_ARGS__))
+#define ioctl(...) (pthread_testcancel(), ioctl(__VA_ARGS__))
+#define link(...) (pthread_testcancel(), link(__VA_ARGS__))
+#define localtime(...) (pthread_testcancel(), localtime(__VA_ARGS__))
+#define lseek(...) (pthread_testcancel(), lseek(__VA_ARGS__))
+#define lstat(...) (pthread_testcancel(), lstat(__VA_ARGS__))
+#define mkstemp(...) (pthread_testcancel(), mkstemp(__VA_ARGS__))
+#define nftw(...) (pthread_testcancel(), nftw(__VA_ARGS__))
+#define opendir(...) (pthread_testcancel(), opendir(__VA_ARGS__))
+#define openlog(...) (pthread_testcancel(), openlog(__VA_ARGS__))
+#define pathconf(...) (pthread_testcancel(), pathconf(__VA_ARGS__))
+#define pclose(...) (pthread_testcancel(), pclose(__VA_ARGS__))
+#define perror(...) (pthread_testcancel(), perror(__VA_ARGS__))
+#define popen(...) (pthread_testcancel(), popen(__VA_ARGS__))
+#define posix_fadvise(...) (pthread_testcancel(), posix_fadvise(__VA_ARGS__))
+#define posix_fallocate(...) (pthread_testcancel(), posix_fallocate(__VA_ARGS__))
+#define posix_madvise(...) (pthread_testcancel(), posix_madvise(__VA_ARGS__))
+#define posix_openpt(...) (pthread_testcancel(), posix_openpt(__VA_ARGS__))
+#define posix_spawn(...) (pthread_testcancel(), posix_spawn(__VA_ARGS__))
+#define posix_spawnp(...) (pthread_testcancel(), posix_spawnp(__VA_ARGS__))
+#define posix_trace_clear(...) (pthread_testcancel(), posix_trace_clear(__VA_ARGS__))
+#define posix_trace_close(...) (pthread_testcancel(), posix_trace_close(__VA_ARGS__))
+#define posix_trace_create(...) (pthread_testcancel(), posix_trace_create(__VA_ARGS__))
+#define posix_trace_create_withlog(...) (pthread_testcancel(), posix_trace_create_withlog(__VA_ARGS__))
+#define posix_trace_eventtypelist_getne(...) (pthread_testcancel(), posix_trace_eventtypelist_getne(__VA_ARGS__))
+#define posix_trace_eventtypelist_rewin(...) (pthread_testcancel(), posix_trace_eventtypelist_rewin(__VA_ARGS__))
+#define posix_trace_flush(...) (pthread_testcancel(), posix_trace_flush(__VA_ARGS__))
+#define posix_trace_get_attr(...) (pthread_testcancel(), posix_trace_get_attr(__VA_ARGS__))
+#define posix_trace_get_filter(...) (pthread_testcancel(), posix_trace_get_filter(__VA_ARGS__))
+#define posix_trace_get_status(...) (pthread_testcancel(), posix_trace_get_status(__VA_ARGS__))
+#define posix_trace_getnext_event(...) (pthread_testcancel(), posix_trace_getnext_event(__VA_ARGS__))
+#define posix_trace_open(...) (pthread_testcancel(), posix_trace_open(__VA_ARGS__))
+#define posix_trace_rewind(...) (pthread_testcancel(), posix_trace_rewind(__VA_ARGS__))
+#define posix_trace_setfilter(...) (pthread_testcancel(), posix_trace_setfilter(__VA_ARGS__))
+#define posix_trace_shutdown(...) (pthread_testcancel(), posix_trace_shutdown(__VA_ARGS__))
+#define posix_trace_timedgetnext_event(...) (pthread_testcancel(), posix_trace_timedgetnext_event(__VA_ARGS__))
+#define posix_typed_mem_open(...) (pthread_testcancel(), posix_typed_mem_open(__VA_ARGS__))
+#define printf(...) (pthread_testcancel(), printf(__VA_ARGS__))
+#define putc(...) (pthread_testcancel(), putc(__VA_ARGS__))
+#define putc_unlocked(...) (pthread_testcancel(), putc_unlocked(__VA_ARGS__))
+#define putchar(...) (pthread_testcancel(), putchar(__VA_ARGS__))
+#define putchar_unlocked(...) (pthread_testcancel(), putchar_unlocked(__VA_ARGS__))
+#define puts(...) (pthread_testcancel(), puts(__VA_ARGS__))
+#define pututxline(...) (pthread_testcancel(), pututxline(__VA_ARGS__))
+#undef putwc
+#define putwc(...) (pthread_testcancel(), putwc(__VA_ARGS__))
+#undef putwchar
+#define putwchar(...) (pthread_testcancel(), putwchar(__VA_ARGS__))
+#define readdir(...) (pthread_testcancel(), readdir(__VA_ARSG__))
+#define readdir_r(...) (pthread_testcancel(), readdir_r(__VA_ARGS__))
+#define remove(...) (pthread_testcancel(), remove(__VA_ARGS__))
+#define rename(...) (pthread_testcancel(), rename(__VA_ARGS__))
+#define rewind(...) (pthread_testcancel(), rewind(__VA_ARGS__))
+#define rewinddir(...) (pthread_testcancel(), rewinddir(__VA_ARGS__))
+#define scanf(...) (pthread_testcancel(), scanf(__VA_ARGS__))
+#define seekdir(...) (pthread_testcancel(), seekdir(__VA_ARGS__))
+#define semop(...) (pthread_testcancel(), semop(__VA_ARGS__))
+#define setgrent(...) (pthread_testcancel(), setgrent(__VA_ARGS__))
+#define sethostent(...) (pthread_testcancel(), sethostemt(__VA_ARGS__))
+#define setnetent(...) (pthread_testcancel(), setnetent(__VA_ARGS__))
+#define setprotoent(...) (pthread_testcancel(), setprotoent(__VA_ARGS__))
+#define setpwent(...) (pthread_testcancel(), setpwent(__VA_ARGS__))
+#define setservent(...) (pthread_testcancel(), setservent(__VA_ARGS__))
+#define setutxent(...) (pthread_testcancel(), setutxent(__VA_ARGS__))
+#define stat(...) (pthread_testcancel(), stat(__VA_ARGS__))
+#define strerror(...) (pthread_testcancel(), strerror(__VA_ARGS__))
+#define strerror_r(...) (pthread_testcancel(), strerror_r(__VA_ARGS__))
+#define strftime(...) (pthread_testcancel(), strftime(__VA_ARGS__))
+#define symlink(...) (pthread_testcancel(), symlink(__VA_ARGS__))
+#define sync(...) (pthread_testcancel(), sync(__VA_ARGS__))
+#define syslog(...) (pthread_testcancel(), syslog(__VA_ARGS__))
+#define tmpfile(...) (pthread_testcancel(), tmpfile(__VA_ARGS__))
+#define tmpnam(...) (pthread_testcancel(), tmpnam(__VA_ARGS__))
+#define ttyname(...) (pthread_testcancel(), ttyname(__VA_ARGS__))
+#define ttyname_r(...) (pthread_testcancel(), ttyname_r(__VA_ARGS__))
+#define tzset(...) (pthread_testcancel(), tzset(__VA_ARGS__))
+#define ungetc(...) (pthread_testcancel(), ungetc(__VA_ARGS__))
+#define ungetwc(...) (pthread_testcancel(), ungetwc(__VA_ARGS__))
+#define unlink(...) (pthread_testcancel(), unlink(__VA_ARGS__))
+#define vfprintf(...) (pthread_testcancel(), vfprintf(__VA_ARGS__))
+#define vfwprintf(...) (pthread_testcancel(), vfwprintf(__VA_ARGS__))
+#define vprintf(...) (pthread_testcancel(), vprintf(__VA_ARGS__))
+#define vwprintf(...) (pthread_testcancel(), vwprintf(__VA_ARGS__))
+#define wcsftime(...) (pthread_testcancel(), wcsftime(__VA_ARGS__))
+#define wordexp(...) (pthread_testcancel(), wordexp(__VA_ARGS__))
+#define wprintf(...) (pthread_testcancel(), wprintf(__VA_ARGS__))
+#define wscanf(...) (pthread_testcancel(), wscanf(__VA_ARGS__))
+#endif
+
+/* We deal here with a gcc issue for posix threading on Windows.
+   We would need to change here gcc's gthr-posix.h header, but this
+   got rejected.  So we deal it within this header.  */
+#ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
+#undef _GTHREAD_USE_MUTEX_INIT_FUNC
+#endif
+#define _GTHREAD_USE_MUTEX_INIT_FUNC 1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WIN_PTHREADS_H */
diff --git a/libs/winpthreads/include/pthread_compat.h b/libs/winpthreads/include/pthread_compat.h
new file mode 100644
index 00000000000..63f5f495fcf
--- /dev/null
+++ b/libs/winpthreads/include/pthread_compat.h
@@ -0,0 +1,86 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+ * Parts of this library are derived by:
+ *
+ * Posix Threads library for Microsoft Windows
+ *
+ * Use at own risk, there is no implied warranty to this code.
+ * It uses undocumented features of Microsoft Windows that can change
+ * at any time in the future.
+ *
+ * (C) 2010 Lockless Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of Lockless Inc. nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WIN_PTHREADS_PTHREAD_COMPAT_H
+#define WIN_PTHREADS_PTHREAD_COMPAT_H
+
+#ifdef __GNUC__
+
+#define WINPTHREADS_INLINE inline
+#define WINPTHREADS_ATTRIBUTE(X) __attribute__(X)
+#define WINPTHREADS_SECTION(X) __section__(X)
+
+#elif _MSC_VER
+
+#include "pthread_time.h"
+
+#ifdef _WIN64
+typedef __int64 pid_t;
+#else
+typedef int     pid_t;
+#endif
+typedef int clockid_t;
+
+#define WINPTHREADS_INLINE __inline
+#define WINPTHREADS_ATTRIBUTE(X) __declspec X
+#define WINPTHREADS_SECTION(X) allocate(X)
+
+#endif
+
+#endif
diff --git a/libs/winpthreads/include/pthread_signal.h b/libs/winpthreads/include/pthread_signal.h
new file mode 100644
index 00000000000..42a50ae06cd
--- /dev/null
+++ b/libs/winpthreads/include/pthread_signal.h
@@ -0,0 +1,29 @@
+/*
+   Copyright (c) 2013-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_SIGNAL_H
+#define WIN_PTHREADS_SIGNAL_H
+
+/* Windows has rudimentary signals support.  */
+#define pthread_sigmask(H, S1, S2) 0
+
+#endif /* WIN_PTHREADS_SIGNAL_H */
diff --git a/libs/winpthreads/include/pthread_time.h b/libs/winpthreads/include/pthread_time.h
new file mode 100644
index 00000000000..7a7538c393f
--- /dev/null
+++ b/libs/winpthreads/include/pthread_time.h
@@ -0,0 +1,98 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <sys/timeb.h>
+
+#ifndef WIN_PTHREADS_TIME_H
+#define WIN_PTHREADS_TIME_H
+
+/* Posix timers are supported */
+#ifndef _POSIX_TIMERS
+#define _POSIX_TIMERS           200809L
+#endif
+
+/* Monotonic clocks are available.  */
+#ifndef _POSIX_MONOTONIC_CLOCK
+#define _POSIX_MONOTONIC_CLOCK  200809L
+#endif
+
+/* CPU-time clocks are available.  */
+#ifndef _POSIX_CPUTIME
+#define _POSIX_CPUTIME          200809L
+#endif
+
+/* Clock support in threads are available.  */
+#ifndef _POSIX_THREAD_CPUTIME
+#define _POSIX_THREAD_CPUTIME   200809L
+#endif
+
+#ifndef __clockid_t_defined
+typedef int clockid_t;
+#define __clockid_t_defined 1
+#endif  /* __clockid_t_defined */
+
+#ifndef TIMER_ABSTIME
+#define TIMER_ABSTIME   1
+#endif
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME              0
+#endif
+
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC             1
+#endif
+
+#ifndef CLOCK_PROCESS_CPUTIME_ID
+#define CLOCK_PROCESS_CPUTIME_ID    2
+#endif
+
+#ifndef CLOCK_THREAD_CPUTIME_ID
+#define CLOCK_THREAD_CPUTIME_ID     3
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Make sure we provide default for WINPTHREAD_API, if not defined.  */
+#pragma push_macro("WINPTHREAD_API")
+#ifndef WINPTHREAD_API
+#define WINPTHREAD_API
+#endif
+
+/* These should really be dllimport'ed if using winpthread dll */
+int __cdecl WINPTHREAD_API nanosleep(const struct timespec *request, struct timespec *remain);
+
+int __cdecl WINPTHREAD_API clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, struct timespec *remain);
+int __cdecl WINPTHREAD_API clock_getres(clockid_t clock_id, struct timespec *res);
+int __cdecl WINPTHREAD_API clock_gettime(clockid_t clock_id, struct timespec *tp);
+int __cdecl WINPTHREAD_API clock_settime(clockid_t clock_id, const struct timespec *tp);
+
+#pragma pop_macro("WINPTHREAD_API")
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WIN_PTHREADS_TIME_H */
+
diff --git a/libs/winpthreads/include/pthread_unistd.h b/libs/winpthreads/include/pthread_unistd.h
new file mode 100644
index 00000000000..646935344b1
--- /dev/null
+++ b/libs/winpthreads/include/pthread_unistd.h
@@ -0,0 +1,192 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_UNISTD_H
+#define WIN_PTHREADS_UNISTD_H
+
+/* Set defines described by the POSIX Threads Extension (1003.1c-1995) */
+/* _SC_THREADS
+  Basic support for POSIX threads is available. The functions
+
+  pthread_atfork(),
+  pthread_attr_destroy(),
+  pthread_attr_getdetachstate(),
+  pthread_attr_getschedparam(),
+  pthread_attr_init(),
+  pthread_attr_setdetachstate(),
+  pthread_attr_setschedparam(),
+  pthread_cancel(),
+  pthread_cleanup_push(),
+  pthread_cleanup_pop(),
+  pthread_cond_broadcast(),
+  pthread_cond_destroy(),
+  pthread_cond_init(),
+  pthread_cond_signal(),
+  pthread_cond_timedwait(),
+  pthread_cond_wait(),
+  pthread_condattr_destroy(),
+  pthread_condattr_init(),
+  pthread_create(),
+  pthread_detach(),
+  pthread_equal(),
+  pthread_exit(),
+  pthread_getspecific(),
+  pthread_join(,
+  pthread_key_create(),
+  pthread_key_delete(),
+  pthread_mutex_destroy(),
+  pthread_mutex_init(),
+  pthread_mutex_lock(),
+  pthread_mutex_trylock(),
+  pthread_mutex_unlock(),
+  pthread_mutexattr_destroy(),
+  pthread_mutexattr_init(),
+  pthread_once(),
+  pthread_rwlock_destroy(),
+  pthread_rwlock_init(),
+  pthread_rwlock_rdlock(),
+  pthread_rwlock_tryrdlock(),
+  pthread_rwlock_trywrlock(),
+  pthread_rwlock_unlock(),
+  pthread_rwlock_wrlock(),
+  pthread_rwlockattr_destroy(),
+  pthread_rwlockattr_init(),
+  pthread_self(),
+  pthread_setcancelstate(),
+  pthread_setcanceltype(),
+  pthread_setspecific(),
+  pthread_testcancel()
+
+  are present. */
+#undef _POSIX_THREADS
+#define _POSIX_THREADS 200112L
+
+/* _SC_READER_WRITER_LOCKS
+  This option implies the _POSIX_THREADS option. Conversely, under
+  POSIX 1003.1-2001 the _POSIX_THREADS option implies this option.
+
+  The functions
+  pthread_rwlock_destroy(),
+  pthread_rwlock_init(),
+  pthread_rwlock_rdlock(),
+  pthread_rwlock_tryrdlock(),
+  pthread_rwlock_trywrlock(),
+  pthread_rwlock_unlock(),
+  pthread_rwlock_wrlock(),
+  pthread_rwlockattr_destroy(),
+  pthread_rwlockattr_init()
+
+  are present.
+*/
+#undef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS 200112L
+
+/* _SC_SPIN_LOCKS
+  This option implies the _POSIX_THREADS and _POSIX_THREAD_SAFE_FUNCTIONS
+  options. The functions
+
+  pthread_spin_destroy(),
+  pthread_spin_init(),
+  pthread_spin_lock(),
+  pthread_spin_trylock(),
+  pthread_spin_unlock()
+
+  are present. */
+#undef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS 200112L
+
+/* _SC_BARRIERS
+  This option implies the _POSIX_THREADS and _POSIX_THREAD_SAFE_FUNCTIONS
+  options. The functions
+
+  pthread_barrier_destroy(),
+  pthread_barrier_init(),
+  pthread_barrier_wait(),
+  pthread_barrierattr_destroy(),
+  pthread_barrierattr_init()
+
+  are present.
+*/
+#undef _POSIX_BARRIERS
+#define _POSIX_BARRIERS 200112L
+
+/* _SC_TIMEOUTS
+  The functions
+
+  mq_timedreceive(), - not supported
+  mq_timedsend(), - not supported
+  posix_trace_timedgetnext_event(), - not supported
+  pthread_mutex_timedlock(),
+  pthread_rwlock_timedrdlock(),
+  pthread_rwlock_timedwrlock(),
+  sem_timedwait(),
+
+  are present. */
+#undef _POSIX_TIMEOUTS
+#define _POSIX_TIMEOUTS 200112L
+
+/* _SC_TIMERS - not supported
+  The functions
+
+  clock_getres(),
+  clock_gettime(),
+  clock_settime(),
+  nanosleep(),
+  timer_create(),
+  timer_delete(),
+  timer_gettime(),
+  timer_getoverrun(),
+  timer_settime()
+
+  are present.  */
+/* #undef _POSIX_TIMERS */
+
+/* _SC_CLOCK_SELECTION
+   This option implies the _POSIX_TIMERS option. The functions
+
+   pthread_condattr_getclock(),
+   pthread_condattr_setclock(),
+   clock_nanosleep()
+
+   are present.
+*/
+#undef _POSIX_CLOCK_SELECTION
+#define _POSIX_CLOCK_SELECTION 200112
+
+/* _SC_SEMAPHORES
+  The include file <semaphore.h> is present. The functions
+
+  sem_close(),
+  sem_destroy(),
+  sem_getvalue(),
+  sem_init(),
+  sem_open(),
+  sem_post(),
+  sem_trywait(),
+  sem_unlink(),
+  sem_wait()
+
+  are present. */
+#undef _POSIX_SEMAPHORES
+#define _POSIX_SEMAPHORES 200112
+
+#endif /* WIN_PTHREADS_UNISTD_H */
diff --git a/libs/winpthreads/include/sched.h b/libs/winpthreads/include/sched.h
new file mode 100644
index 00000000000..e77bf4cc3be
--- /dev/null
+++ b/libs/winpthreads/include/sched.h
@@ -0,0 +1,79 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <process.h>
+#include <limits.h>
+#include <signal.h>
+
+#include <sys/timeb.h>
+
+#ifndef WIN_PTHREADS_SCHED_H
+#define WIN_PTHREADS_SCHED_H
+
+#ifndef SCHED_OTHER
+/* Some POSIX realtime extensions, mostly stubbed */
+#define SCHED_OTHER     0
+#define SCHED_FIFO      1
+#define SCHED_RR        2
+#define SCHED_MIN       SCHED_OTHER
+#define SCHED_MAX       SCHED_RR
+
+struct sched_param {
+  int sched_priority;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined DLL_EXPORT && !defined (WINPTHREAD_EXPORT_ALL_DEBUG)
+#ifdef IN_WINPTHREAD
+#define WINPTHREAD_SCHED_API __declspec(dllexport)
+#else
+#define WINPTHREAD_SCHED_API __declspec(dllimport)
+#endif
+#else
+#define WINPTHREAD_SCHED_API
+#endif
+
+int WINPTHREAD_SCHED_API sched_yield(void);
+int WINPTHREAD_SCHED_API sched_get_priority_min(int pol);
+int WINPTHREAD_SCHED_API sched_get_priority_max(int pol);
+int WINPTHREAD_SCHED_API sched_getscheduler(pid_t pid);
+int WINPTHREAD_SCHED_API sched_setscheduler(pid_t pid, int pol, const struct sched_param *param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#ifndef sched_rr_get_interval
+#define sched_rr_get_interval(_p, _i) \
+  ( errno = ENOTSUP, (int) -1 )
+#endif
+
+#endif /* WIN_PTHREADS_SCHED_H */
diff --git a/libs/winpthreads/include/semaphore.h b/libs/winpthreads/include/semaphore.h
new file mode 100644
index 00000000000..14cb703713f
--- /dev/null
+++ b/libs/winpthreads/include/semaphore.h
@@ -0,0 +1,81 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_SEMAPHORE_H
+#define WIN_PTHREADS_SEMAPHORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined DLL_EXPORT && !defined (WINPTHREAD_EXPORT_ALL_DEBUG)
+#ifdef IN_WINPTHREAD
+#define WINPTHREAD_SEMA_API __declspec(dllexport)
+#else
+#define WINPTHREAD_SEMA_API __declspec(dllimport)
+#endif
+#else
+#define WINPTHREAD_SEMA_API
+#endif
+
+/* Set this to 0 to disable it */
+#define USE_SEM_CriticalSection_SpinCount	100
+
+#define SEM_VALUE_MAX   INT_MAX
+
+#ifndef _MODE_T_
+#define	_MODE_T_
+typedef unsigned short mode_t;
+#endif
+
+typedef void		*sem_t;
+
+#define SEM_FAILED 		NULL
+
+int WINPTHREAD_SEMA_API sem_init(sem_t * sem, int pshared, unsigned int value);
+
+int WINPTHREAD_SEMA_API sem_destroy(sem_t *sem);
+
+int WINPTHREAD_SEMA_API sem_trywait(sem_t *sem);
+
+int WINPTHREAD_SEMA_API sem_wait(sem_t *sem);
+
+int WINPTHREAD_SEMA_API sem_timedwait(sem_t * sem, const struct timespec *t);
+
+int WINPTHREAD_SEMA_API sem_post(sem_t *sem);
+
+int WINPTHREAD_SEMA_API sem_post_multiple(sem_t *sem, int count);
+
+/* yes, it returns a semaphore (or SEM_FAILED) */
+sem_t * WINPTHREAD_SEMA_API sem_open(const char * name, int oflag, mode_t mode, unsigned int value);
+
+int WINPTHREAD_SEMA_API sem_close(sem_t * sem);
+
+int WINPTHREAD_SEMA_API sem_unlink(const char * name);
+
+int WINPTHREAD_SEMA_API sem_getvalue(sem_t * sem, int * sval);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WIN_PTHREADS_SEMAPHORE_H */
diff --git a/libs/winpthreads/src/barrier.c b/libs/winpthreads/src/barrier.c
new file mode 100644
index 00000000000..95b2252af59
--- /dev/null
+++ b/libs/winpthreads/src/barrier.c
@@ -0,0 +1,246 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "pthread.h"
+#include "barrier.h"
+#include "ref.h" 
+#include "misc.h"
+
+static pthread_spinlock_t barrier_global = PTHREAD_SPINLOCK_INITIALIZER;
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int
+barrier_unref(volatile pthread_barrier_t *barrier, int res)
+{
+    pthread_spin_lock(&barrier_global);
+#ifdef WINPTHREAD_DBG
+    assert((((barrier_t *)*barrier)->valid == LIFE_BARRIER) && (((barrier_t *)*barrier)->busy > 0));
+#endif
+     ((barrier_t *)*barrier)->busy -= 1;
+    pthread_spin_unlock(&barrier_global);
+    return res;
+}
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int barrier_ref(volatile pthread_barrier_t *barrier)
+{
+    int r = 0;
+    pthread_spin_lock(&barrier_global);
+
+    if (!barrier || !*barrier || ((barrier_t *)*barrier)->valid != LIFE_BARRIER) r = EINVAL;
+    else {
+        ((barrier_t *)*barrier)->busy += 1;
+    }
+
+    pthread_spin_unlock(&barrier_global);
+
+    return r;
+}
+
+static WINPTHREADS_ATTRIBUTE((noinline))  int
+barrier_ref_destroy(volatile pthread_barrier_t *barrier, pthread_barrier_t *bDestroy)
+{
+    int r = 0;
+
+    *bDestroy = NULL;
+    pthread_spin_lock(&barrier_global);
+    
+    if (!barrier || !*barrier || ((barrier_t *)*barrier)->valid != LIFE_BARRIER) r = EINVAL;
+    else {
+        barrier_t *b_ = (barrier_t *)*barrier;
+        if (b_->busy) r = EBUSY;
+        else {
+            *bDestroy = *barrier;
+            *barrier = NULL;
+        }
+    }
+
+    pthread_spin_unlock(&barrier_global);
+    return r;
+}
+
+static WINPTHREADS_ATTRIBUTE((noinline)) void
+barrier_ref_set (volatile pthread_barrier_t *barrier, void *v)
+{
+  pthread_spin_lock(&barrier_global);
+  *barrier = v;
+  pthread_spin_unlock(&barrier_global);
+}
+
+int pthread_barrier_destroy(pthread_barrier_t *b_)
+{
+    pthread_barrier_t bDestroy;
+    barrier_t *b;
+    int r;
+    
+    while ((r = barrier_ref_destroy(b_,&bDestroy)) == EBUSY)
+      Sleep(0);
+    
+    if (r)
+      return r;
+
+    b = (barrier_t *)bDestroy;
+    
+    pthread_mutex_lock(&b->m);
+
+    if (sem_destroy(&b->sems[0]) != 0)
+    {
+        /* Could this happen? */
+        *b_ = bDestroy;
+        pthread_mutex_unlock (&b->m);
+        return EBUSY;
+    }
+    if (sem_destroy(&b->sems[1]) != 0)
+    {
+      sem_init (&b->sems[0], b->share, 0);
+      *b_ = bDestroy;
+      pthread_mutex_unlock (&b->m);
+      return -1;
+    }
+    pthread_mutex_unlock(&b->m);
+    if(pthread_mutex_destroy(&b->m) != 0) {
+     sem_init (&b->sems[0], b->share, 0);
+     sem_init (&b->sems[1], b->share, 0);
+     *b_ = bDestroy;
+     return -1;
+    }
+    b->valid = DEAD_BARRIER;
+    free(bDestroy);
+    return 0;
+
+}
+
+int
+pthread_barrier_init (pthread_barrier_t *b_, const void *attr,
+		      unsigned int count)
+{
+    barrier_t *b;
+
+    if (!count || !b_)
+      return EINVAL;
+
+    if (!(b = (pthread_barrier_t)calloc(1,sizeof(*b))))
+       return ENOMEM;
+    if (!attr || *((int **)attr) == NULL)
+      b->share = PTHREAD_PROCESS_PRIVATE;
+    else
+      memcpy (&b->share, *((void **) attr), sizeof (int));
+    b->total = count;
+    b->count = count;
+    b->valid = LIFE_BARRIER;
+    b->sel = 0;
+
+    if (pthread_mutex_init(&b->m, NULL) != 0)
+    {
+      free (b);
+      return ENOMEM;
+    }
+
+    if (sem_init(&b->sems[0], b->share, 0) != 0)
+    {
+       pthread_mutex_destroy(&b->m);
+       free (b);
+       return ENOMEM;
+    }
+    if (sem_init(&b->sems[1], b->share, 0) != 0)
+    {
+       pthread_mutex_destroy(&b->m);
+       sem_destroy(&b->sems[0]);
+       free (b);
+       return ENOMEM;
+    }
+    barrier_ref_set (b_,b);
+
+    return 0;
+}
+
+int pthread_barrier_wait(pthread_barrier_t *b_)
+{
+  long sel;
+  int r, e, rslt;
+  barrier_t *b;
+
+  r = barrier_ref(b_);
+  if(r) return r;
+
+  b = (barrier_t *)*b_;
+
+  if ((r = pthread_mutex_lock(&b->m))) return  barrier_unref(b_,EINVAL);
+  sel = b->sel;
+  InterlockedDecrement((long*)&b->total);
+  if (b->total == 0)
+  {
+    b->total = b->count;
+    b->sel = (sel != 0 ? 0 : 1);
+    e = 1;
+    rslt = PTHREAD_BARRIER_SERIAL_THREAD;
+    r = (b->count > 1 ? sem_post_multiple (&b->sems[sel], b->count - 1) : 0);
+  }
+  else { e = 0; rslt= 0; }
+  pthread_mutex_unlock(&b->m);
+  if (!e)
+    r = sem_wait(&b->sems[sel]);
+
+  if (!r) r = rslt;
+  return barrier_unref(b_,r);
+}
+
+int pthread_barrierattr_init(void **attr)
+{
+  int *p;
+
+  if (!(p = (int *) calloc (1, sizeof (int))))
+    return ENOMEM;
+
+  *p = PTHREAD_PROCESS_PRIVATE;
+  *attr = p;
+
+  return 0;
+}
+
+int pthread_barrierattr_destroy(void **attr)
+{
+  void *p;
+  if (!attr || (p = *attr) == NULL)
+    return EINVAL;
+  *attr = NULL;
+  free (p);
+  return 0;
+}
+
+int pthread_barrierattr_setpshared(void **attr, int s)
+{
+  if (!attr || *attr == NULL
+      || (s != PTHREAD_PROCESS_SHARED && s != PTHREAD_PROCESS_PRIVATE))
+    return EINVAL;
+  memcpy (*attr, &s, sizeof (int));
+  return 0;
+}
+
+int pthread_barrierattr_getpshared(void **attr, int *s)
+{
+  if (!attr || !s || *attr == NULL)
+    return EINVAL;
+  memcpy (s, *attr, sizeof (int));
+  return 0;
+}
diff --git a/libs/winpthreads/src/barrier.h b/libs/winpthreads/src/barrier.h
new file mode 100644
index 00000000000..b3e2146e7eb
--- /dev/null
+++ b/libs/winpthreads/src/barrier.h
@@ -0,0 +1,49 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_BARRIER_H
+#define WIN_PTHREADS_BARRIER_H
+
+#define LIFE_BARRIER 0xBAB1FEED
+#define DEAD_BARRIER 0xDEADB00F
+
+#define _PTHREAD_BARRIER_FLAG (1<<30)
+
+#define CHECK_BARRIER(b)  { \
+    if (!(b) || ( ((barrier_t *)(*b))->valid != (unsigned int)LIFE_BARRIER ) ) return EINVAL; }
+
+#include "../include/semaphore.h"
+
+typedef struct barrier_t barrier_t;
+struct barrier_t
+{
+    int valid;
+    int busy;
+    int count;
+    int total;
+    int share;
+    long sel;
+    pthread_mutex_t m;
+    sem_t sems[2];
+};
+
+#endif
diff --git a/libs/winpthreads/src/clock.c b/libs/winpthreads/src/clock.c
new file mode 100644
index 00000000000..5ad710b2e22
--- /dev/null
+++ b/libs/winpthreads/src/clock.c
@@ -0,0 +1,240 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <time.h>
+#include <windows.h>
+#ifndef IN_WINPTHREAD
+#define IN_WINPTHREAD 1
+#endif
+#include "pthread.h"
+#include "pthread_time.h"
+
+#define POW10_7                 10000000
+#define POW10_9                 1000000000
+
+/* Number of 100ns-seconds between the beginning of the Windows epoch
+ * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970)
+ */
+#define DELTA_EPOCH_IN_100NS    INT64_C(116444736000000000)
+
+static WINPTHREADS_INLINE int lc_set_errno(int result)
+{
+    if (result != 0) {
+        errno = result;
+        return -1;
+    }
+    return 0;
+}
+
+/**
+ * Get the resolution of the specified clock clock_id and
+ * stores it in the struct timespec pointed to by res.
+ * @param  clock_id The clock_id argument is the identifier of the particular
+ *         clock on which to act. The following clocks are supported:
+ * <pre>
+ *     CLOCK_REALTIME  System-wide real-time clock. Setting this clock
+ *                 requires appropriate privileges.
+ *     CLOCK_MONOTONIC Clock that cannot be set and represents monotonic
+ *                 time since some unspecified starting point.
+ *     CLOCK_PROCESS_CPUTIME_ID High-resolution per-process timer from the CPU.
+ *     CLOCK_THREAD_CPUTIME_ID  Thread-specific CPU-time clock.
+ * </pre>
+ * @param  res The pointer to a timespec structure to receive the time
+ *         resolution.
+ * @return If the function succeeds, the return value is 0.
+ *         If the function fails, the return value is -1,
+ *         with errno set to indicate the error.
+ */
+int clock_getres(clockid_t clock_id, struct timespec *res)
+{
+    switch(clock_id) {
+    case CLOCK_MONOTONIC:
+        {
+            LARGE_INTEGER pf;
+
+            if (QueryPerformanceFrequency(&pf) == 0)
+                return lc_set_errno(EINVAL);
+
+            res->tv_sec = 0;
+            res->tv_nsec = (int) ((POW10_9 + (pf.QuadPart >> 1)) / pf.QuadPart);
+            if (res->tv_nsec < 1)
+                res->tv_nsec = 1;
+
+            return 0;
+        }
+
+    case CLOCK_REALTIME:
+    case CLOCK_PROCESS_CPUTIME_ID:
+    case CLOCK_THREAD_CPUTIME_ID:
+        {
+            DWORD   timeAdjustment, timeIncrement;
+            BOOL    isTimeAdjustmentDisabled;
+
+            (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled);
+            res->tv_sec = 0;
+            res->tv_nsec = timeIncrement * 100;
+
+            return 0;
+        }
+    default:
+        break;
+    }
+
+    return lc_set_errno(EINVAL);
+}
+
+/**
+ * Get the time of the specified clock clock_id and stores it in the struct
+ * timespec pointed to by tp.
+ * @param  clock_id The clock_id argument is the identifier of the particular
+ *         clock on which to act. The following clocks are supported:
+ * <pre>
+ *     CLOCK_REALTIME  System-wide real-time clock. Setting this clock
+ *                 requires appropriate privileges.
+ *     CLOCK_MONOTONIC Clock that cannot be set and represents monotonic
+ *                 time since some unspecified starting point.
+ *     CLOCK_PROCESS_CPUTIME_ID High-resolution per-process timer from the CPU.
+ *     CLOCK_THREAD_CPUTIME_ID  Thread-specific CPU-time clock.
+ * </pre>
+ * @param  tp The pointer to a timespec structure to receive the time.
+ * @return If the function succeeds, the return value is 0.
+ *         If the function fails, the return value is -1,
+ *         with errno set to indicate the error.
+ */
+int clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+    unsigned __int64 t;
+    LARGE_INTEGER pf, pc;
+    union {
+        unsigned __int64 u64;
+        FILETIME ft;
+    }  ct, et, kt, ut;
+
+    switch(clock_id) {
+    case CLOCK_REALTIME:
+        {
+            GetSystemTimeAsFileTime(&ct.ft);
+            t = ct.u64 - DELTA_EPOCH_IN_100NS;
+            tp->tv_sec = t / POW10_7;
+            tp->tv_nsec = ((int) (t % POW10_7)) * 100;
+
+            return 0;
+        }
+
+    case CLOCK_MONOTONIC:
+        {
+            if (QueryPerformanceFrequency(&pf) == 0)
+                return lc_set_errno(EINVAL);
+
+            if (QueryPerformanceCounter(&pc) == 0)
+                return lc_set_errno(EINVAL);
+
+            tp->tv_sec = pc.QuadPart / pf.QuadPart;
+            tp->tv_nsec = (int) (((pc.QuadPart % pf.QuadPart) * POW10_9 + (pf.QuadPart >> 1)) / pf.QuadPart);
+            if (tp->tv_nsec >= POW10_9) {
+                tp->tv_sec ++;
+                tp->tv_nsec -= POW10_9;
+            }
+
+            return 0;
+        }
+
+    case CLOCK_PROCESS_CPUTIME_ID:
+        {
+        if(0 == GetProcessTimes(GetCurrentProcess(), &ct.ft, &et.ft, &kt.ft, &ut.ft))
+            return lc_set_errno(EINVAL);
+        t = kt.u64 + ut.u64;
+        tp->tv_sec = t / POW10_7;
+        tp->tv_nsec = ((int) (t % POW10_7)) * 100;
+
+        return 0;
+        }
+
+    case CLOCK_THREAD_CPUTIME_ID: 
+        {
+            if(0 == GetThreadTimes(GetCurrentThread(), &ct.ft, &et.ft, &kt.ft, &ut.ft))
+                return lc_set_errno(EINVAL);
+            t = kt.u64 + ut.u64;
+            tp->tv_sec = t / POW10_7;
+            tp->tv_nsec = ((int) (t % POW10_7)) * 100;
+
+            return 0;
+        }
+
+    default:
+        break;
+    }
+
+    return lc_set_errno(EINVAL);
+}
+
+/**
+ * Sleep for the specified time.
+ * @param  clock_id This argument should always be CLOCK_REALTIME (0).
+ * @param  flags 0 for relative sleep interval, others for absolute waking up.
+ * @param  request The desired sleep interval or absolute waking up time.
+ * @param  remain The remain amount of time to sleep.
+ *         The current implemention just ignore it.
+ * @return If the function succeeds, the return value is 0.
+ *         If the function fails, the return value is -1,
+ *         with errno set to indicate the error.
+ */
+int clock_nanosleep(clockid_t clock_id, int flags,
+                           const struct timespec *request,
+                           struct timespec *remain)
+{
+    struct timespec tp;
+
+    if (clock_id != CLOCK_REALTIME)
+        return lc_set_errno(EINVAL);
+
+    if (flags == 0)
+        return nanosleep(request, remain);
+
+    /* TIMER_ABSTIME = 1 */
+    clock_gettime(CLOCK_REALTIME, &tp);
+
+    tp.tv_sec = request->tv_sec - tp.tv_sec;
+    tp.tv_nsec = request->tv_nsec - tp.tv_nsec;
+    if (tp.tv_nsec < 0) {
+        tp.tv_nsec += POW10_9;
+        tp.tv_sec --;
+    }
+
+    return nanosleep(&tp, remain);
+}
+
+/**
+ * Set the time of the specified clock clock_id.
+ * @param  clock_id This argument should always be CLOCK_REALTIME (0).
+ * @param  tp The requested time.
+ * @return If the function succeeds, the return value is 0.
+ *         If the function fails, the return value is -1,
+ *         with errno set to indicate the error.
+ */
+int clock_settime(clockid_t clock_id, const struct timespec *tp)
+{
+    SYSTEMTIME st;
+
+    union {
+        unsigned __int64 u64;
+        FILETIME ft;
+    }  t;
+
+    if (clock_id != CLOCK_REALTIME)
+        return lc_set_errno(EINVAL);
+
+    t.u64 = tp->tv_sec * (__int64) POW10_7 + tp->tv_nsec / 100 + DELTA_EPOCH_IN_100NS;
+    if (FileTimeToSystemTime(&t.ft, &st) == 0)
+        return lc_set_errno(EINVAL);
+
+    if (SetSystemTime(&st) == 0)
+        return lc_set_errno(EPERM);
+
+    return 0;
+}
diff --git a/libs/winpthreads/src/cond.c b/libs/winpthreads/src/cond.c
new file mode 100644
index 00000000000..d50f85b40b2
--- /dev/null
+++ b/libs/winpthreads/src/cond.c
@@ -0,0 +1,755 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+ * Posix Condition Variables for Microsoft Windows.
+ * 22-9-2010 Partly based on the ACE framework implementation.
+ */
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <time.h>
+#include "pthread.h"
+#include "pthread_time.h"
+#include "ref.h"
+#include "cond.h"
+#include "thread.h"
+#include "misc.h"
+#include "winpthread_internal.h"
+
+#include "pthread_compat.h"
+
+int __pthread_shallcancel (void);
+
+static int do_sema_b_wait (HANDLE sema, int nointerrupt, DWORD timeout,CRITICAL_SECTION *cs, LONG *val);
+static int do_sema_b_release(HANDLE sema, LONG count,CRITICAL_SECTION *cs, LONG *val);
+static void cleanup_wait(void *arg);
+
+typedef struct sCondWaitHelper {
+    cond_t *c;
+    pthread_mutex_t *external_mutex;
+    int *r;
+} sCondWaitHelper;
+
+int do_sema_b_wait_intern (HANDLE sema, int nointerrupt, DWORD timeout);
+
+#ifdef WINPTHREAD_DBG
+static int print_state = 0;
+static FILE *fo;
+void cond_print_set(int state, FILE *f)
+{
+    if (f) fo = f;
+    if (!fo) fo = stdout;
+    print_state = state;
+}
+
+void cond_print(volatile pthread_cond_t *c, char *txt)
+{
+    if (!print_state) return;
+    cond_t *c_ = (cond_t *)*c;
+    if (c_ == NULL) {
+        fprintf(fo,"C%p %d %s\n",(void *)*c,(int)GetCurrentThreadId(),txt);
+    } else {
+        fprintf(fo,"C%p %d V=%0X w=%ld %s\n",
+            (void *)*c,
+            (int)GetCurrentThreadId(), 
+            (int)c_->valid, 
+            c_->waiters_count_,
+            txt
+            );
+    }
+}
+#endif
+
+static pthread_spinlock_t cond_locked = PTHREAD_SPINLOCK_INITIALIZER;
+
+static int
+cond_static_init (pthread_cond_t *c)
+{
+  int r = 0;
+  
+  pthread_spin_lock (&cond_locked);
+  if (c == NULL)
+    r = EINVAL;
+  else if (*c == PTHREAD_COND_INITIALIZER)
+    r = pthread_cond_init (c, NULL);
+  else
+    /* We assume someone was faster ... */
+    r = 0;
+  pthread_spin_unlock (&cond_locked);
+  return r;
+}
+
+int
+pthread_condattr_destroy (pthread_condattr_t *a)
+{
+  if (!a)
+    return EINVAL;
+   *a = 0;
+   return 0;
+}
+
+int
+pthread_condattr_init (pthread_condattr_t *a)
+{
+  if (!a)
+    return EINVAL;
+  *a = 0;
+  return 0;
+}
+
+int
+pthread_condattr_getpshared (const pthread_condattr_t *a, int *s)
+{
+  if (!a || !s)
+    return EINVAL;
+  *s = *a;
+  return 0;
+}
+
+int
+pthread_condattr_getclock (const pthread_condattr_t *a, clockid_t *clock_id)
+{
+  if (!a || !clock_id)
+    return EINVAL;
+  *clock_id = 0;
+  return 0;
+}
+
+int
+pthread_condattr_setclock(pthread_condattr_t *a, clockid_t clock_id)
+{
+  if (!a || clock_id != 0)
+    return EINVAL;
+  return 0;
+}
+
+int
+__pthread_clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *rqtp,
+			   struct timespec *rmtp)
+{
+  unsigned long long tick, tick2;
+  unsigned long long delay;
+  DWORD dw;
+
+  if (clock_id != CLOCK_REALTIME
+      && clock_id != CLOCK_MONOTONIC
+      && clock_id != CLOCK_PROCESS_CPUTIME_ID)
+   return EINVAL;
+  if ((flags & TIMER_ABSTIME) != 0)
+    delay = _pthread_rel_time_in_ms (rqtp);
+  else
+    delay = _pthread_time_in_ms_from_timespec (rqtp);
+  do
+    {
+      dw = (DWORD) (delay >= 99999ULL ? 99999ULL : delay);
+      tick = _pthread_time_in_ms ();
+      pthread_delay_np_ms (dw);
+      tick2 = _pthread_time_in_ms ();
+      tick2 -= tick;
+      if (tick2 >= delay)
+        delay = 0;
+      else
+        delay -= tick2;
+    }
+  while (delay != 0ULL);
+  if (rmtp)
+    memset (rmtp, 0, sizeof (*rmtp));
+  return 0;
+}
+
+int
+pthread_condattr_setpshared (pthread_condattr_t *a, int s)
+{
+  if (!a || (s != PTHREAD_PROCESS_SHARED && s != PTHREAD_PROCESS_PRIVATE))
+    return EINVAL;
+  if (s == PTHREAD_PROCESS_SHARED)
+    {
+       *a = PTHREAD_PROCESS_PRIVATE;
+       return ENOSYS;
+    }
+  *a = s;
+  return 0;
+}
+
+int
+pthread_cond_init (pthread_cond_t *c, const pthread_condattr_t *a)
+{
+  cond_t *_c;
+  int r = 0;
+
+  if (!c)
+    return EINVAL;
+  if (a && *a == PTHREAD_PROCESS_SHARED)
+    return ENOSYS;
+
+  if ( !(_c = calloc(1,sizeof(*_c))) ) {
+      return ENOMEM; 
+  }
+  _c->valid  = DEAD_COND;
+  _c->busy = 0;
+  _c->waiters_count_ = 0;
+  _c->waiters_count_gone_ = 0;
+  _c->waiters_count_unblock_ = 0;
+
+  _c->sema_q = CreateSemaphore (NULL,       /* no security */
+      0,          /* initially 0 */
+      0x7fffffff, /* max count */
+      NULL);      /* unnamed  */
+  _c->sema_b =  CreateSemaphore (NULL,       /* no security */
+      0,          /* initially 0 */
+      0x7fffffff, /* max count */
+      NULL);  
+  if (_c->sema_q == NULL || _c->sema_b == NULL) {
+      if (_c->sema_q != NULL)
+	CloseHandle (_c->sema_q);
+      if (_c->sema_b != NULL)
+	CloseHandle (_c->sema_b);
+      free (_c);
+      r = EAGAIN;
+  } else {
+      InitializeCriticalSection(&_c->waiters_count_lock_);
+      InitializeCriticalSection(&_c->waiters_b_lock_);
+      InitializeCriticalSection(&_c->waiters_q_lock_);
+      _c->value_q = 0;
+      _c->value_b = 1;
+  }
+  if (!r)
+    {
+      _c->valid = LIFE_COND;
+      *c = (pthread_cond_t)_c;
+    }
+  else
+    *c = (pthread_cond_t)NULL;
+  return r;
+}
+
+int
+pthread_cond_destroy (pthread_cond_t *c)
+{
+  cond_t *_c;
+  int r;
+  if (!c || !*c)
+    return EINVAL;
+  if (*c == PTHREAD_COND_INITIALIZER)
+    {
+      pthread_spin_lock (&cond_locked);
+      if (*c == PTHREAD_COND_INITIALIZER)
+      {
+	*c = (pthread_cond_t)NULL;
+	r = 0;
+      }
+      else
+	r = EBUSY;
+      pthread_spin_unlock (&cond_locked);
+      return r;
+    }
+  _c = (cond_t *) *c;
+  r = do_sema_b_wait(_c->sema_b, 0, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
+  if (r != 0)
+    return r;
+  if (!TryEnterCriticalSection (&_c->waiters_count_lock_))
+    {
+       do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+       return EBUSY;
+    }
+  if (_c->waiters_count_ > _c->waiters_count_gone_)
+    {
+      r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+      if (!r) r = EBUSY;
+      LeaveCriticalSection(&_c->waiters_count_lock_);
+      return r;
+    }
+  *c = (pthread_cond_t)NULL;
+  do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+
+  if (!CloseHandle (_c->sema_q) && !r)
+    r = EINVAL;
+  if (!CloseHandle (_c->sema_b) && !r)
+    r = EINVAL;
+  LeaveCriticalSection (&_c->waiters_count_lock_);
+  DeleteCriticalSection(&_c->waiters_count_lock_);
+  DeleteCriticalSection(&_c->waiters_b_lock_);
+  DeleteCriticalSection(&_c->waiters_q_lock_);
+  _c->valid  = DEAD_COND;
+  free(_c);
+  return 0;
+}
+
+int
+pthread_cond_signal (pthread_cond_t *c)
+{
+  cond_t *_c;
+  int r;
+
+  if (!c || !*c)
+    return EINVAL;
+  _c = (cond_t *)*c;
+  if (_c == (cond_t *)PTHREAD_COND_INITIALIZER)
+    return 0;
+  else if (_c->valid != (unsigned int)LIFE_COND)
+    return EINVAL;
+
+  EnterCriticalSection (&_c->waiters_count_lock_);
+  /* If there aren't any waiters, then this is a no-op.   */
+  if (_c->waiters_count_unblock_ != 0)
+    {
+      if (_c->waiters_count_ == 0)
+      {
+	LeaveCriticalSection (&_c->waiters_count_lock_);
+	/* pthread_testcancel(); */
+	return 0;
+      }
+      _c->waiters_count_ -= 1;
+      _c->waiters_count_unblock_ += 1;
+    }
+  else if (_c->waiters_count_ > _c->waiters_count_gone_)
+    {
+      r = do_sema_b_wait (_c->sema_b, 1, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
+      if (r != 0)
+      {
+	LeaveCriticalSection (&_c->waiters_count_lock_);
+	/* pthread_testcancel(); */
+	return r;
+      }
+      if (_c->waiters_count_gone_ != 0)
+      {
+	_c->waiters_count_ -= _c->waiters_count_gone_;
+	_c->waiters_count_gone_ = 0;
+      }
+      _c->waiters_count_ -= 1;
+      _c->waiters_count_unblock_ = 1;
+    }
+  else
+    {
+      LeaveCriticalSection (&_c->waiters_count_lock_);
+      /* pthread_testcancel(); */
+      return 0;
+    }
+  LeaveCriticalSection (&_c->waiters_count_lock_);
+  r = do_sema_b_release(_c->sema_q, 1,&_c->waiters_q_lock_,&_c->value_q);
+  /* pthread_testcancel(); */
+  return r;
+}
+
+int
+pthread_cond_broadcast (pthread_cond_t *c)
+{
+  cond_t *_c;
+  int r;
+  int relCnt = 0;    
+
+  if (!c || !*c)
+    return EINVAL;
+  _c = (cond_t *)*c;
+  if (_c == (cond_t*)PTHREAD_COND_INITIALIZER)
+    return 0;
+  else if (_c->valid != (unsigned int)LIFE_COND)
+    return EINVAL;
+
+  EnterCriticalSection (&_c->waiters_count_lock_);
+  /* If there aren't any waiters, then this is a no-op.   */
+  if (_c->waiters_count_unblock_ != 0)
+    {
+      if (_c->waiters_count_ == 0)
+      {
+	LeaveCriticalSection (&_c->waiters_count_lock_);
+	/* pthread_testcancel(); */
+	return 0;
+      }
+      relCnt = _c->waiters_count_;
+      _c->waiters_count_ = 0;
+      _c->waiters_count_unblock_ += relCnt;
+    }
+  else if (_c->waiters_count_ > _c->waiters_count_gone_)
+    {
+      r = do_sema_b_wait (_c->sema_b, 1, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
+      if (r != 0)
+      {
+	LeaveCriticalSection (&_c->waiters_count_lock_);
+	/* pthread_testcancel(); */
+	return r;
+      }
+      if (_c->waiters_count_gone_ != 0)
+      {
+	_c->waiters_count_ -= _c->waiters_count_gone_;
+	_c->waiters_count_gone_ = 0;
+      }
+      relCnt = _c->waiters_count_;
+      _c->waiters_count_ = 0;
+      _c->waiters_count_unblock_ = relCnt;
+    }
+  else
+    {
+      LeaveCriticalSection (&_c->waiters_count_lock_);
+      /* pthread_testcancel(); */
+      return 0;
+    }
+  LeaveCriticalSection (&_c->waiters_count_lock_);
+  r = do_sema_b_release(_c->sema_q, relCnt,&_c->waiters_q_lock_,&_c->value_q);
+  /* pthread_testcancel(); */
+  return r;
+}
+
+int
+pthread_cond_wait (pthread_cond_t *c, pthread_mutex_t *external_mutex)
+{
+  sCondWaitHelper ch;
+  cond_t *_c;
+  int r;
+
+  /* pthread_testcancel(); */
+
+  if (!c || *c == (pthread_cond_t)NULL)
+    return EINVAL;
+  _c = (cond_t *)*c;
+  if (*c == PTHREAD_COND_INITIALIZER)
+  {
+    r = cond_static_init(c);
+    if (r != 0 && r != EBUSY)
+      return r;
+    _c = (cond_t *) *c;
+  } else if (_c->valid != (unsigned int)LIFE_COND)
+    return EINVAL;
+
+tryagain:
+  r = do_sema_b_wait (_c->sema_b, 0, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
+  if (r != 0)
+    return r;
+
+  if (!TryEnterCriticalSection (&_c->waiters_count_lock_))
+  {
+    r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+    if (r != 0)
+      return r;
+    sched_yield();
+    goto tryagain;
+  }
+
+  _c->waiters_count_++;
+  LeaveCriticalSection(&_c->waiters_count_lock_);
+  r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+  if (r != 0)
+    return r;
+
+  ch.c = _c;
+  ch.r = &r;
+  ch.external_mutex = external_mutex;
+
+  pthread_cleanup_push(cleanup_wait, (void *) &ch);
+  r = pthread_mutex_unlock(external_mutex);
+  if (!r)
+    r = do_sema_b_wait (_c->sema_q, 0, INFINITE,&_c->waiters_q_lock_,&_c->value_q);
+
+  pthread_cleanup_pop(1);
+  return r;
+}
+
+static int
+pthread_cond_timedwait_impl (pthread_cond_t *c, pthread_mutex_t *external_mutex, const struct timespec *t, int rel)
+{
+  sCondWaitHelper ch;
+  DWORD dwr;
+  int r;
+  cond_t *_c;
+
+  /* pthread_testcancel(); */
+
+  if (!c || !*c)
+    return EINVAL;
+  _c = (cond_t *)*c;
+  if (_c == (cond_t *)PTHREAD_COND_INITIALIZER)
+  {
+    r = cond_static_init(c);
+    if (r && r != EBUSY)
+      return r;
+    _c = (cond_t *) *c;
+  } else if ((_c)->valid != (unsigned int)LIFE_COND)
+    return EINVAL;
+
+  if (rel == 0)
+  {
+    dwr = dwMilliSecs(_pthread_rel_time_in_ms(t));
+  }
+  else
+  {
+    dwr = dwMilliSecs(_pthread_time_in_ms_from_timespec(t));
+  }
+
+tryagain:
+  r = do_sema_b_wait (_c->sema_b, 0, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
+  if (r != 0)
+    return r;
+
+  if (!TryEnterCriticalSection (&_c->waiters_count_lock_))
+  {
+    r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+    if (r != 0)
+      return r;
+    sched_yield();
+    goto tryagain;
+  }
+
+  _c->waiters_count_++;
+  LeaveCriticalSection(&_c->waiters_count_lock_);
+  r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+  if (r != 0)
+    return r;
+
+  ch.c = _c;
+  ch.r = &r;
+  ch.external_mutex = external_mutex;
+  {
+    pthread_cleanup_push(cleanup_wait, (void *) &ch);
+
+    r = pthread_mutex_unlock(external_mutex);
+    if (!r)
+      r = do_sema_b_wait (_c->sema_q, 0, dwr,&_c->waiters_q_lock_,&_c->value_q);
+
+    pthread_cleanup_pop(1);
+  }
+  return r;
+}
+
+int
+pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct timespec *t)
+{
+  return pthread_cond_timedwait_impl(c, m, t, 0);
+}
+
+int
+pthread_cond_timedwait_relative_np(pthread_cond_t *c, pthread_mutex_t *m, const struct timespec *t)
+{
+  return pthread_cond_timedwait_impl(c, m, t, 1);
+}
+
+static void
+cleanup_wait (void *arg)
+{
+  int n, r;
+  sCondWaitHelper *ch = (sCondWaitHelper *) arg;
+  cond_t *_c;
+
+  _c = ch->c;
+  EnterCriticalSection (&_c->waiters_count_lock_);
+  n = _c->waiters_count_unblock_;
+  if (n != 0)
+    _c->waiters_count_unblock_ -= 1;
+  else if ((INT_MAX/2) - 1 == _c->waiters_count_gone_)
+  {
+    _c->waiters_count_gone_ += 1;
+    r = do_sema_b_wait (_c->sema_b, 1, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
+    if (r != 0)
+    {
+      LeaveCriticalSection(&_c->waiters_count_lock_);
+      ch->r[0] = r;
+      return;
+    }
+    _c->waiters_count_ -= _c->waiters_count_gone_;
+    r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+    if (r != 0)
+    {
+      LeaveCriticalSection(&_c->waiters_count_lock_);
+      ch->r[0] = r;
+      return;
+    }
+    _c->waiters_count_gone_ = 0;
+  }
+  else
+    _c->waiters_count_gone_ += 1;
+  LeaveCriticalSection (&_c->waiters_count_lock_);
+
+  if (n == 1)
+  {
+    r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
+    if (r != 0)
+    {
+      ch->r[0] = r;
+      return;
+    }
+  }
+  r = pthread_mutex_lock(ch->external_mutex);
+  if (r != 0)
+    ch->r[0] = r;
+}
+
+static int
+do_sema_b_wait (HANDLE sema, int nointerrupt, DWORD timeout,CRITICAL_SECTION *cs, LONG *val)
+{
+  int r;
+  LONG v;
+  EnterCriticalSection(cs);
+  InterlockedDecrement(val);
+  v = val[0];
+  LeaveCriticalSection(cs);
+  if (v >= 0)
+    return 0;
+  r = do_sema_b_wait_intern (sema, nointerrupt, timeout);
+  EnterCriticalSection(cs);
+  if (r != 0)
+    InterlockedIncrement(val);
+  LeaveCriticalSection(cs);
+  return r;
+}
+
+int
+do_sema_b_wait_intern (HANDLE sema, int nointerrupt, DWORD timeout)
+{
+  HANDLE arr[2];
+  DWORD maxH = 1;
+  int r = 0;
+  DWORD res, dt;
+  if (nointerrupt == 1)
+  {
+    res = _pthread_wait_for_single_object(sema, timeout);
+    switch (res) {
+    case WAIT_TIMEOUT:
+	r = ETIMEDOUT;
+	break;
+    case WAIT_ABANDONED:
+	r = EPERM;
+	break;
+    case WAIT_OBJECT_0:
+	break;
+    default:
+	/*We can only return EINVAL though it might not be posix compliant  */
+	r = EINVAL;
+    }
+    if (r != 0 && r != EINVAL && WaitForSingleObject(sema, 0) == WAIT_OBJECT_0)
+      r = 0;
+    return r;
+  }
+  arr[0] = sema;
+  arr[1] = (HANDLE) pthread_getevent ();
+  if (arr[1] != NULL) maxH += 1;
+  if (maxH == 2)
+  {
+redo:
+      res = _pthread_wait_for_multiple_objects(maxH, arr, 0, timeout);
+      switch (res) {
+      case WAIT_TIMEOUT:
+	  r = ETIMEDOUT;
+	  break;
+      case (WAIT_OBJECT_0 + 1):
+          ResetEvent(arr[1]);
+          if (nointerrupt != 2)
+	    {
+            pthread_testcancel();
+            return EINVAL;
+	    }
+	  pthread_testcancel ();
+	  goto redo;
+      case WAIT_ABANDONED:
+	  r = EPERM;
+	  break;
+      case WAIT_OBJECT_0:
+          r = 0;
+	  break;
+      default:
+	  /*We can only return EINVAL though it might not be posix compliant  */
+	  r = EINVAL;
+      }
+      if (r != 0 && r != EINVAL && WaitForSingleObject(arr[0], 0) == WAIT_OBJECT_0)
+	r = 0;
+      if (r != 0 && nointerrupt != 2 && __pthread_shallcancel ())
+	return EINVAL;
+      return r;
+  }
+  if (timeout == INFINITE)
+  {
+    do {
+      res = _pthread_wait_for_single_object(sema, 40);
+      switch (res) {
+      case WAIT_TIMEOUT:
+	  r = ETIMEDOUT;
+	  break;
+      case WAIT_ABANDONED:
+	  r = EPERM;
+	  break;
+      case WAIT_OBJECT_0:
+          r = 0;
+	  break;
+      default:
+	  /*We can only return EINVAL though it might not be posix compliant  */
+	  r = EINVAL;
+      }
+      if (r != 0 && __pthread_shallcancel ())
+      {
+	if (nointerrupt != 2)
+	  pthread_testcancel();
+	return EINVAL;
+      }
+    } while (r == ETIMEDOUT);
+    if (r != 0 && r != EINVAL && WaitForSingleObject(sema, 0) == WAIT_OBJECT_0)
+      r = 0;
+    return r;
+  }
+  dt = 20;
+  do {
+    if (dt > timeout) dt = timeout;
+    res = _pthread_wait_for_single_object(sema, dt);
+    switch (res) {
+    case WAIT_TIMEOUT:
+	r = ETIMEDOUT;
+	break;
+    case WAIT_ABANDONED:
+	r = EPERM;
+	break;
+    case WAIT_OBJECT_0:
+	r = 0;
+	break;
+    default:
+	/*We can only return EINVAL though it might not be posix compliant  */
+	r = EINVAL;
+    }
+    timeout -= dt;
+    if (timeout != 0 && r != 0 && __pthread_shallcancel ())
+      return EINVAL;
+  } while (r == ETIMEDOUT && timeout != 0);
+  if (r != 0 && r == ETIMEDOUT && WaitForSingleObject(sema, 0) == WAIT_OBJECT_0)
+    r = 0;
+  if (r != 0 && nointerrupt != 2)
+    pthread_testcancel();
+  return r;
+}
+
+static int
+do_sema_b_release(HANDLE sema, LONG count,CRITICAL_SECTION *cs, LONG *val)
+{
+  int wc;
+  EnterCriticalSection(cs);
+  if (((long long) val[0] + (long long) count) > (long long) 0x7fffffffLL)
+  {
+    LeaveCriticalSection(cs);
+    return ERANGE;
+  }
+  wc = -val[0];
+  InterlockedExchangeAdd(val, count);
+  if (wc <= 0 || ReleaseSemaphore(sema, (wc < count ? wc : count), NULL))
+  {
+    LeaveCriticalSection(cs);
+    return 0;
+  }
+  InterlockedExchangeAdd(val, -count);
+  LeaveCriticalSection(cs);
+  return EINVAL;  
+}
diff --git a/libs/winpthreads/src/cond.h b/libs/winpthreads/src/cond.h
new file mode 100644
index 00000000000..c70d3114617
--- /dev/null
+++ b/libs/winpthreads/src/cond.h
@@ -0,0 +1,61 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_COND_H
+#define WIN_PTHREADS_COND_H
+
+#include <windows.h>
+
+#define CHECK_COND(c)  { \
+    if (!(c) || !*c || (*c == PTHREAD_COND_INITIALIZER) \
+        || ( ((cond_t *)(*c))->valid != (unsigned int)LIFE_COND ) ) \
+        return EINVAL; }
+
+#define LIFE_COND 0xC0BAB1FD
+#define DEAD_COND 0xC0DEADBF
+
+#define STATIC_COND_INITIALIZER(x)		((pthread_cond_t)(x) == ((pthread_cond_t)PTHREAD_COND_INITIALIZER))
+
+typedef struct cond_t cond_t;
+struct cond_t
+{
+    unsigned int valid;   
+    int busy;
+    LONG waiters_count_; /* Number of waiting threads.  */
+    LONG waiters_count_unblock_; /* Number of waiting threads whitch can be unblocked.  */
+    LONG waiters_count_gone_; /* Number of waiters which are gone.  */
+    CRITICAL_SECTION waiters_count_lock_; /* Serialize access to <waiters_count_>.  */
+    CRITICAL_SECTION waiters_q_lock_; /* Serialize access to sema_q.  */
+    LONG value_q;
+    CRITICAL_SECTION waiters_b_lock_; /* Serialize access to sema_b.  */
+    LONG value_b;
+    HANDLE sema_q; /* Semaphore used to queue up threads waiting for the condition to
+                 become signaled.  */
+    HANDLE sema_b; /* Semaphore used to queue up threads waiting for the condition which
+                 became signaled.  */
+};
+
+void cond_print_set(int state, FILE *f);
+
+void cond_print(volatile pthread_cond_t *c, char *txt);
+
+#endif
diff --git a/libs/winpthreads/src/libgcc/dll_dependency.S b/libs/winpthreads/src/libgcc/dll_dependency.S
new file mode 100644
index 00000000000..0496e9406fe
--- /dev/null
+++ b/libs/winpthreads/src/libgcc/dll_dependency.S
@@ -0,0 +1,90 @@
+/* Implementation for gcc's internal stack-allocation routines.  */
+#if defined(__i386__) || defined(__x86_64__)
+.global ___chkstk
+.global	__alloca
+
+.global ___chkstk_ms
+___chkstk_ms:
+#ifdef _WIN64
+	pushq	%rax
+	pushq	%rcx
+	cmpq	$0x1000, %rax
+	leaq	24(%rsp), %rcx
+	jb	.Lchkstk_ms_end
+.Lchkstk_ms_loop:
+	subq	$0x1000, %rcx
+	subq	$0x1000, %rax
+	orq	$0x0, (%rcx)
+	cmpq	$0x1000, %rax
+	ja	.Lchkstk_ms_loop
+.Lchkstk_ms_end:
+	subq	%rax, %rcx
+	orq	$0x0, (%rcx)
+	popq	%rcx
+	popq	%rax
+	ret
+#else
+	pushl	%eax
+	pushl	%ecx
+	cmpl	$0x1000, %eax
+	leal	12(%esp), %ecx
+	jb	chkstk_ms_end
+chkstk_ms_loop:
+	subl	$0x1000, %ecx
+	subl	$0x1000, %eax
+	orl	$0x0, (%ecx)
+	cmpl	$0x1000, %eax
+	ja	chkstk_ms_loop
+chkstk_ms_end:
+	subl	%eax, %ecx
+	orl	$0x0, (%ecx)
+	popl	%ecx
+	popl	%eax
+	ret
+#endif
+
+#ifdef _WIN64
+__alloca:
+	movq	%rcx, %rax
+.align	4
+___chkstk:
+	popq	%r11
+	movq	%rsp, %r10
+	cmpq	$0x1000, %rax
+	jb	.Lchkstk_end
+.Lchkstk_loop:
+	subq	$0x1000, %r10
+	subq	$0x1000, %rax
+	orl	$0x0, (%r10)
+	cmpq	$0x1000, %rax
+	ja	.Lchkstk_loop
+.Lchkstk_end:
+	subq	%rax, %r10
+	movq	%rsp, %rax
+	orl	$0x0, (%r10)
+	movq	%r10, %rsp
+	pushq	%r11
+	ret
+#else
+___chkstk:
+__alloca:
+	pushl	%ecx
+	leal	8(%esp), %ecx
+	cmpl	$0x1000, %eax		/* > 4k ?*/
+	jb	chkstk_end
+chkstk_loop:
+	subl	$0x1000, %ecx
+	subl	$0x1000, %eax
+	orl	$0x0, (%ecx)
+	cmpl	$0x1000, %eax
+	ja	chkstk_loop
+chkstk_end:
+	subl	%eax, %ecx	   
+	orl	$0x0, (%ecx)
+	movl	%esp, %eax
+	movl	%ecx, %esp
+	movl	(%eax), %ecx
+	pushl	4(%eax)
+	ret
+#endif
+#endif
diff --git a/libs/winpthreads/src/libgcc/dll_math.c b/libs/winpthreads/src/libgcc/dll_math.c
new file mode 100644
index 00000000000..aeec068055c
--- /dev/null
+++ b/libs/winpthreads/src/libgcc/dll_math.c
@@ -0,0 +1,579 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LIBKERN_QUAD_H_
+#define	_LIBKERN_QUAD_H_
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *  - The type long long (aka quad_t) exists.
+ *
+ *  - A quad variable is exactly twice as long as `long'.
+ *
+ *  - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with 128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */
+/*
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/limits.h>
+#include <sys/syslimits.h>
+*/
+
+#include <limits.h>
+typedef long long quad_t;
+typedef unsigned long long u_quad_t;
+typedef unsigned long u_long;
+#define CHAR_BIT __CHAR_BIT__
+
+/*
+ * Define the order of 32-bit words in 64-bit words.
+ * For little endian only.
+ */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+	quad_t	q;		/* as a (signed) quad */
+	quad_t	uq;		/* as an unsigned quad */
+	long	sl[2];		/* as two signed longs */
+	u_long	ul[2];		/* as two unsigned longs */
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define	H		_QUAD_HIGHWORD
+#define	L		_QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define	QUAD_BITS	(sizeof(quad_t) * CHAR_BIT)
+#define	LONG_BITS	(sizeof(long) * CHAR_BIT)
+#define	HALF_BITS	(sizeof(long) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)).  (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */
+#define	HHALF(x)	((x) >> HALF_BITS)
+#define	LHALF(x)	((x) & ((1 << HALF_BITS) - 1))
+#define	LHUP(x)		((x) << HALF_BITS)
+
+typedef unsigned int	qshift_t;
+
+quad_t		__ashldi3(quad_t, qshift_t);
+quad_t		__ashrdi3(quad_t, qshift_t);
+int		__cmpdi2(quad_t a, quad_t b);
+quad_t		__divdi3(quad_t a, quad_t b);
+quad_t		__lshrdi3(quad_t, qshift_t);
+quad_t		__moddi3(quad_t a, quad_t b);
+u_quad_t	__qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+u_quad_t	__udivdi3(u_quad_t a, u_quad_t b);
+u_quad_t	__umoddi3(u_quad_t a, u_quad_t b);
+int		__ucmpdi2(u_quad_t a, u_quad_t b);
+quad_t	__divmoddi4(quad_t a, quad_t b, quad_t *rem);
+
+#endif /* !_LIBKERN_QUAD_H_ */
+
+#if defined (_X86_) && !defined (__x86_64__)
+/*
+ * Shift a (signed) quad value left (arithmetic shift left).
+ * This is the same as logical shift left!
+ */
+quad_t
+__ashldi3(a, shift)
+	quad_t a;
+	qshift_t shift;
+{
+	union uu aa;
+
+	aa.q = a;
+	if (shift >= LONG_BITS) {
+		aa.ul[H] = shift >= QUAD_BITS ? 0 :
+		    aa.ul[L] << (shift - LONG_BITS);
+		aa.ul[L] = 0;
+	} else if (shift > 0) {
+		aa.ul[H] = (aa.ul[H] << shift) |
+		    (aa.ul[L] >> (LONG_BITS - shift));
+		aa.ul[L] <<= shift;
+	}
+	return (aa.q);
+}
+
+/*
+ * Shift a (signed) quad value right (arithmetic shift right).
+ */
+quad_t
+__ashrdi3(a, shift)
+	quad_t a;
+	qshift_t shift;
+{
+	union uu aa;
+
+	aa.q = a;
+	if (shift >= LONG_BITS) {
+		long s;
+
+		/*
+		 * Smear bits rightward using the machine's right-shift
+		 * method, whether that is sign extension or zero fill,
+		 * to get the `sign word' s.  Note that shifting by
+		 * LONG_BITS is undefined, so we shift (LONG_BITS-1),
+		 * then 1 more, to get our answer.
+		 */
+		s = (aa.sl[H] >> (LONG_BITS - 1)) >> 1;
+		aa.ul[L] = shift >= QUAD_BITS ? s :
+		    aa.sl[H] >> (shift - LONG_BITS);
+		aa.ul[H] = s;
+	} else if (shift > 0) {
+		aa.ul[L] = (aa.ul[L] >> shift) |
+		    (aa.ul[H] << (LONG_BITS - shift));
+		aa.sl[H] >>= shift;
+	}
+	return (aa.q);
+}
+
+/*
+ * Return 0, 1, or 2 as a <, =, > b respectively.
+ * Both a and b are considered signed---which means only the high word is
+ * signed.
+ */
+int
+__cmpdi2(a, b)
+	quad_t a, b;
+{
+	union uu aa, bb;
+
+	aa.q = a;
+	bb.q = b;
+	return (aa.sl[H] < bb.sl[H] ? 0 : aa.sl[H] > bb.sl[H] ? 2 :
+	    aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1);
+}
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(a, b)
+	quad_t a, b;
+{
+	u_quad_t ua, ub, uq;
+	int neg;
+
+	if (a < 0)
+		ua = -(u_quad_t)a, neg = 1;
+	else
+		ua = a, neg = 0;
+	if (b < 0)
+		ub = -(u_quad_t)b, neg ^= 1;
+	else
+		ub = b;
+	uq = __qdivrem(ua, ub, (u_quad_t *)0);
+	return (neg ? -uq : uq);
+}
+
+/*
+ * Shift an (unsigned) quad value right (logical shift right).
+ */
+quad_t
+__lshrdi3(a, shift)
+	quad_t a;
+	qshift_t shift;
+{
+	union uu aa;
+
+	aa.q = a;
+	if (shift >= LONG_BITS) {
+		aa.ul[L] = shift >= QUAD_BITS ? 0 :
+		    aa.ul[H] >> (shift - LONG_BITS);
+		aa.ul[H] = 0;
+	} else if (shift > 0) {
+		aa.ul[L] = (aa.ul[L] >> shift) |
+		    (aa.ul[H] << (LONG_BITS - shift));
+		aa.ul[H] >>= shift;
+	}
+	return (aa.q);
+}
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(a, b)
+	quad_t a, b;
+{
+	u_quad_t ua, ub, ur;
+	int neg;
+
+	if (a < 0)
+		ua = -(u_quad_t)a, neg = 1;
+	else
+		ua = a, neg = 0;
+	if (b < 0)
+		ub = -(u_quad_t)b;
+	else
+		ub = b;
+	(void)__qdivrem(ua, ub, &ur);
+	return (neg ? -ur : ur);
+}
+
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#define	B	(1 << HALF_BITS)	/* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define	COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+__shl(register digit *p, register int len, register int sh)
+{
+	register int i;
+
+	for (i = 0; i < len; i++)
+		p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+	p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long.  As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(uq, vq, arq)
+	u_quad_t uq, vq, *arq;
+{
+	union uu tmp;
+	digit *u, *v, *q;
+	register digit v1, v2;
+	u_long qhat, rhat, t;
+	int m, n, d, j, i;
+	digit uspace[5], vspace[5], qspace[5];
+
+	/*
+	 * Take care of special cases: divide by zero, and u < v.
+	 */
+	if (vq == 0) {
+		/* divide by zero. */
+		static volatile const unsigned int zero = 0;
+
+		tmp.ul[H] = tmp.ul[L] = 1 / zero;
+		if (arq)
+			*arq = uq;
+		return (tmp.q);
+	}
+	if (uq < vq) {
+		if (arq)
+			*arq = uq;
+		return (0);
+	}
+	u = &uspace[0];
+	v = &vspace[0];
+	q = &qspace[0];
+
+	/*
+	 * Break dividend and divisor into digits in base B, then
+	 * count leading zeros to determine m and n.  When done, we
+	 * will have:
+	 *	u = (u[1]u[2]...u[m+n]) sub B
+	 *	v = (v[1]v[2]...v[n]) sub B
+	 *	v[1] != 0
+	 *	1 < n <= 4 (if n = 1, we use a different division algorithm)
+	 *	m >= 0 (otherwise u < v, which we already checked)
+	 *	m + n = 4
+	 * and thus
+	 *	m = 4 - n <= 2
+	 */
+	tmp.uq = uq;
+	u[0] = 0;
+	u[1] = HHALF(tmp.ul[H]);
+	u[2] = LHALF(tmp.ul[H]);
+	u[3] = HHALF(tmp.ul[L]);
+	u[4] = LHALF(tmp.ul[L]);
+	tmp.uq = vq;
+	v[1] = HHALF(tmp.ul[H]);
+	v[2] = LHALF(tmp.ul[H]);
+	v[3] = HHALF(tmp.ul[L]);
+	v[4] = LHALF(tmp.ul[L]);
+	for (n = 4; v[1] == 0; v++) {
+		if (--n == 1) {
+			u_long rbj;	/* r*B+u[j] (not root boy jim) */
+			digit q1, q2, q3, q4;
+
+			/*
+			 * Change of plan, per exercise 16.
+			 *	r = 0;
+			 *	for j = 1..4:
+			 *		q[j] = floor((r*B + u[j]) / v),
+			 *		r = (r*B + u[j]) % v;
+			 * We unroll this completely here.
+			 */
+			t = v[2];	/* nonzero, by definition */
+			q1 = u[1] / t;
+			rbj = COMBINE(u[1] % t, u[2]);
+			q2 = rbj / t;
+			rbj = COMBINE(rbj % t, u[3]);
+			q3 = rbj / t;
+			rbj = COMBINE(rbj % t, u[4]);
+			q4 = rbj / t;
+			if (arq)
+				*arq = rbj % t;
+			tmp.ul[H] = COMBINE(q1, q2);
+			tmp.ul[L] = COMBINE(q3, q4);
+			return (tmp.q);
+		}
+	}
+
+	/*
+	 * By adjusting q once we determine m, we can guarantee that
+	 * there is a complete four-digit quotient at &qspace[1] when
+	 * we finally stop.
+	 */
+	for (m = 4 - n; u[1] == 0; u++)
+		m--;
+	for (i = 4 - m; --i >= 0;)
+		q[i] = 0;
+	q += 4 - m;
+
+	/*
+	 * Here we run Program D, translated from MIX to C and acquiring
+	 * a few minor changes.
+	 *
+	 * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+	 */
+	d = 0;
+	for (t = v[1]; t < B / 2; t <<= 1)
+		d++;
+	if (d > 0) {
+		__shl(&u[0], m + n, d);		/* u <<= d */
+		__shl(&v[1], n - 1, d);		/* v <<= d */
+	}
+	/*
+	 * D2: j = 0.
+	 */
+	j = 0;
+	v1 = v[1];	/* for D3 -- note that v[1..n] are constant */
+	v2 = v[2];	/* for D3 */
+	do {
+		register digit uj0, uj1, uj2;
+
+		/*
+		 * D3: Calculate qhat (\^q, in TeX notation).
+		 * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+		 * let rhat = (u[j]*B + u[j+1]) mod v[1].
+		 * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+		 * decrement qhat and increase rhat correspondingly.
+		 * Note that if rhat >= B, v[2]*qhat < rhat*B.
+		 */
+		uj0 = u[j + 0];	/* for D3 only -- note that u[j+...] change */
+		uj1 = u[j + 1];	/* for D3 only */
+		uj2 = u[j + 2];	/* for D3 only */
+		if (uj0 == v1) {
+			qhat = B;
+			rhat = uj1;
+			goto qhat_too_big;
+		} else {
+			u_long nn = COMBINE(uj0, uj1);
+			qhat = nn / v1;
+			rhat = nn % v1;
+		}
+		while (v2 * qhat > COMBINE(rhat, uj2)) {
+	qhat_too_big:
+			qhat--;
+			if ((rhat += v1) >= B)
+				break;
+		}
+		/*
+		 * D4: Multiply and subtract.
+		 * The variable `t' holds any borrows across the loop.
+		 * We split this up so that we do not require v[0] = 0,
+		 * and to eliminate a final special case.
+		 */
+		for (t = 0, i = n; i > 0; i--) {
+			t = u[i + j] - v[i] * qhat - t;
+			u[i + j] = LHALF(t);
+			t = (B - HHALF(t)) & (B - 1);
+		}
+		t = u[j] - t;
+		u[j] = LHALF(t);
+		/*
+		 * D5: test remainder.
+		 * There is a borrow if and only if HHALF(t) is nonzero;
+		 * in that (rare) case, qhat was too large (by exactly 1).
+		 * Fix it by adding v[1..n] to u[j..j+n].
+		 */
+		if (HHALF(t)) {
+			qhat--;
+			for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+				t += u[i + j] + v[i];
+				u[i + j] = LHALF(t);
+				t = HHALF(t);
+			}
+			u[j] = LHALF(u[j] + t);
+		}
+		q[j] = qhat;
+	} while (++j <= m);		/* D7: loop on j. */
+
+	/*
+	 * If caller wants the remainder, we have to calculate it as
+	 * u[m..m+n] >> d (this is at most n digits and thus fits in
+	 * u[m+1..m+n], but we may need more source digits).
+	 */
+	if (arq) {
+		if (d) {
+			for (i = m + n; i > m; --i)
+				u[i] = (u[i] >> d) |
+				    LHALF(u[i - 1] << (HALF_BITS - d));
+			u[i] = 0;
+		}
+		tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+		tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+		*arq = tmp.q;
+	}
+
+	tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+	tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+	return (tmp.q);
+}
+
+/*
+ * Return 0, 1, or 2 as a <, =, > b respectively.
+ * Neither a nor b are considered signed.
+ */
+int
+__ucmpdi2(a, b)
+	u_quad_t a, b;
+{
+	union uu aa, bb;
+
+	aa.uq = a;
+	bb.uq = b;
+	return (aa.ul[H] < bb.ul[H] ? 0 : aa.ul[H] > bb.ul[H] ? 2 :
+	    aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1);
+}
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(a, b)
+	u_quad_t a, b;
+{
+
+	return (__qdivrem(a, b, (u_quad_t *)0));
+}
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(a, b)
+	u_quad_t a, b;
+{
+	u_quad_t r;
+
+	(void)__qdivrem(a, b, &r);
+	return (r);
+}
+
+/*
+ * Divide two signed quads.
+ * This function is new in GCC 7.
+ */
+quad_t
+__divmoddi4(a, b, rem)
+	quad_t a, b, *rem;
+{
+	u_quad_t ua, ub, uq, ur;
+	int negq, negr;
+
+	if (a < 0)
+		ua = -(u_quad_t)a, negq = 1, negr = 1;
+	else
+		ua = a, negq = 0, negr = 0;
+	if (b < 0)
+		ub = -(u_quad_t)b, negq ^= 1;
+	else
+		ub = b;
+	uq = __qdivrem(ua, ub, &ur);
+	if (rem)
+		*rem = (negr ? -ur : ur);
+	return (negq ? -uq : uq);
+}
+
+#else
+static int __attribute__((unused)) dummy;
+#endif /*deined (_X86_) && !defined (__x86_64__)*/
+
diff --git a/libs/winpthreads/src/misc.c b/libs/winpthreads/src/misc.c
new file mode 100644
index 00000000000..16ed488ecf5
--- /dev/null
+++ b/libs/winpthreads/src/misc.c
@@ -0,0 +1,158 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include "pthread.h"
+#include "windows.h"
+#include "misc.h"
+
+unsigned long long _pthread_time_in_ms(void)
+{
+    FILETIME ft;
+
+    GetSystemTimeAsFileTime(&ft);
+    return (((unsigned long long)ft.dwHighDateTime << 32) + ft.dwLowDateTime
+            - 0x19DB1DED53E8000ULL) / 10000ULL;
+}
+
+unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts)
+{
+    unsigned long long t = (unsigned long long) ts->tv_sec * 1000LL;
+    /* The +999999 is here to ensure that the division always rounds up */
+    t += (unsigned long long) (ts->tv_nsec + 999999) / 1000000;
+
+    return t;
+}
+
+unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
+{
+    unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
+    unsigned long long t2 = _pthread_time_in_ms();
+
+    /* Prevent underflow */
+    if (t1 < t2) return 0;
+    return t1 - t2;
+}
+
+static unsigned long long
+_pthread_get_tick_count (long long *frequency)
+{
+#if defined (_WIN32_WINNT) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
+  (void) frequency; /* unused */
+  return GetTickCount64 ();
+#else
+  LARGE_INTEGER freq, timestamp;
+
+  if (*frequency == 0)
+  {
+    if (QueryPerformanceFrequency (&freq))
+      *frequency = freq.QuadPart;
+    else
+      *frequency = -1;
+  }
+
+  if (*frequency > 0 && QueryPerformanceCounter (&timestamp))
+    return timestamp.QuadPart / (*frequency / 1000);
+
+  /* Fallback */
+  return GetTickCount ();
+#endif
+}
+
+/* A wrapper around WaitForSingleObject() that ensures that
+ * the wait function does not time out before the time
+ * actually runs out. This is needed because WaitForSingleObject()
+ * might have poor accuracy, returning earlier than expected.
+ * On the other hand, returning a bit *later* than expected
+ * is acceptable in a preemptive multitasking environment.
+ */
+unsigned long
+_pthread_wait_for_single_object (void *handle, unsigned long timeout)
+{
+  DWORD result;
+  unsigned long long start_time, end_time;
+  unsigned long wait_time;
+  long long frequency = 0;
+
+  if (timeout == INFINITE || timeout == 0)
+    return WaitForSingleObject ((HANDLE) handle, (DWORD) timeout);
+
+  start_time = _pthread_get_tick_count (&frequency);
+  end_time = start_time + timeout;
+  wait_time = timeout;
+
+  do
+  {
+    unsigned long long current_time;
+
+    result = WaitForSingleObject ((HANDLE) handle, (DWORD) wait_time);
+    if (result != WAIT_TIMEOUT)
+      break;
+
+    current_time = _pthread_get_tick_count (&frequency);
+    if (current_time >= end_time)
+      break;
+
+    wait_time = (DWORD) (end_time - current_time);
+  } while (TRUE);
+
+  return result;
+}
+
+/* A wrapper around WaitForMultipleObjects() that ensures that
+ * the wait function does not time out before the time
+ * actually runs out. This is needed because WaitForMultipleObjects()
+ * might have poor accuracy, returning earlier than expected.
+ * On the other hand, returning a bit *later* than expected
+ * is acceptable in a preemptive multitasking environment.
+ */
+unsigned long
+_pthread_wait_for_multiple_objects (unsigned long count, void **handles, unsigned int all, unsigned long timeout)
+{
+  DWORD result;
+  unsigned long long start_time, end_time;
+  unsigned long wait_time;
+  long long frequency = 0;
+
+  if (timeout == INFINITE || timeout == 0)
+    return WaitForMultipleObjects ((DWORD) count, (HANDLE *) handles, all, (DWORD) timeout);
+
+  start_time = _pthread_get_tick_count (&frequency);
+  end_time = start_time + timeout;
+  wait_time = timeout;
+
+  do
+  {
+    unsigned long long current_time;
+
+    result = WaitForMultipleObjects ((DWORD) count, (HANDLE *) handles, all, (DWORD) wait_time);
+    if (result != WAIT_TIMEOUT)
+      break;
+
+    current_time = _pthread_get_tick_count (&frequency);
+    if (current_time >= end_time)
+      break;
+
+    wait_time = (DWORD) (end_time - current_time);
+  } while (TRUE);
+
+  return result;
+}
diff --git a/libs/winpthreads/src/misc.h b/libs/winpthreads/src/misc.h
new file mode 100644
index 00000000000..cdb242689d2
--- /dev/null
+++ b/libs/winpthreads/src/misc.h
@@ -0,0 +1,114 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_MISC_H
+#define WIN_PTHREADS_MISC_H
+
+#include "pthread_compat.h"
+
+#ifndef assert
+
+#ifndef ASSERT_TRACE
+# define ASSERT_TRACE 0
+#else
+# undef ASSERT_TRACE
+# define ASSERT_TRACE 0
+#endif
+
+# define assert(e) \
+   ((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \
+                                    "Assertion succeeded: (%s), file %s, line %d\n", \
+                        #e, __FILE__, (int) __LINE__), \
+                                fflush(stderr) : \
+                             0) : \
+          (fprintf(stderr, "Assertion failed: (%s), file %s, line %d\n", \
+                   #e, __FILE__, (int) __LINE__), exit(1), 0))
+
+# define fixme(e) \
+   ((e) ? ((ASSERT_TRACE) ? fprintf(stderr, \
+                                    "Assertion succeeded: (%s), file %s, line %d\n", \
+                        #e, __FILE__, (int) __LINE__), \
+                                fflush(stderr) : \
+                             0) : \
+          (fprintf(stderr, "FIXME: (%s), file %s, line %d\n", \
+                   #e, __FILE__, (int) __LINE__), 0, 0))
+
+#endif
+
+#define PTR2INT(x)	((int)(uintptr_t)(x))
+
+#if SIZE_MAX>UINT_MAX
+typedef long long LONGBAG;
+#else
+typedef long LONGBAG;
+#endif
+
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#undef GetHandleInformation
+#define GetHandleInformation(h,f)  (1)
+#endif
+
+#define CHECK_HANDLE(h) { DWORD dwFlags; \
+    if (!(h) || ((h) == INVALID_HANDLE_VALUE) || !GetHandleInformation((h), &dwFlags)) \
+    return EINVAL; }
+
+#define CHECK_PTR(p)    if (!(p)) return EINVAL;
+
+#define UPD_RESULT(x,r)    { int _r=(x); r = r ? r : _r; }
+
+#define CHECK_THREAD(t)  { \
+    CHECK_PTR(t); \
+    CHECK_HANDLE(t->h); }
+
+#define CHECK_OBJECT(o, e)  { DWORD dwFlags; \
+    if (!(o)) return e; \
+    if (!((o)->h) || (((o)->h) == INVALID_HANDLE_VALUE) || !GetHandleInformation(((o)->h), &dwFlags)) \
+        return e; }
+
+#define VALID(x)    if (!(p)) return EINVAL;
+
+/* ms can be 64 bit, solve wrap-around issues: */
+static WINPTHREADS_INLINE unsigned long dwMilliSecs(unsigned long long ms)
+{
+  if (ms >= 0xffffffffULL) return 0xfffffffful;
+  return (unsigned long) ms;
+}
+
+#ifndef _mm_pause
+#define _mm_pause()			{__asm__ __volatile__("pause");}
+#endif
+
+#ifndef _ReadWriteBarrier
+#define _ReadWriteBarrier   __sync_synchronize
+#endif
+
+#ifndef YieldProcessor
+#define YieldProcessor      _mm_pause
+#endif
+
+unsigned long long _pthread_time_in_ms(void);
+unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts);
+unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts);
+unsigned long _pthread_wait_for_single_object (void *handle, unsigned long timeout);
+unsigned long _pthread_wait_for_multiple_objects (unsigned long count, void **handles, unsigned int all, unsigned long timeout);
+
+#endif
diff --git a/libs/winpthreads/src/mutex.c b/libs/winpthreads/src/mutex.c
new file mode 100644
index 00000000000..c6f26139427
--- /dev/null
+++ b/libs/winpthreads/src/mutex.c
@@ -0,0 +1,385 @@
+/*
+   Copyright (c) 2011, 2014 mingw-w64 project
+   Copyright (c) 2015 Intel Corporation
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include "pthread.h"
+#include "misc.h"
+
+typedef enum {
+  Unlocked,        /* Not locked. */
+  Locked,          /* Locked but without waiters. */
+  Waiting,         /* Locked, may have waiters. */
+} mutex_state_t;
+
+typedef enum {
+  Normal,
+  Errorcheck,
+  Recursive,
+} mutex_type_t;
+
+/* The heap-allocated part of a mutex. */
+typedef struct {
+  mutex_state_t state;
+  mutex_type_t type;
+  HANDLE event;       /* Auto-reset event, or NULL if not yet allocated. */
+  unsigned rec_lock;  /* For recursive mutexes, the number of times the
+                         mutex has been locked in excess by the same thread. */
+  volatile DWORD owner;  /* For recursive and error-checking mutexes, the
+                            ID of the owning thread if the mutex is locked. */
+} mutex_impl_t;
+
+/* Whether a mutex is still a static initializer (not a pointer to
+   a mutex_impl_t). */
+static bool
+is_static_initializer(pthread_mutex_t m)
+{
+  /* Treat 0 as a static initializer as well (for normal mutexes),
+     to tolerate sloppy code in libgomp. (We should rather fix that code!) */
+  intptr_t v = (intptr_t)m;
+  return v >= -3 && v <= 0;
+/* Should be simple:
+  return (uintptr_t)m >= (uintptr_t)-3; */
+}
+
+/* Create and return the implementation part of a mutex from a static
+   initialiser. Return NULL on out-of-memory error. */
+static WINPTHREADS_ATTRIBUTE((noinline)) mutex_impl_t *
+mutex_impl_init(pthread_mutex_t *m, mutex_impl_t *mi)
+{
+  mutex_impl_t *new_mi = malloc(sizeof(mutex_impl_t));
+  if (new_mi == NULL)
+    return NULL;
+  new_mi->state = Unlocked;
+  new_mi->type = (mi == (void *)PTHREAD_RECURSIVE_MUTEX_INITIALIZER ? Recursive
+                  : mi == (void *)PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ? Errorcheck
+                  : Normal);
+  new_mi->event = NULL;
+  new_mi->rec_lock = 0;
+  new_mi->owner = (DWORD)-1;
+  if (__sync_bool_compare_and_swap(m, (pthread_mutex_t)mi, (pthread_mutex_t)new_mi)) {
+    return new_mi;
+  } else {
+    /* Someone created the struct before us. */
+    free(new_mi);
+    return (mutex_impl_t *)*m;
+  }
+}
+
+#define likely(cond) __builtin_expect((cond) != 0, 1)
+#define unlikely(cond) __builtin_expect((cond) != 0, 0)
+
+/* Return the implementation part of a mutex, creating it if necessary.
+   Return NULL on out-of-memory error. */
+static inline mutex_impl_t *
+mutex_impl(pthread_mutex_t *m)
+{
+  mutex_impl_t *mi = (mutex_impl_t *)*m;
+  if (is_static_initializer((pthread_mutex_t)mi)) {
+    return mutex_impl_init(m, mi);
+  } else {
+    /* mi cannot be null here; avoid a test in the fast path. */
+    if (mi == NULL)
+      __builtin_unreachable();
+    return mi;
+  }
+}
+
+/* Lock a mutex. Give up after 'timeout' ms (with ETIMEDOUT),
+   or never if timeout=INFINITE. */
+static inline int
+pthread_mutex_lock_intern (pthread_mutex_t *m, DWORD timeout)
+{
+  mutex_impl_t *mi = mutex_impl(m);
+  if (mi == NULL)
+    return ENOMEM;
+
+  mutex_state_t old_state = __sync_lock_test_and_set(&mi->state, Locked);
+  if (unlikely(old_state != Unlocked)) {
+    /* The mutex is already locked. */
+
+    if (mi->type != Normal) {
+      /* Recursive or Errorcheck */
+      if (mi->owner == GetCurrentThreadId()) {
+        /* FIXME: A recursive mutex should not need two atomic ops when locking
+           recursively.  We could rewrite by doing compare-and-swap instead of
+           test-and-set the first time, but it would lead to more code
+           duplication and add a conditional branch to the critical path. */
+        __sync_bool_compare_and_swap(&mi->state, Locked, old_state);
+        if (mi->type == Recursive) {
+          mi->rec_lock++;
+          return 0;
+        } else {
+          /* type == Errorcheck */
+          return EDEADLK;
+        }
+      }
+    }
+
+    /* Make sure there is an event object on which to wait. */
+    if (mi->event == NULL) {
+      /* Make an auto-reset event object. */
+      HANDLE ev = CreateEvent(NULL, false, false, NULL);
+      if (ev == NULL) {
+        switch (GetLastError()) {
+        case ERROR_ACCESS_DENIED:
+          return EPERM;
+        default:
+          return ENOMEM;    /* Probably accurate enough. */
+        }
+      }
+      if (!__sync_bool_compare_and_swap(&mi->event, NULL, ev)) {
+        /* Someone created the event before us. */
+        CloseHandle(ev);
+      }
+    }
+
+    /* At this point, mi->event is non-NULL. */
+
+    while (__sync_lock_test_and_set(&mi->state, Waiting) != Unlocked) {
+      /* For timed locking attempts, it is possible (although unlikely)
+         that we are woken up but someone else grabs the lock before us,
+         and we have to go back to sleep again. In that case, the total
+         wait may be longer than expected. */
+
+      unsigned r = _pthread_wait_for_single_object(mi->event, timeout);
+      switch (r) {
+      case WAIT_TIMEOUT:
+        return ETIMEDOUT;
+      case WAIT_OBJECT_0:
+        break;
+      default:
+        return EINVAL;
+      }
+    }
+  }
+
+  if (mi->type != Normal)
+    mi->owner = GetCurrentThreadId();
+
+  return 0;
+}
+
+int
+pthread_mutex_lock (pthread_mutex_t *m)
+{
+  return pthread_mutex_lock_intern (m, INFINITE);
+}
+
+int pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec *ts)
+{
+  unsigned long long patience;
+  if (ts != NULL) {
+    unsigned long long end = _pthread_time_in_ms_from_timespec(ts);
+    unsigned long long now = _pthread_time_in_ms();
+    patience = end > now ? end - now : 0;
+    if (patience > 0xffffffff)
+      patience = INFINITE;
+  } else {
+    patience = INFINITE;
+  }
+  return pthread_mutex_lock_intern(m, patience);
+}
+
+int pthread_mutex_unlock(pthread_mutex_t *m)
+{    
+  /* Here m might an initialiser of an error-checking or recursive mutex, in
+     which case the behaviour is well-defined, so we can't skip this check. */
+  mutex_impl_t *mi = mutex_impl(m);
+  if (mi == NULL)
+    return ENOMEM;
+
+  if (unlikely(mi->type != Normal)) {
+    if (mi->state == Unlocked)
+      return EINVAL;
+    if (mi->owner != GetCurrentThreadId())
+      return EPERM;
+    if (mi->rec_lock > 0) {
+      mi->rec_lock--;
+      return 0;
+    }
+    mi->owner = (DWORD)-1;
+  }
+  if (unlikely(__sync_lock_test_and_set(&mi->state, Unlocked) == Waiting)) {
+    if (!SetEvent(mi->event))
+      return EPERM;
+  }
+  return 0;
+}
+
+int pthread_mutex_trylock(pthread_mutex_t *m)
+{
+  mutex_impl_t *mi = mutex_impl(m);
+  if (mi == NULL)
+    return ENOMEM;
+
+  if (__sync_bool_compare_and_swap(&mi->state, Unlocked, Locked)) {
+    if (mi->type != Normal)
+      mi->owner = GetCurrentThreadId();
+    return 0;
+  } else {
+    if (mi->type == Recursive && mi->owner == GetCurrentThreadId()) {
+      mi->rec_lock++;
+      return 0;
+    }
+    return EBUSY;
+  }
+}
+
+int
+pthread_mutex_init (pthread_mutex_t *m, const pthread_mutexattr_t *a)
+{
+  pthread_mutex_t init = PTHREAD_MUTEX_INITIALIZER;
+  if (a != NULL) {
+    int pshared;
+    if (pthread_mutexattr_getpshared(a, &pshared) == 0
+        && pshared == PTHREAD_PROCESS_SHARED)
+      return ENOSYS;
+
+    int type;
+    if (pthread_mutexattr_gettype(a, &type) == 0) {
+      switch (type) {
+      case PTHREAD_MUTEX_ERRORCHECK:
+        init = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
+        break;
+      case PTHREAD_MUTEX_RECURSIVE:
+        init = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+        break;
+      default:
+        init = PTHREAD_MUTEX_INITIALIZER;
+        break;
+      }
+    }
+  }
+  *m = init;
+  return 0;
+}
+
+int pthread_mutex_destroy (pthread_mutex_t *m)
+{
+  mutex_impl_t *mi = (mutex_impl_t *)*m;
+  if (!is_static_initializer((pthread_mutex_t)mi)) {
+    if (mi->event != NULL)
+      CloseHandle(mi->event);
+    free(mi);
+    /* Sabotage attempts to re-use the mutex before initialising it again. */
+    *m = (pthread_mutex_t)NULL;
+  }
+
+  return 0;
+}
+
+int pthread_mutexattr_init(pthread_mutexattr_t *a)
+{
+  *a = PTHREAD_MUTEX_NORMAL | (PTHREAD_PROCESS_PRIVATE << 3);
+  return 0;
+}
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
+{
+  if (!a)
+    return EINVAL;
+
+  return 0;
+}
+
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *a, int *type)
+{
+  if (!a || !type)
+    return EINVAL;
+	
+  *type = *a & 3;
+  
+  return 0;
+}
+
+int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type)
+{
+    if (!a || (type != PTHREAD_MUTEX_NORMAL && type != PTHREAD_MUTEX_RECURSIVE && type != PTHREAD_MUTEX_ERRORCHECK))
+      return EINVAL;
+    *a &= ~3;
+    *a |= type;
+
+    return 0;
+}
+
+int pthread_mutexattr_getpshared(const pthread_mutexattr_t *a, int *type)
+{
+    if (!a || !type)
+      return EINVAL;
+    *type = (*a & 4 ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE);
+
+    return 0;
+}
+
+int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type)
+{
+    int r = 0;
+    if (!a || (type != PTHREAD_PROCESS_SHARED
+	&& type != PTHREAD_PROCESS_PRIVATE))
+      return EINVAL;
+    if (type == PTHREAD_PROCESS_SHARED)
+    {
+      type = PTHREAD_PROCESS_PRIVATE;
+      r = ENOSYS;
+    }
+    type = (type == PTHREAD_PROCESS_SHARED ? 4 : 0);
+
+    *a &= ~4;
+    *a |= type;
+
+    return r;
+}
+
+int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *a, int *type)
+{
+    *type = *a & (8 + 16);
+
+    return 0;
+}
+
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type)
+{
+    if ((type & (8 + 16)) != 8 + 16) return EINVAL;
+
+    *a &= ~(8 + 16);
+    *a |= type;
+
+    return 0;
+}
+
+int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *a, int * prio)
+{
+    *prio = *a / PTHREAD_PRIO_MULT;
+    return 0;
+}
+
+int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio)
+{
+    *a &= (PTHREAD_PRIO_MULT - 1);
+    *a += prio * PTHREAD_PRIO_MULT;
+
+    return 0;
+}
diff --git a/libs/winpthreads/src/nanosleep.c b/libs/winpthreads/src/nanosleep.c
new file mode 100644
index 00000000000..0cce4492e29
--- /dev/null
+++ b/libs/winpthreads/src/nanosleep.c
@@ -0,0 +1,71 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <errno.h>
+#include <time.h>
+#include <windows.h>
+#include "pthread.h"
+#include "pthread_time.h"
+#include "winpthread_internal.h"
+
+#define POW10_3                 1000
+#define POW10_4                 10000
+#define POW10_6                 1000000
+#define POW10_9                 1000000000
+#define MAX_SLEEP_IN_MS         4294967294UL
+
+/**
+ * Sleep for the specified time.
+ * @param  request The desired amount of time to sleep.
+ * @param  remain The remain amount of time to sleep.
+ * @return If the function succeeds, the return value is 0.
+ *         If the function fails, the return value is -1,
+ *         with errno set to indicate the error.
+ */
+int nanosleep(const struct timespec *request, struct timespec *remain)
+{
+    unsigned long ms, rc = 0;
+    unsigned __int64 u64, want, real;
+
+    union {
+        unsigned __int64 ns100;
+        FILETIME ft;
+    }  _start, _end;
+
+    if (request->tv_sec < 0 || request->tv_nsec < 0 || request->tv_nsec >= POW10_9) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (remain != NULL) GetSystemTimeAsFileTime(&_start.ft);
+
+    want = u64 = request->tv_sec * POW10_3 + request->tv_nsec / POW10_6;
+    while (u64 > 0 && rc == 0) {
+        if (u64 >= MAX_SLEEP_IN_MS) ms = MAX_SLEEP_IN_MS;
+        else ms = (unsigned long) u64;
+
+        u64 -= ms;
+        rc = pthread_delay_np_ms(ms);
+    }
+
+    if (rc != 0) { /* WAIT_IO_COMPLETION (192) */
+        if (remain != NULL) {
+            GetSystemTimeAsFileTime(&_end.ft);
+            real = (_end.ns100 - _start.ns100) / POW10_4;
+
+            if (real >= want) u64 = 0;
+            else u64 = want - real;
+
+            remain->tv_sec = u64 / POW10_3;
+            remain->tv_nsec = (long) (u64 % POW10_3) * POW10_6;
+        }
+
+        errno = EINTR;
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/libs/winpthreads/src/ref.c b/libs/winpthreads/src/ref.c
new file mode 100644
index 00000000000..0344d457e9d
--- /dev/null
+++ b/libs/winpthreads/src/ref.c
@@ -0,0 +1,34 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <windows.h>
+#include <winternl.h>
+#include <stdio.h>
+#include "pthread.h"
+#include "semaphore.h"
+#include "rwlock.h"
+#include "cond.h"
+#include "barrier.h"
+#include "sem.h"
+#include "ref.h"
+#include "misc.h"
+
diff --git a/libs/winpthreads/src/ref.h b/libs/winpthreads/src/ref.h
new file mode 100644
index 00000000000..5ca67506fa1
--- /dev/null
+++ b/libs/winpthreads/src/ref.h
@@ -0,0 +1,29 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_REF_H
+#define WIN_PTHREADS_REF_H
+#include "pthread.h"
+#include "semaphore.h"
+
+#endif
+
diff --git a/libs/winpthreads/src/rwlock.c b/libs/winpthreads/src/rwlock.c
new file mode 100644
index 00000000000..933d438859f
--- /dev/null
+++ b/libs/winpthreads/src/rwlock.c
@@ -0,0 +1,533 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "pthread.h"
+#include "thread.h"
+#include "ref.h"
+#include "rwlock.h"
+#include "misc.h"
+
+static pthread_spinlock_t rwl_global = PTHREAD_SPINLOCK_INITIALIZER;
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int rwlock_static_init(pthread_rwlock_t *rw);
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int rwl_unref(volatile pthread_rwlock_t *rwl, int res)
+{
+    pthread_spin_lock(&rwl_global);
+#ifdef WINPTHREAD_DBG
+    assert((((rwlock_t *)*rwl)->valid == LIFE_RWLOCK) && (((rwlock_t *)*rwl)->busy > 0));
+#endif
+     ((rwlock_t *)*rwl)->busy--;
+    pthread_spin_unlock(&rwl_global);
+    return res;
+}
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int rwl_ref(pthread_rwlock_t *rwl, int f )
+{
+    int r = 0;
+    INIT_RWLOCK(rwl);
+    pthread_spin_lock(&rwl_global);
+
+    if (!rwl || !*rwl || ((rwlock_t *)*rwl)->valid != LIFE_RWLOCK) r = EINVAL;
+    else {
+        ((rwlock_t *)*rwl)->busy ++;
+    }
+
+    pthread_spin_unlock(&rwl_global);
+
+    return r;
+}
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int rwl_ref_unlock(pthread_rwlock_t *rwl )
+{
+    int r = 0;
+
+    pthread_spin_lock(&rwl_global);
+
+    if (!rwl || !*rwl || ((rwlock_t *)*rwl)->valid != LIFE_RWLOCK) r = EINVAL;
+    else if (STATIC_RWL_INITIALIZER(*rwl)) r= EPERM;
+    else {
+        ((rwlock_t *)*rwl)->busy ++;
+    }
+
+    pthread_spin_unlock(&rwl_global);
+
+    return r;
+}
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int rwl_ref_destroy(pthread_rwlock_t *rwl, pthread_rwlock_t *rDestroy )
+{
+    int r = 0;
+
+    *rDestroy = (pthread_rwlock_t)NULL;
+    pthread_spin_lock(&rwl_global);
+    
+    if (!rwl || !*rwl) r = EINVAL;
+    else {
+        rwlock_t *r_ = (rwlock_t *)*rwl;
+        if (STATIC_RWL_INITIALIZER(*rwl)) *rwl = (pthread_rwlock_t)NULL;
+        else if (r_->valid != LIFE_RWLOCK) r = EINVAL;
+        else if (r_->busy) r = EBUSY;
+        else {
+            *rDestroy = *rwl;
+            *rwl = (pthread_rwlock_t)NULL;
+        }
+    }
+
+    pthread_spin_unlock(&rwl_global);
+    return r;
+}
+
+static int rwlock_gain_both_locks(rwlock_t *rwlock)
+{
+  int ret;
+  ret = pthread_mutex_lock(&rwlock->mex);
+  if (ret != 0)
+    return ret;
+  ret = pthread_mutex_lock(&rwlock->mcomplete);
+  if (ret != 0)
+    pthread_mutex_unlock(&rwlock->mex);
+  return ret;
+}
+
+static int rwlock_free_both_locks(rwlock_t *rwlock, int last_fail)
+{
+  int ret, ret2;
+  ret = pthread_mutex_unlock(&rwlock->mcomplete);
+  ret2 = pthread_mutex_unlock(&rwlock->mex);
+  if (last_fail && ret2 != 0)
+    ret = ret2;
+  else if (!last_fail && !ret)
+    ret = ret2;
+  return ret;
+}
+
+#ifdef WINPTHREAD_DBG
+static int print_state = 0;
+void rwl_print_set(int state)
+{
+    print_state = state;
+}
+
+void rwl_print(volatile pthread_rwlock_t *rwl, char *txt)
+{
+    if (!print_state) return;
+    rwlock_t *r = (rwlock_t *)*rwl;
+    if (r == NULL) {
+        printf("RWL%p %d %s\n",(void *)*rwl,(int)GetCurrentThreadId(),txt);
+    } else {
+        printf("RWL%p %d V=%0X B=%d r=%ld w=%ld L=%p %s\n",
+            (void *)*rwl,
+            (int)GetCurrentThreadId(), 
+            (int)r->valid, 
+            (int)r->busy,
+            0L,0L,NULL,txt);
+    }
+}
+#endif
+
+static pthread_spinlock_t cond_locked = PTHREAD_SPINLOCK_INITIALIZER;
+
+static WINPTHREADS_ATTRIBUTE((noinline)) int rwlock_static_init(pthread_rwlock_t *rw)
+{
+  int r;
+  pthread_spin_lock(&cond_locked);
+  if (*rw != PTHREAD_RWLOCK_INITIALIZER)
+  {
+    pthread_spin_unlock(&cond_locked);
+    return EINVAL;
+  }
+  r = pthread_rwlock_init (rw, NULL);
+  pthread_spin_unlock(&cond_locked);
+  
+  return r;
+}
+
+int pthread_rwlock_init (pthread_rwlock_t *rwlock_, const pthread_rwlockattr_t *attr)
+{
+    rwlock_t *rwlock;
+    int r;
+
+    if(!rwlock_)
+      return EINVAL;
+    *rwlock_ = (pthread_rwlock_t)NULL;
+    if ((rwlock = calloc(1, sizeof(*rwlock))) == NULL)
+      return ENOMEM; 
+    rwlock->valid = DEAD_RWLOCK;
+
+    rwlock->nex_count = rwlock->nsh_count = rwlock->ncomplete = 0;
+    if ((r = pthread_mutex_init (&rwlock->mex, NULL)) != 0)
+    {
+        free(rwlock);
+        return r;
+    }
+    if ((r = pthread_mutex_init (&rwlock->mcomplete, NULL)) != 0)
+    {
+      pthread_mutex_destroy(&rwlock->mex);
+      free(rwlock);
+      return r;
+    }
+    if ((r = pthread_cond_init (&rwlock->ccomplete, NULL)) != 0)
+    {
+      pthread_mutex_destroy(&rwlock->mex);
+      pthread_mutex_destroy (&rwlock->mcomplete);
+      free(rwlock);
+      return r;
+    }
+    rwlock->valid = LIFE_RWLOCK;
+    *rwlock_ = (pthread_rwlock_t)rwlock;
+    return r;
+} 
+
+int pthread_rwlock_destroy (pthread_rwlock_t *rwlock_)
+{
+    rwlock_t *rwlock;
+    pthread_rwlock_t rDestroy;
+    int r, r2;
+    
+    pthread_spin_lock(&cond_locked);
+    r = rwl_ref_destroy(rwlock_,&rDestroy);
+    pthread_spin_unlock(&cond_locked);
+    
+    if(r) return r;
+    if(!rDestroy) return 0; /* destroyed a (still) static initialized rwl */
+
+    rwlock = (rwlock_t *)rDestroy;
+    r = rwlock_gain_both_locks (rwlock);
+    if (r != 0)
+    {
+      *rwlock_ = rDestroy;
+      return r;
+    }
+    if (rwlock->nsh_count > rwlock->ncomplete || rwlock->nex_count > 0)
+    {
+      *rwlock_ = rDestroy;
+      r = rwlock_free_both_locks(rwlock, 1);
+      if (!r)
+        r = EBUSY;
+      return r;
+    }
+    rwlock->valid  = DEAD_RWLOCK;
+    r = rwlock_free_both_locks(rwlock, 0);
+    if (r != 0) { *rwlock_ = rDestroy; return r; }
+
+    r = pthread_cond_destroy(&rwlock->ccomplete);
+    r2 = pthread_mutex_destroy(&rwlock->mex);
+    if (!r) r = r2;
+    r2 = pthread_mutex_destroy(&rwlock->mcomplete);
+    if (!r) r = r2;
+    rwlock->valid  = DEAD_RWLOCK;
+    free((void *)rDestroy);
+    return 0;
+} 
+
+int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock_)
+{
+  rwlock_t *rwlock;
+  int ret;
+
+  /* pthread_testcancel(); */
+
+  ret = rwl_ref(rwlock_,0);
+  if(ret != 0) return ret;
+
+  rwlock = (rwlock_t *)*rwlock_;
+
+  ret = pthread_mutex_lock(&rwlock->mex);
+  if (ret != 0) return rwl_unref(rwlock_, ret);
+  InterlockedIncrement((long*)&rwlock->nsh_count);
+  if (rwlock->nsh_count == INT_MAX)
+  {
+    ret = pthread_mutex_lock(&rwlock->mcomplete);
+    if (ret != 0)
+    {
+      pthread_mutex_unlock(&rwlock->mex);
+      return rwl_unref(rwlock_,ret);
+    }
+    rwlock->nsh_count -= rwlock->ncomplete;
+    rwlock->ncomplete = 0;
+    ret = rwlock_free_both_locks(rwlock, 0);
+    return rwl_unref(rwlock_, ret);
+  }
+  ret = pthread_mutex_unlock(&rwlock->mex);
+  return rwl_unref(rwlock_, ret);
+}
+
+int pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock_, const struct timespec *ts)
+{
+  rwlock_t *rwlock;
+  int ret;
+
+  /* pthread_testcancel(); */
+
+  ret = rwl_ref(rwlock_,0);
+  if(ret != 0) return ret;
+
+  rwlock = (rwlock_t *)*rwlock_;
+  if ((ret = pthread_mutex_timedlock (&rwlock->mex, ts)) != 0)
+      return rwl_unref(rwlock_, ret);
+  InterlockedIncrement(&rwlock->nsh_count);
+  if (rwlock->nsh_count == INT_MAX)
+  {
+    ret = pthread_mutex_timedlock(&rwlock->mcomplete, ts);
+    if (ret != 0)
+    {
+      if (ret == ETIMEDOUT)
+	InterlockedIncrement(&rwlock->ncomplete);
+      pthread_mutex_unlock(&rwlock->mex);
+      return rwl_unref(rwlock_, ret);
+    }
+    rwlock->nsh_count -= rwlock->ncomplete;
+    rwlock->ncomplete = 0;
+    ret = rwlock_free_both_locks(rwlock, 0);
+    return rwl_unref(rwlock_, ret);
+  }
+  ret = pthread_mutex_unlock(&rwlock->mex);
+  return rwl_unref(rwlock_, ret);
+}
+
+int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock_)
+{
+  rwlock_t *rwlock;
+  int ret;
+
+  ret = rwl_ref(rwlock_,RWL_TRY);
+  if(ret != 0) return ret;
+
+  rwlock = (rwlock_t *)*rwlock_;
+  ret = pthread_mutex_trylock(&rwlock->mex);
+  if (ret != 0)
+      return rwl_unref(rwlock_, ret);
+  InterlockedIncrement(&rwlock->nsh_count);
+  if (rwlock->nsh_count == INT_MAX)
+  {
+    ret = pthread_mutex_lock(&rwlock->mcomplete);
+    if (ret != 0)
+    {
+      pthread_mutex_unlock(&rwlock->mex);
+      return rwl_unref(rwlock_, ret);
+    }
+    rwlock->nsh_count -= rwlock->ncomplete;
+    rwlock->ncomplete = 0;
+    ret = rwlock_free_both_locks(rwlock, 0);
+    return rwl_unref(rwlock_, ret);
+  }
+  ret = pthread_mutex_unlock(&rwlock->mex);
+  return rwl_unref(rwlock_,ret);
+} 
+
+int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock_)
+{
+  rwlock_t *rwlock;
+  int ret;
+
+  ret = rwl_ref(rwlock_,RWL_TRY);
+  if(ret != 0) return ret;
+
+  rwlock = (rwlock_t *)*rwlock_;
+  ret = pthread_mutex_trylock (&rwlock->mex);
+  if (ret != 0)
+    return rwl_unref(rwlock_, ret);
+  ret = pthread_mutex_trylock(&rwlock->mcomplete);
+  if (ret != 0)
+  {
+    int r1 = pthread_mutex_unlock(&rwlock->mex);
+    if (r1 != 0)
+      ret = r1;
+    return rwl_unref(rwlock_, ret);
+  }
+  if (rwlock->nex_count != 0)
+    return rwl_unref(rwlock_, EBUSY);
+  if (rwlock->ncomplete > 0)
+  {
+    rwlock->nsh_count -= rwlock->ncomplete;
+    rwlock->ncomplete = 0;
+  }
+  if (rwlock->nsh_count > 0)
+  {
+    ret = rwlock_free_both_locks(rwlock, 0);
+    if (!ret)
+      ret = EBUSY;
+    return rwl_unref(rwlock_, ret);
+  }
+  rwlock->nex_count = 1;
+  return rwl_unref(rwlock_, 0);
+} 
+
+int pthread_rwlock_unlock (pthread_rwlock_t *rwlock_)
+{
+  rwlock_t *rwlock;
+  int ret;
+
+  ret = rwl_ref_unlock(rwlock_);
+  if(ret != 0) return ret;
+
+  rwlock = (rwlock_t *)*rwlock_;
+  if (rwlock->nex_count == 0)
+  {
+    ret = pthread_mutex_lock(&rwlock->mcomplete);
+    if (!ret)
+    {
+      int r1;
+      InterlockedIncrement(&rwlock->ncomplete);
+      if (rwlock->ncomplete == 0)
+	ret = pthread_cond_signal(&rwlock->ccomplete);
+      r1 = pthread_mutex_unlock(&rwlock->mcomplete);
+      if (!ret)
+	ret = r1;
+    }
+  }
+  else
+  {
+    InterlockedDecrement(&rwlock->nex_count);
+    ret = rwlock_free_both_locks(rwlock, 0);
+  }
+  return rwl_unref(rwlock_, ret);
+} 
+
+static void st_cancelwrite (void *arg)
+{
+    rwlock_t *rwlock = (rwlock_t *)arg;
+
+    rwlock->nsh_count = - rwlock->ncomplete;
+    rwlock->ncomplete = 0;
+    rwlock_free_both_locks(rwlock, 0);
+}
+
+int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock_)
+{
+  rwlock_t *rwlock;
+  int ret;
+
+  /* pthread_testcancel(); */
+  ret = rwl_ref(rwlock_,0);
+  if(ret != 0) return ret;
+
+  rwlock = (rwlock_t *)*rwlock_;
+  ret = rwlock_gain_both_locks(rwlock);
+  if (ret != 0)
+    return rwl_unref(rwlock_,ret);
+
+  if (rwlock->nex_count == 0)
+  {
+    if (rwlock->ncomplete > 0)
+    {
+      rwlock->nsh_count -= rwlock->ncomplete;
+      rwlock->ncomplete = 0;
+    }
+    if (rwlock->nsh_count > 0)
+    {
+      rwlock->ncomplete = -rwlock->nsh_count;
+      pthread_cleanup_push(st_cancelwrite, (void *) rwlock);
+      do {
+	ret = pthread_cond_wait(&rwlock->ccomplete, &rwlock->mcomplete);
+      } while (!ret && rwlock->ncomplete < 0);
+
+      pthread_cleanup_pop(!ret ? 0 : 1);
+      if (!ret)
+	rwlock->nsh_count = 0;
+    }
+  }
+  if(!ret)
+    InterlockedIncrement((long*)&rwlock->nex_count);
+  return rwl_unref(rwlock_,ret);
+}
+
+int pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock_, const struct timespec *ts)
+{
+  int ret;
+  rwlock_t *rwlock;
+
+  /* pthread_testcancel(); */
+  if (!rwlock_ || !ts)
+    return EINVAL;
+  if ((ret = rwl_ref(rwlock_,0)) != 0)
+    return ret;
+  rwlock = (rwlock_t *)*rwlock_;
+
+  ret = pthread_mutex_timedlock(&rwlock->mex, ts);
+  if (ret != 0)
+    return rwl_unref(rwlock_,ret);
+  ret = pthread_mutex_timedlock (&rwlock->mcomplete, ts);
+  if (ret != 0)
+  {
+    pthread_mutex_unlock(&rwlock->mex);
+    return rwl_unref(rwlock_,ret);
+  }
+  if (rwlock->nex_count == 0)
+  {
+    if (rwlock->ncomplete > 0)
+    {
+      rwlock->nsh_count -= rwlock->ncomplete;
+      rwlock->ncomplete = 0;
+    }
+    if (rwlock->nsh_count > 0)
+    {
+      rwlock->ncomplete = -rwlock->nsh_count;
+      pthread_cleanup_push(st_cancelwrite, (void *) rwlock);
+      do {
+	ret = pthread_cond_timedwait(&rwlock->ccomplete, &rwlock->mcomplete, ts);
+      } while (rwlock->ncomplete < 0 && !ret);
+      pthread_cleanup_pop(!ret ? 0 : 1);
+
+      if (!ret)
+	rwlock->nsh_count = 0;
+    }
+  }
+  if(!ret)
+    InterlockedIncrement((long*)&rwlock->nex_count);
+  return rwl_unref(rwlock_,ret);
+}
+
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a)
+{
+  if (!a)
+    return EINVAL;
+  return 0;
+}
+
+int pthread_rwlockattr_init(pthread_rwlockattr_t *a)
+{
+  if (!a)
+    return EINVAL;
+  *a = PTHREAD_PROCESS_PRIVATE;
+  return 0;
+}
+
+int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s)
+{
+  if (!a || !s)
+    return EINVAL;
+  *s = *a;
+  return 0;
+}
+
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s)
+{
+  if (!a || (s != PTHREAD_PROCESS_SHARED && s != PTHREAD_PROCESS_PRIVATE))
+    return EINVAL;
+  *a = s;
+  return 0;
+}
diff --git a/libs/winpthreads/src/rwlock.h b/libs/winpthreads/src/rwlock.h
new file mode 100644
index 00000000000..f08b0d37bef
--- /dev/null
+++ b/libs/winpthreads/src/rwlock.h
@@ -0,0 +1,52 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREADS_RWLOCK_H
+#define WIN_PTHREADS_RWLOCK_H
+
+#define LIFE_RWLOCK 0xBAB1F0ED
+#define DEAD_RWLOCK 0xDEADB0EF
+
+#define INIT_RWLOCK(rwl)  { int r; \
+    if (STATIC_RWL_INITIALIZER(*rwl)) { if ((r = rwlock_static_init(rwl))) { if (r != EBUSY) return r; }}}
+
+#define STATIC_RWL_INITIALIZER(x)		((pthread_rwlock_t)(x) == ((pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER))
+
+typedef struct rwlock_t rwlock_t;
+struct rwlock_t {
+    unsigned int valid;
+    int busy;
+    LONG nex_count; /* Exclusive access counter.  */
+    LONG nsh_count; /* Shared access counter. */
+    LONG ncomplete; /* Shared completed counter. */
+    pthread_mutex_t mex; /* Exclusive access protection.  */
+    pthread_mutex_t mcomplete; /* Shared completed protection. */
+    pthread_cond_t ccomplete; /* Shared access completed queue.  */
+};
+
+#define RWL_SET	0x01
+#define RWL_TRY	0x02
+
+void rwl_print(volatile pthread_rwlock_t *rwl, char *txt);
+void rwl_print_set(int state);
+
+#endif
diff --git a/libs/winpthreads/src/sched.c b/libs/winpthreads/src/sched.c
new file mode 100644
index 00000000000..976bcc10521
--- /dev/null
+++ b/libs/winpthreads/src/sched.c
@@ -0,0 +1,218 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+#include "pthread.h"
+#include "thread.h"
+
+#include "misc.h"
+
+int sched_get_priority_min(int pol)
+{
+  if (pol < SCHED_MIN || pol > SCHED_MAX) {
+      errno = EINVAL;
+      return -1;
+  }
+
+  return THREAD_PRIORITY_IDLE;
+}
+
+int sched_get_priority_max(int pol)
+{
+  if (pol < SCHED_MIN || pol > SCHED_MAX) {
+      errno = EINVAL;
+      return -1;
+  }
+
+  return THREAD_PRIORITY_TIME_CRITICAL;
+}
+
+int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *p)
+{
+    int r = 0;
+
+    if (attr == NULL || p == NULL) {
+        return EINVAL;
+    }
+    memcpy(&attr->param, p, sizeof (*p));
+    return r;
+}
+
+int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *p)
+{
+    int r = 0;
+
+    if (attr == NULL || p == NULL) {
+        return EINVAL;
+    }
+    memcpy(p, &attr->param, sizeof (*p));
+    return r;
+}
+
+int pthread_attr_setschedpolicy (pthread_attr_t *attr, int pol)
+{
+  if (!attr || pol < SCHED_MIN || pol > SCHED_MAX)
+    return EINVAL;
+  if (pol != SCHED_OTHER)
+    return ENOTSUP;
+  return 0;
+}
+
+int pthread_attr_getschedpolicy (const pthread_attr_t *attr, int *pol)
+{
+  if (!attr || !pol)
+    return EINVAL;
+  *pol = SCHED_OTHER;
+  return 0;
+}
+
+static int pthread_check(pthread_t t)
+{
+  struct _pthread_v *pv;
+
+  if (!t)
+    return ESRCH;
+  pv = __pth_gpointer_locked (t);
+  if (pv->ended == 0)
+    return 0;
+  CHECK_OBJECT(pv, ESRCH);
+  return 0;
+}
+
+int pthread_getschedparam(pthread_t t, int *pol, struct sched_param *p)
+{
+    int r;
+    //if (!t)
+    //  t = pthread_self();
+
+    if ((r = pthread_check(t)) != 0)
+    {
+        return r;
+    }
+
+    if (!p || !pol)
+    {
+        return EINVAL;
+    }
+    *pol = __pth_gpointer_locked (t)->sched_pol;
+    p->sched_priority = __pth_gpointer_locked (t)->sched.sched_priority;
+
+    return 0;
+}
+
+int pthread_setschedparam(pthread_t t, int pol,  const struct sched_param *p)
+{
+  struct _pthread_v *pv;
+    int r, pr = 0;
+    //if (!t.p) t = pthread_self();
+
+    if ((r = pthread_check(t)) != 0)
+        return r;
+
+    if (pol < SCHED_MIN || pol > SCHED_MAX || p == NULL)
+        return EINVAL;
+    if (pol != SCHED_OTHER)
+        return ENOTSUP;
+    pr = p->sched_priority;
+    if (pr < sched_get_priority_min(pol) || pr > sched_get_priority_max(pol))
+      return EINVAL;
+
+    /* See msdn: there are actually 7 priorities:
+    THREAD_PRIORITY_IDLE    -      -15
+    THREAD_PRIORITY_LOWEST          -2
+    THREAD_PRIORITY_BELOW_NORMAL    -1
+    THREAD_PRIORITY_NORMAL           0
+    THREAD_PRIORITY_ABOVE_NORMAL     1
+    THREAD_PRIORITY_HIGHEST          2
+    THREAD_PRIORITY_TIME_CRITICAL   15
+    */
+    if (pr <= THREAD_PRIORITY_IDLE) {
+        pr = THREAD_PRIORITY_IDLE;
+    } else if (pr <= THREAD_PRIORITY_LOWEST) {
+        pr = THREAD_PRIORITY_LOWEST;
+    } else if (pr >= THREAD_PRIORITY_TIME_CRITICAL) {
+        pr = THREAD_PRIORITY_TIME_CRITICAL;
+    } else if (pr >= THREAD_PRIORITY_HIGHEST) {
+        pr = THREAD_PRIORITY_HIGHEST;
+    }
+    pv = __pth_gpointer_locked (t);
+    if (SetThreadPriority(pv->h, pr)) {
+        pv->sched_pol = pol;
+        pv->sched.sched_priority = p->sched_priority;
+    } else
+        r = EINVAL;
+    return r;
+}
+
+int sched_getscheduler(pid_t pid)
+{
+  if (pid != 0)
+  {
+      HANDLE h = NULL;
+      int selfPid = (int) GetCurrentProcessId ();
+
+      if (pid != (pid_t) selfPid && (h = OpenProcess (PROCESS_QUERY_INFORMATION, 0, (DWORD) pid)) == NULL)
+      {
+	  errno = (GetLastError () == (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+	  return -1;
+      }
+      if (h)
+	  CloseHandle (h);
+  }
+  return SCHED_OTHER;
+}
+
+int sched_setscheduler(pid_t pid, int pol, const struct sched_param *param)
+{
+  if (!param)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (pid != 0)
+  {
+      HANDLE h = NULL;
+      int selfPid = (int) GetCurrentProcessId ();
+
+      if (pid != (pid_t) selfPid && (h = OpenProcess (PROCESS_SET_INFORMATION, 0, (DWORD) pid)) == NULL)
+      {
+	  errno = (GetLastError () == (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH;
+	  return -1;
+      }
+      if (h)
+          CloseHandle (h);
+  }
+
+  if (pol != SCHED_OTHER)
+  {
+      errno = ENOSYS;
+      return -1;
+  }
+  return SCHED_OTHER;
+}
+
+int sched_yield(void)
+{
+  Sleep(0);
+  return 0;
+}
diff --git a/libs/winpthreads/src/sem.c b/libs/winpthreads/src/sem.c
new file mode 100644
index 00000000000..81fa8f8e636
--- /dev/null
+++ b/libs/winpthreads/src/sem.c
@@ -0,0 +1,354 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "pthread.h"
+#include "thread.h"
+#include "misc.h"
+#include "semaphore.h"
+#include "sem.h"
+#include "ref.h"
+
+int do_sema_b_wait_intern (HANDLE sema, int nointerrupt, DWORD timeout);
+
+static int
+sem_result (int res)
+{
+  if (res != 0) {
+    errno = res;
+    return -1;
+  }
+  return 0;
+}
+
+int
+sem_init (sem_t *sem, int pshared, unsigned int value)
+{
+  _sem_t *sv;
+
+  if (!sem || value > (unsigned int)SEM_VALUE_MAX)
+    return sem_result (EINVAL);
+  if (pshared != PTHREAD_PROCESS_PRIVATE)
+    return sem_result (EPERM);
+
+  if (!(sv = (sem_t) calloc (1,sizeof (*sv))))
+    return sem_result (ENOMEM);
+
+  sv->value = value;
+  if (pthread_mutex_init (&sv->vlock, NULL) != 0)
+    {
+      free (sv);
+      return sem_result (ENOSPC);
+    }
+  if ((sv->s = CreateSemaphore (NULL, 0, SEM_VALUE_MAX, NULL)) == NULL)
+    {
+      pthread_mutex_destroy (&sv->vlock);
+      free (sv);
+      return sem_result (ENOSPC);
+    }
+
+  sv->valid = LIFE_SEM;
+  *sem = sv;
+  return 0;
+}
+
+int
+sem_destroy (sem_t *sem)
+{
+  int r;
+  _sem_t *sv = NULL;
+
+  if (!sem || (sv = *sem) == NULL)
+    return sem_result (EINVAL);
+  if ((r = pthread_mutex_lock (&sv->vlock)) != 0)
+    return sem_result (r);
+
+#if 0
+  /* We don't wait for destroying a semaphore ...
+     or?  */
+  if (sv->value < 0)
+    {
+      pthread_mutex_unlock (&sv->vlock);
+      return sem_result (EBUSY);
+    }
+#endif
+
+  if (!CloseHandle (sv->s))
+    {
+      pthread_mutex_unlock (&sv->vlock);
+      return sem_result (EINVAL);
+    }
+  *sem = NULL;
+  sv->value = SEM_VALUE_MAX;
+  pthread_mutex_unlock(&sv->vlock);
+  Sleep (0);
+  while (pthread_mutex_destroy (&sv->vlock) == EBUSY)
+    Sleep (0);
+  sv->valid = DEAD_SEM;
+  free (sv);
+  return 0;
+}
+
+static int
+sem_std_enter (sem_t *sem,_sem_t **svp, int do_test)
+{
+  int r;
+  _sem_t *sv;
+
+  if (do_test)
+    pthread_testcancel ();
+  if (!sem)
+    return sem_result (EINVAL);
+  sv = *sem;
+  if (sv == NULL)
+    return sem_result (EINVAL);
+
+  if ((r = pthread_mutex_lock (&sv->vlock)) != 0)
+    return sem_result (r);
+
+  if (*sem == NULL)
+    {
+      pthread_mutex_unlock(&sv->vlock);
+      return sem_result (EINVAL);
+    }
+  *svp = sv;
+  return 0;
+}
+
+int
+sem_trywait (sem_t *sem)
+{
+  _sem_t *sv;
+
+  if (sem_std_enter (sem, &sv, 0) != 0)
+    return -1;
+  if (sv->value <= 0)
+    {
+      pthread_mutex_unlock (&sv->vlock);
+      return sem_result (EAGAIN);
+    }
+  sv->value--;
+  pthread_mutex_unlock (&sv->vlock);
+
+  return 0;
+}
+
+struct sSemTimedWait
+{
+  sem_t *p;
+  int *ret;
+};
+
+static void
+clean_wait_sem (void *s)
+{
+  struct sSemTimedWait *p = (struct sSemTimedWait *) s;
+  _sem_t *sv = NULL;
+
+  if (sem_std_enter (p->p, &sv, 0) != 0)
+    return;
+
+  if (WaitForSingleObject (sv->s, 0) != WAIT_OBJECT_0)
+    InterlockedIncrement (&sv->value);
+  else if (p->ret)
+    p->ret[0] = 0;
+  pthread_mutex_unlock (&sv->vlock);
+}
+
+int
+sem_wait (sem_t *sem)
+{
+  long cur_v;
+  int ret = 0;
+  _sem_t *sv;
+  HANDLE semh;
+  struct sSemTimedWait arg;
+
+  if (sem_std_enter (sem, &sv, 1) != 0)
+    return -1;
+
+  arg.ret = &ret;
+  arg.p = sem;
+  InterlockedDecrement (&sv->value);
+  cur_v = sv->value;
+  semh = sv->s;
+  pthread_mutex_unlock (&sv->vlock);
+
+  if (cur_v >= 0)
+    return 0;
+  else
+    {
+      pthread_cleanup_push (clean_wait_sem, (void *) &arg);
+      ret = do_sema_b_wait_intern (semh, 2, INFINITE);
+      pthread_cleanup_pop (ret);
+      if (ret == EINVAL)
+        return 0;
+    }
+
+  if (!ret)
+    return 0;
+
+  return sem_result (ret);
+}
+
+int
+sem_timedwait (sem_t *sem, const struct timespec *t)
+{
+  int cur_v, ret = 0;
+  DWORD dwr;
+  HANDLE semh;
+  _sem_t *sv;
+  struct sSemTimedWait arg;
+
+  if (!t)
+    return sem_wait (sem);
+  dwr = dwMilliSecs(_pthread_rel_time_in_ms (t));
+
+  if (sem_std_enter (sem, &sv, 1) != 0)
+    return -1;
+
+  arg.ret = &ret;
+  arg.p = sem;
+  InterlockedDecrement (&sv->value);
+  cur_v = sv->value;
+  semh = sv->s;
+  pthread_mutex_unlock(&sv->vlock);
+
+  if (cur_v >= 0)
+    return 0;
+  else
+    {
+      pthread_cleanup_push (clean_wait_sem, (void *) &arg);
+      ret = do_sema_b_wait_intern (semh, 2, dwr);
+      pthread_cleanup_pop (ret);
+      if (ret == EINVAL)
+        return 0;
+    }
+
+  if (!ret)
+    return 0;
+  return sem_result (ret);
+}
+
+int
+sem_post (sem_t *sem)
+{
+  _sem_t *sv;;
+
+  if (sem_std_enter (sem, &sv, 0) != 0)
+    return -1;
+
+  if (sv->value >= SEM_VALUE_MAX)
+    {
+      pthread_mutex_unlock (&sv->vlock);
+      return sem_result (ERANGE);
+    }
+  InterlockedIncrement (&sv->value);
+  if (sv->value > 0 || ReleaseSemaphore (sv->s, 1, NULL))
+    {
+      pthread_mutex_unlock (&sv->vlock);
+      return 0;
+    }
+  InterlockedDecrement (&sv->value);
+  pthread_mutex_unlock (&sv->vlock);
+
+  return sem_result (EINVAL);
+}
+
+int
+sem_post_multiple (sem_t *sem, int count)
+{
+  int waiters_count;
+  _sem_t *sv;;
+
+  if (count <= 0)
+    return sem_result (EINVAL);
+  if (sem_std_enter (sem, &sv, 0) != 0)
+    return -1;
+
+  if (sv->value > (SEM_VALUE_MAX - count))
+  {
+    pthread_mutex_unlock (&sv->vlock);
+    return sem_result (ERANGE);
+  }
+  waiters_count = -sv->value;
+  sv->value += count;
+  /*InterlockedExchangeAdd((long*)&sv->value, (long) count);*/
+  if (waiters_count <= 0
+      || ReleaseSemaphore (sv->s,
+			   (waiters_count < count ? waiters_count
+			   			  : count), NULL))
+  {
+    pthread_mutex_unlock(&sv->vlock);
+    return 0;
+  }
+  /*InterlockedExchangeAdd((long*)&sv->value, -((long) count));*/
+  sv->value -= count;
+  pthread_mutex_unlock(&sv->vlock);
+  return sem_result (EINVAL);
+}
+
+sem_t *
+sem_open (const char *name, int oflag, mode_t mode, unsigned int value)
+{
+  sem_result (ENOSYS);
+  return NULL;
+}
+
+int
+sem_close (sem_t *sem)
+{
+  return sem_result (ENOSYS);
+}
+
+int
+sem_unlink (const char *name)
+{
+  return sem_result (ENOSYS);
+}
+
+int
+sem_getvalue (sem_t *sem, int *sval)
+{
+  _sem_t *sv;
+  int r;
+
+  if (!sval)
+    return sem_result (EINVAL);
+
+  if (!sem || (sv = *sem) == NULL)
+    return sem_result (EINVAL);
+
+  if ((r = pthread_mutex_lock (&sv->vlock)) != 0)
+    return sem_result (r);
+  if (*sem == NULL)
+    {
+      pthread_mutex_unlock (&sv->vlock);
+      return sem_result (EINVAL);
+    }
+
+  *sval = (int) sv->value;
+  pthread_mutex_unlock (&sv->vlock);
+  return 0;  
+}
diff --git a/libs/winpthreads/src/sem.h b/libs/winpthreads/src/sem.h
new file mode 100644
index 00000000000..3b3ace7f73e
--- /dev/null
+++ b/libs/winpthreads/src/sem.h
@@ -0,0 +1,40 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_SEM
+#define WIN_SEM
+
+#include <windows.h>
+
+#define LIFE_SEM 0xBAB1F00D
+#define DEAD_SEM 0xDEADBEEF
+
+typedef struct _sem_t _sem_t;
+struct _sem_t
+{
+    unsigned int valid;
+    HANDLE s;
+    volatile long value;
+    pthread_mutex_t vlock;
+};
+
+#endif /* WIN_SEM */
diff --git a/libs/winpthreads/src/spinlock.c b/libs/winpthreads/src/spinlock.c
new file mode 100644
index 00000000000..2032d602a28
--- /dev/null
+++ b/libs/winpthreads/src/spinlock.c
@@ -0,0 +1,81 @@
+/*
+   Copyright (c) 2013 mingw-w64 project
+   Copyright (c) 2015 Intel Corporation
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include "pthread.h"
+
+#define likely(cond) __builtin_expect((cond) != 0, 1)
+#define unlikely(cond) __builtin_expect((cond) != 0, 0)
+
+/* We use the pthread_spinlock_t itself as a lock:
+   -1 is free, 0 is locked.
+   (This is dictated by PTHREAD_SPINLOCK_INITIALIZER, which we can't change
+   without breaking binary compatibility.) */
+typedef intptr_t spinlock_word_t;
+
+int
+pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+  spinlock_word_t *lk = (spinlock_word_t *)lock;
+  *lk = -1;
+  return 0;
+}
+
+
+int
+pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+  return 0;
+}
+
+int
+pthread_spin_lock (pthread_spinlock_t *lock)
+{
+  volatile spinlock_word_t *lk = (volatile spinlock_word_t *)lock;
+  while (unlikely(__sync_lock_test_and_set(lk, 0) == 0))
+    do {
+#if defined(__i386__) || defined(__x86_64__)
+      asm("pause" ::: "memory");
+#elif defined(__arm__) || defined(__aarch64__)
+      asm("wfe" ::: "memory");
+#else
+#error Unsupported architecture
+#endif
+    } while (*lk == 0);
+  return 0;
+}
+  
+int
+pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+  spinlock_word_t *lk = (spinlock_word_t *)lock;
+  return __sync_lock_test_and_set(lk, 0) == 0 ? EBUSY : 0;
+}
+
+
+int
+pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+  volatile spinlock_word_t *lk = (volatile spinlock_word_t *)lock;
+  *lk = -1;
+  return 0;
+}
diff --git a/libs/winpthreads/src/thread.c b/libs/winpthreads/src/thread.c
new file mode 100644
index 00000000000..a9f286ba3a5
--- /dev/null
+++ b/libs/winpthreads/src/thread.c
@@ -0,0 +1,1865 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <windows.h>
+#include <strsafe.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <signal.h>
+#include "pthread.h"
+#include "thread.h"
+#include "misc.h"
+#include "winpthread_internal.h"
+
+static _pthread_v *__pthread_self_lite (void);
+
+void (**_pthread_key_dest)(void *) = NULL;
+
+static volatile long _pthread_cancelling;
+static int _pthread_concur;
+
+/* FIXME Will default to zero as needed */
+static pthread_once_t _pthread_tls_once;
+static DWORD _pthread_tls = 0xffffffff;
+
+static pthread_rwlock_t _pthread_key_lock = PTHREAD_RWLOCK_INITIALIZER;
+static unsigned long _pthread_key_max=0L;
+static unsigned long _pthread_key_sch=0L;
+
+static _pthread_v *pthr_root = NULL, *pthr_last = NULL;
+static pthread_mutex_t mtx_pthr_locked = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+
+static __pthread_idlist *idList = NULL;
+static size_t idListCnt = 0;
+static size_t idListMax = 0;
+static pthread_t idListNextId = 0;
+
+#if !defined(_MSC_VER)
+#define USE_VEH_FOR_MSC_SETTHREADNAME
+#endif
+#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+/* forbidden RemoveVectoredExceptionHandler/AddVectoredExceptionHandler APIs */
+#undef USE_VEH_FOR_MSC_SETTHREADNAME
+#endif
+
+#if defined(USE_VEH_FOR_MSC_SETTHREADNAME)
+static void *SetThreadName_VEH_handle = NULL;
+
+static LONG __stdcall
+SetThreadName_VEH (PEXCEPTION_POINTERS ExceptionInfo)
+{
+  if (ExceptionInfo->ExceptionRecord != NULL &&
+      ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SET_THREAD_NAME)
+    return EXCEPTION_CONTINUE_EXECUTION;
+
+  return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
+typedef struct _THREADNAME_INFO
+{
+  DWORD  dwType;	/* must be 0x1000 */
+  LPCSTR szName;	/* pointer to name (in user addr space) */
+  DWORD  dwThreadID;	/* thread ID (-1=caller thread) */
+  DWORD  dwFlags;	/* reserved for future use, must be zero */
+} THREADNAME_INFO;
+
+static void
+SetThreadName (DWORD dwThreadID, LPCSTR szThreadName)
+{
+   THREADNAME_INFO info;
+   DWORD infosize;
+
+   info.dwType = 0x1000;
+   info.szName = szThreadName;
+   info.dwThreadID = dwThreadID;
+   info.dwFlags = 0;
+
+   infosize = sizeof (info) / sizeof (ULONG_PTR);
+
+#if defined(_MSC_VER) && !defined (USE_VEH_FOR_MSC_SETTHREADNAME)
+   __try
+     {
+       RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (ULONG_PTR *)&info);
+     }
+   __except (EXCEPTION_EXECUTE_HANDLER)
+     {
+     }
+#else
+   /* Without a debugger we *must* have an exception handler,
+    * otherwise raising an exception will crash the process.
+    */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+   if ((!IsDebuggerPresent ()) && (SetThreadName_VEH_handle == NULL))
+#else
+   if (!IsDebuggerPresent ())
+#endif
+     return;
+
+   RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (ULONG_PTR *) &info);
+#endif
+}
+
+/* Search the list idList for an element with identifier ID.  If
+   found, its associated _pthread_v pointer is returned, otherwise
+   NULL.
+   NOTE: This method is not locked.  */
+static struct _pthread_v *
+__pthread_get_pointer (pthread_t id)
+{
+  size_t l, r, p;
+  if (!idListCnt)
+    return NULL;
+  if (idListCnt == 1)
+    return (idList[0].id == id ? idList[0].ptr : NULL);
+  l = 0; r = idListCnt - 1;
+  while (l <= r)
+  {
+    p = (l + r) >> 1;
+    if (idList[p].id == id)
+      return idList[p].ptr;
+    else if (idList[p].id > id)
+      {
+	if (p == l)
+	  return NULL;
+	r = p - 1;
+      }
+    else
+      {
+	l = p + 1;
+      }
+  }
+
+  return NULL;
+}
+
+static void
+__pth_remove_use_for_key (pthread_key_t key)
+{
+  int i;
+
+  pthread_mutex_lock (&mtx_pthr_locked);
+  for (i = 0; i < idListCnt; i++)
+    {
+      if (idList[i].ptr != NULL
+          && idList[i].ptr->keyval != NULL
+          && key < idList[i].ptr->keymax)
+        {
+	  idList[i].ptr->keyval[key] = NULL;
+	  idList[i].ptr->keyval_set[key] = 0;
+	}
+    }
+  pthread_mutex_unlock (&mtx_pthr_locked);
+}
+
+/* Search the list idList for an element with identifier ID.  If
+   found, its associated _pthread_v pointer is returned, otherwise
+   NULL.
+   NOTE: This method uses lock mtx_pthr_locked.  */
+struct _pthread_v *
+__pth_gpointer_locked (pthread_t id)
+{
+  struct _pthread_v *ret;
+  if (!id)
+    return NULL;
+  pthread_mutex_lock (&mtx_pthr_locked);
+  ret =  __pthread_get_pointer (id);
+  pthread_mutex_unlock (&mtx_pthr_locked);
+  return ret;
+}
+
+/* Registers in the list idList an element with _pthread_v pointer
+   and creates and unique identifier ID.  If successful created the
+   ID of this element is returned, otherwise on failure zero ID gets
+   returned.
+   NOTE: This method is not locked.  */
+static pthread_t
+__pthread_register_pointer (struct _pthread_v *ptr)
+{
+  __pthread_idlist *e;
+  size_t i;
+
+  if (!ptr)
+    return 0;
+  /* Check if a resize of list is necessary.  */
+  if (idListCnt >= idListMax)
+    {
+      if (!idListCnt)
+        {
+	  e = (__pthread_idlist *) malloc (sizeof (__pthread_idlist) * 16);
+	  if (!e)
+	    return 0;
+	  idListMax = 16;
+	  idList = e;
+	}
+      else
+        {
+	  e = (__pthread_idlist *) realloc (idList, sizeof (__pthread_idlist) * (idListMax + 16));
+	  if (!e)
+	    return 0;
+	  idListMax += 16;
+	  idList = e;
+	}
+    }
+  do
+    {
+      ++idListNextId;
+      /* If two MSB are set we reset to id 1.  We need to check here bits
+         to avoid gcc's no-overflow issue on increment.  Additionally we
+         need to handle different size of pthread_t on 32-bit/64-bit.  */
+      if ((idListNextId & ( ((pthread_t) 1) << ((sizeof (pthread_t) * 8) - 2))) != 0)
+        idListNextId = 1;
+    }
+  while (idListNextId == 0 || __pthread_get_pointer (idListNextId));
+  /* We assume insert at end of list.  */
+  i = idListCnt;
+  if (i != 0)
+    {
+      /* Find position we can actual insert sorted.  */
+      while (i > 0 && idList[i - 1].id > idListNextId)
+        --i;
+      if (i != idListCnt)
+	memmove (&idList[i + 1], &idList[i], sizeof (__pthread_idlist) * (idListCnt - i));
+    }
+  idList[i].id = idListNextId;
+  idList[i].ptr = ptr;
+  ++idListCnt;
+  return idListNextId;
+}
+
+/* Deregisters in the list idList an element with identifier ID and
+   returns its _pthread_v pointer on success.  Otherwise NULL is returned.
+   NOTE: This method is not locked.  */
+static struct _pthread_v *
+__pthread_deregister_pointer (pthread_t id)
+{
+  size_t l, r, p;
+  if (!idListCnt)
+    return NULL;
+  l = 0; r = idListCnt - 1;
+  while (l <= r)
+  {
+    p = (l + r) >> 1;
+    if (idList[p].id == id)
+      {
+	struct _pthread_v *ret = idList[p].ptr;
+	p++;
+	if (p < idListCnt)
+	  memmove (&idList[p - 1], &idList[p], sizeof (__pthread_idlist) * (idListCnt - p));
+	--idListCnt;
+	/* Is this last element in list then free list.  */
+	if (idListCnt == 0)
+	{
+	  free (idList);
+	  idListCnt = idListMax = 0;
+	}
+	return ret;
+      }
+    else if (idList[p].id > id)
+      {
+	if (p == l)
+	  return NULL;
+	r = p - 1;
+      }
+    else
+      {
+	l = p + 1;
+      }
+  }
+  return NULL;
+}
+
+/* Save a _pthread_v element for reuse in pool.  */
+static void
+push_pthread_mem (_pthread_v *sv)
+{
+  if (!sv || sv->next != NULL)
+    return;
+  pthread_mutex_lock (&mtx_pthr_locked);
+  if (sv->x != 0)
+    __pthread_deregister_pointer (sv->x);
+  if (sv->keyval)
+    free (sv->keyval);
+  if (sv->keyval_set)
+    free (sv->keyval_set);
+  if (sv->thread_name)
+    free (sv->thread_name);
+  memset (sv, 0, sizeof(struct _pthread_v));
+  if (pthr_last == NULL)
+    pthr_root = pthr_last = sv;
+  else
+  {
+    pthr_last->next = sv;
+    pthr_last = sv;
+  }
+  pthread_mutex_unlock (&mtx_pthr_locked);
+}
+
+/* Get a _pthread_v element from pool, or allocate it.
+   Note the unique identifier is created for the element here, too.  */
+static _pthread_v *
+pop_pthread_mem (void)
+{
+  _pthread_v *r = NULL;
+
+  pthread_mutex_lock (&mtx_pthr_locked);
+  if ((r = pthr_root) == NULL)
+    {
+      if ((r = (_pthread_v *)calloc (1,sizeof(struct _pthread_v))) != NULL)
+	{
+	  r->x = __pthread_register_pointer (r);
+	  if (r->x == 0)
+	    {
+	      free (r);
+	      r = NULL;
+	    }
+	}
+      pthread_mutex_unlock (&mtx_pthr_locked);
+      return r;
+    }
+  r->x = __pthread_register_pointer (r);
+  if (r->x == 0)
+    r = NULL;
+  else
+    {
+      if((pthr_root = r->next) == NULL)
+	pthr_last = NULL;
+
+      r->next = NULL;
+    }
+  pthread_mutex_unlock (&mtx_pthr_locked);
+  return r;
+}
+
+/* Free memory consumed in _pthread_v pointer pool.  */
+static void
+free_pthread_mem (void)
+{
+  _pthread_v *t;
+
+  if (1)
+  return;  
+  pthread_mutex_lock (&mtx_pthr_locked);
+  t = pthr_root;
+  while (t != NULL)
+  {
+    _pthread_v *sv = t;
+    t = t->next;
+    if (sv->x != 0 && sv->ended == 0 && sv->valid != DEAD_THREAD)
+      {
+	pthread_mutex_unlock (&mtx_pthr_locked);
+	pthread_cancel (t->x);
+	Sleep (0);
+	pthread_mutex_lock (&mtx_pthr_locked);
+	t = pthr_root;
+	continue;
+      }
+    else if (sv->x != 0 && sv->valid != DEAD_THREAD)
+      {
+	pthread_mutex_unlock (&mtx_pthr_locked);
+	Sleep (0);
+	pthread_mutex_lock (&mtx_pthr_locked);
+	continue;
+      }
+    if (sv->x != 0)
+      __pthread_deregister_pointer (sv->x);
+    sv->x = 0;
+    free (sv);
+    pthr_root = t;
+  }
+  pthread_mutex_unlock (&mtx_pthr_locked);
+}
+
+static void
+replace_spin_keys (pthread_spinlock_t *old, pthread_spinlock_t new)
+{
+  if (old == NULL)
+    return;
+
+  if (EPERM == pthread_spin_destroy (old))
+    {
+#define THREADERR "Error cleaning up spin_keys for thread "
+#define THREADERR_LEN ((sizeof (THREADERR) / sizeof (*THREADERR)) - 1)
+#define THREADID_LEN THREADERR_LEN + 66 + 1 + 1
+      int i;
+      char thread_id[THREADID_LEN] = THREADERR;
+      _ultoa ((unsigned long) GetCurrentThreadId (), &thread_id[THREADERR_LEN], 10);
+      for (i = THREADERR_LEN; thread_id[i] != '\0' && i < THREADID_LEN - 1; i++)
+        {
+        }
+      if (i < THREADID_LEN - 1)
+        {
+          thread_id[i] = '\n';
+          thread_id[i + 1] = '\0';
+        }
+#undef THREADERR
+#undef THREADERR_LEN
+#undef THREADID_LEN
+      OutputDebugStringA (thread_id);
+      abort ();
+    }
+
+  *old = new;
+}
+
+/* Hook for TLS-based deregistration/registration of thread.  */
+static BOOL WINAPI
+__dyn_tls_pthread (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
+{
+  _pthread_v *t = NULL;
+  pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER;
+
+  if (dwReason == DLL_PROCESS_DETACH)
+    {
+#if defined(USE_VEH_FOR_MSC_SETTHREADNAME)
+      if (lpreserved == NULL && SetThreadName_VEH_handle != NULL)
+        {
+          RemoveVectoredExceptionHandler (SetThreadName_VEH_handle);
+          SetThreadName_VEH_handle = NULL;
+        }
+#endif
+      free_pthread_mem ();
+    }
+  else if (dwReason == DLL_PROCESS_ATTACH)
+    {
+#if defined(USE_VEH_FOR_MSC_SETTHREADNAME)
+      SetThreadName_VEH_handle = AddVectoredExceptionHandler (1, &SetThreadName_VEH);
+      /* Can't do anything on error anyway, check for NULL later */
+#endif
+    }
+  else if (dwReason == DLL_THREAD_DETACH)
+    {
+      if (_pthread_tls != 0xffffffff)
+	t = (_pthread_v *)TlsGetValue(_pthread_tls);
+      if (t && t->thread_noposix != 0)
+	{
+	  _pthread_cleanup_dest (t->x);
+	  if (t->h != NULL)
+	    {
+	      CloseHandle (t->h);
+	      if (t->evStart)
+		CloseHandle (t->evStart);
+	      t->evStart = NULL;
+	      t->h = NULL;
+	    }
+	  pthread_mutex_destroy (&t->p_clock);
+	  replace_spin_keys (&t->spin_keys, new_spin_keys);
+	  push_pthread_mem (t);
+	  t = NULL;
+	  TlsSetValue (_pthread_tls, t);
+	}
+      else if (t && t->ended == 0)
+	{
+	  if (t->evStart)
+	    CloseHandle(t->evStart);
+	  t->evStart = NULL;
+	  t->ended = 1;
+	  _pthread_cleanup_dest (t->x);
+	  if ((t->p_state & PTHREAD_CREATE_DETACHED) == PTHREAD_CREATE_DETACHED)
+	    {
+	      t->valid = DEAD_THREAD;
+	      if (t->h != NULL)
+		CloseHandle (t->h);
+	      t->h = NULL;
+	      pthread_mutex_destroy(&t->p_clock);
+	      replace_spin_keys (&t->spin_keys, new_spin_keys);
+	      push_pthread_mem (t);
+	      t = NULL;
+	      TlsSetValue (_pthread_tls, t);
+	      return TRUE;
+	    }
+	  pthread_mutex_destroy(&t->p_clock);
+	  replace_spin_keys (&t->spin_keys, new_spin_keys);
+	}
+      else if (t)
+	{
+	  if (t->evStart)
+	    CloseHandle (t->evStart);
+	  t->evStart = NULL;
+	  pthread_mutex_destroy (&t->p_clock);
+	  replace_spin_keys (&t->spin_keys, new_spin_keys);
+	}
+    }
+  return TRUE;
+}
+
+/* TLS-runtime section variable.  */
+#ifdef _MSC_VER
+#pragma section(".CRT$XLF", shared)
+#endif
+PIMAGE_TLS_CALLBACK WINPTHREADS_ATTRIBUTE((WINPTHREADS_SECTION(".CRT$XLF"))) __xl_f  = (PIMAGE_TLS_CALLBACK) __dyn_tls_pthread;
+#ifdef _MSC_VER
+#pragma data_seg()
+#endif
+
+#ifdef WINPTHREAD_DBG
+static int print_state = 0;
+void thread_print_set (int state)
+{
+  print_state = state;
+}
+
+void
+thread_print (volatile pthread_t t, char *txt)
+{
+    if (!print_state)
+      return;
+    if (!t)
+      printf("T%p %d %s\n",NULL,(int)GetCurrentThreadId(),txt);
+    else
+      {
+	printf("T%p %d V=%0X H=%p %s\n",
+	    __pth_gpointer_locked (t), 
+	    (int)GetCurrentThreadId(), 
+	    (int) (__pth_gpointer_locked (t))->valid, 
+	    (__pth_gpointer_locked (t))->h,
+	    txt
+	    );
+      }
+}
+#endif
+
+/* Internal collect-once structure.  */
+typedef struct collect_once_t {
+  pthread_once_t *o;
+  pthread_mutex_t m;
+  int count;
+  struct collect_once_t *next;
+} collect_once_t;
+
+static collect_once_t *once_obj = NULL;
+
+static pthread_spinlock_t once_global = PTHREAD_SPINLOCK_INITIALIZER;
+
+static collect_once_t *
+enterOnceObject (pthread_once_t *o)
+{
+  collect_once_t *c, *p = NULL;
+  pthread_spin_lock (&once_global);
+  c = once_obj;
+  while (c != NULL && c->o != o)
+    {
+      c = (p = c)->next;
+    }
+  if (!c)
+    {
+      c = (collect_once_t *) calloc(1,sizeof(collect_once_t));
+      c->o = o;
+      c->count = 1;
+      if (!p)
+        once_obj = c;
+      else
+        p->next = c;
+      pthread_mutex_init(&c->m, NULL);
+    }
+  else
+    c->count += 1;
+  pthread_spin_unlock (&once_global);
+  return c;
+}
+
+static void
+leaveOnceObject (collect_once_t *c)
+{
+  collect_once_t *h, *p = NULL;
+  if (!c)
+    return;
+  pthread_spin_lock (&once_global);
+  h = once_obj;
+  while (h != NULL && c != h)
+    h = (p = h)->next;
+
+  if (h)
+    {
+      c->count -= 1;
+      if (c->count == 0)
+	{
+	  pthread_mutex_destroy(&c->m);
+	  if (!p)
+	    once_obj = c->next;
+	  else
+	    p->next = c->next;
+	  free (c);
+	}
+    }
+  else
+    fprintf(stderr, "%p not found?!?!\n", c);
+  pthread_spin_unlock (&once_global);
+}
+
+static void
+_pthread_once_cleanup (void *o)
+{
+  collect_once_t *co = (collect_once_t *) o;
+  pthread_mutex_unlock (&co->m);
+  leaveOnceObject (co);
+}
+
+static int
+_pthread_once_raw (pthread_once_t *o, void (*func)(void))
+{
+  collect_once_t *co;
+  long state = *o;
+
+  CHECK_PTR(o);
+  CHECK_PTR(func);
+
+  if (state == 1)
+    return 0;
+  co = enterOnceObject(o);
+  pthread_mutex_lock(&co->m);
+  if (*o == 0)
+    {
+      func();
+      *o = 1;
+    }
+  else if (*o != 1)
+    fprintf (stderr," once %p is %d\n", o, (int) *o);
+  pthread_mutex_unlock(&co->m);
+  leaveOnceObject(co);
+
+  /* Done */
+  return 0;
+}
+
+/* Unimplemented.  */
+void *
+pthread_timechange_handler_np(void *dummy)
+{
+  return NULL;
+}
+
+/* Compatibility routine for pthread-win32.  It waits for ellapse of
+   interval and additionally checks for possible thread-cancelation.  */
+int
+pthread_delay_np (const struct timespec *interval)
+{
+  DWORD to = (!interval ? 0 : dwMilliSecs (_pthread_time_in_ms_from_timespec (interval)));
+  struct _pthread_v *s = __pthread_self_lite ();
+
+  if (!to)
+    {
+      pthread_testcancel ();
+      Sleep (0);
+      pthread_testcancel ();
+      return 0;
+    }
+  pthread_testcancel ();
+  if (s->evStart)
+    _pthread_wait_for_single_object (s->evStart, to);
+  else
+    Sleep (to);
+  pthread_testcancel ();
+  return 0;
+}
+
+int pthread_delay_np_ms (DWORD to);
+
+int
+pthread_delay_np_ms (DWORD to)
+{
+  struct _pthread_v *s = __pthread_self_lite ();
+
+  if (!to)
+    {
+      pthread_testcancel ();
+      Sleep (0);
+      pthread_testcancel ();
+      return 0;
+    }
+  pthread_testcancel ();
+  if (s->evStart)
+    _pthread_wait_for_single_object (s->evStart, to);
+  else
+    Sleep (to);
+  pthread_testcancel ();
+  return 0;
+}
+
+/* Compatibility routine for pthread-win32.  It returns the
+   amount of available CPUs on system.  */
+int
+pthread_num_processors_np(void) 
+{
+  int r = 0;
+  DWORD_PTR ProcessAffinityMask, SystemAffinityMask;
+
+  if (GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask, &SystemAffinityMask))
+    {
+      for(; ProcessAffinityMask != 0; ProcessAffinityMask >>= 1)
+	r += (ProcessAffinityMask & 1) != 0;
+    }
+  /* assume at least 1 */
+  return r ? r : 1;
+}
+
+/* Compatiblity routine for pthread-win32.  Allows to set amount of used
+   CPUs for process.  */
+int
+pthread_set_num_processors_np(int n) 
+{
+  DWORD_PTR ProcessAffinityMask, ProcessNewAffinityMask = 0, SystemAffinityMask;
+  int r = 0; 
+  /* need at least 1 */
+  n = n ? n : 1;
+  if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask))
+    {
+      for (; ProcessAffinityMask != 0; ProcessAffinityMask >>= 1)
+	{
+	  ProcessNewAffinityMask <<= 1;
+	  if ((ProcessAffinityMask & 1) != 0 && r < n)
+	    {
+	      ProcessNewAffinityMask |= 1;
+	      r++;
+	    }
+	}
+      SetProcessAffinityMask (GetCurrentProcess (),ProcessNewAffinityMask);
+    }
+  return r;
+}
+
+int
+pthread_once (pthread_once_t *o, void (*func)(void))
+{
+  collect_once_t *co;
+  long state = *o;
+
+  CHECK_PTR(o);
+  CHECK_PTR(func);
+
+  if (state == 1)
+    return 0;
+  co = enterOnceObject(o);
+  pthread_mutex_lock(&co->m);
+  if (*o == 0)
+    {
+      pthread_cleanup_push(_pthread_once_cleanup, co);
+      func();
+      pthread_cleanup_pop(0);
+      *o = 1;
+    }
+  else if (*o != 1)
+    fprintf (stderr," once %p is %d\n", o, (int) *o);
+  pthread_mutex_unlock(&co->m);
+  leaveOnceObject(co);
+
+  return 0;
+}
+
+int
+pthread_key_create (pthread_key_t *key, void (* dest)(void *))
+{
+	unsigned int i;
+	long nmax;
+	void (**d)(void *);
+
+	if (!key)
+		return EINVAL;
+
+	pthread_rwlock_wrlock (&_pthread_key_lock);
+
+	for (i = _pthread_key_sch; i < _pthread_key_max; i++)
+	{
+		if (!_pthread_key_dest[i])
+		{
+			*key = i;
+			if (dest)
+				_pthread_key_dest[i] = dest;
+			else
+				_pthread_key_dest[i] = (void(*)(void *))1;
+			pthread_rwlock_unlock (&_pthread_key_lock);
+			return 0;
+		}
+	}
+
+	for (i = 0; i < _pthread_key_sch; i++)
+	{
+		if (!_pthread_key_dest[i])
+		{
+			*key = i;
+			if (dest)
+				_pthread_key_dest[i] = dest;
+			else
+				_pthread_key_dest[i] = (void(*)(void *))1;
+			pthread_rwlock_unlock (&_pthread_key_lock);
+
+			return 0;
+		}
+	}
+
+	if (_pthread_key_max == PTHREAD_KEYS_MAX)
+	{
+		pthread_rwlock_unlock(&_pthread_key_lock);
+		return ENOMEM;
+	}
+
+	nmax = _pthread_key_max * 2;
+	if (nmax == 0)
+		nmax = _pthread_key_max + 1;
+	if (nmax > PTHREAD_KEYS_MAX)
+		nmax = PTHREAD_KEYS_MAX;
+
+	/* No spare room anywhere */
+	d = (void (__cdecl **)(void *))realloc(_pthread_key_dest, nmax * sizeof(*d));
+	if (!d)
+	{
+		pthread_rwlock_unlock (&_pthread_key_lock);
+		return ENOMEM;
+	}
+
+	/* Clear new region */
+	memset ((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *));
+
+	/* Use new region */
+	_pthread_key_dest = d;
+	_pthread_key_sch = _pthread_key_max + 1;
+	*key = _pthread_key_max;
+	_pthread_key_max = nmax;
+
+	if (dest)
+		_pthread_key_dest[*key] = dest;
+	else
+		_pthread_key_dest[*key] = (void(*)(void *))1;
+
+	pthread_rwlock_unlock (&_pthread_key_lock);
+	return 0;
+}
+
+int
+pthread_key_delete (pthread_key_t key)
+{
+  if (key >= _pthread_key_max || !_pthread_key_dest)
+    return EINVAL;
+
+  pthread_rwlock_wrlock (&_pthread_key_lock);
+  
+  _pthread_key_dest[key] = NULL;
+
+  /* Start next search from our location */
+  if (_pthread_key_sch > key)
+    _pthread_key_sch = key;
+  /* So now we need to walk the complete list of threads
+     and remove key's reference for it.  */
+  __pth_remove_use_for_key (key);
+
+  pthread_rwlock_unlock (&_pthread_key_lock);
+  return 0;
+}
+
+void *
+pthread_getspecific (pthread_key_t key)
+{
+  DWORD lasterr = GetLastError ();
+  void *r;
+  _pthread_v *t = __pthread_self_lite ();
+  pthread_spin_lock (&t->spin_keys);
+  r = (key >= t->keymax || t->keyval_set[key] == 0 ? NULL : t->keyval[key]);
+  pthread_spin_unlock (&t->spin_keys);
+  SetLastError (lasterr);
+  return r;
+}
+
+int
+pthread_setspecific (pthread_key_t key, const void *value)
+{
+  DWORD lasterr = GetLastError ();
+  _pthread_v *t = __pthread_self_lite ();
+  
+  pthread_spin_lock (&t->spin_keys);
+
+  if (key >= t->keymax)
+    {
+      int keymax = (key + 1);
+      void **kv;
+      unsigned char *kv_set;
+
+      kv = (void **) realloc (t->keyval, keymax * sizeof (void *));
+
+      if (!kv)
+        {
+	  pthread_spin_unlock (&t->spin_keys);
+	  return ENOMEM;
+	}
+      kv_set = (unsigned char *) realloc (t->keyval_set, keymax);
+      if (!kv_set)
+        {
+	  pthread_spin_unlock (&t->spin_keys);
+	  return ENOMEM;
+	}
+
+      /* Clear new region */
+      memset (&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void *));
+      memset (&kv_set[t->keymax], 0, (keymax - t->keymax));
+
+      t->keyval = kv;
+      t->keyval_set = kv_set;
+      t->keymax = keymax;
+    }
+
+  t->keyval[key] = (void *) value;
+  t->keyval_set[key] = 1;
+  pthread_spin_unlock (&t->spin_keys);
+  SetLastError (lasterr);
+
+  return 0;
+}
+
+int
+pthread_equal (pthread_t t1, pthread_t t2)
+{
+  return (t1 == t2);
+}
+
+void
+pthread_tls_init (void)
+{
+  _pthread_tls = TlsAlloc();
+
+  /* Cannot continue if out of indexes */
+  if (_pthread_tls == TLS_OUT_OF_INDEXES)
+    abort();
+}
+
+void
+_pthread_cleanup_dest (pthread_t t)
+{
+	_pthread_v *tv;
+	unsigned int i, j;
+
+	if (!t)
+		return;
+	tv = __pth_gpointer_locked (t);
+	if (!tv)
+		return;
+
+	for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
+	{
+		int flag = 0;
+
+		pthread_spin_lock (&tv->spin_keys);
+		for (i = 0; i < tv->keymax; i++)
+		{
+			void *val = tv->keyval[i];
+
+			if (tv->keyval_set[i])
+			{
+				pthread_rwlock_rdlock (&_pthread_key_lock);
+				if ((uintptr_t) _pthread_key_dest[i] > 1)
+				{
+					/* Call destructor */
+					tv->keyval[i] = NULL;
+					tv->keyval_set[i] = 0;
+					pthread_spin_unlock (&tv->spin_keys);
+					_pthread_key_dest[i](val);
+					pthread_spin_lock (&tv->spin_keys);
+					flag = 1;
+				}
+				else
+				{
+					tv->keyval[i] = NULL;
+					tv->keyval_set[i] = 0;
+				}
+				pthread_rwlock_unlock(&_pthread_key_lock);
+			}
+		}
+		pthread_spin_unlock (&tv->spin_keys);
+		/* Nothing to do? */
+		if (!flag)
+			return;
+	}
+}
+
+static _pthread_v *
+__pthread_self_lite (void)
+{
+  _pthread_v *t;
+  pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER;
+
+  _pthread_once_raw (&_pthread_tls_once, pthread_tls_init);
+
+  t = (_pthread_v *) TlsGetValue (_pthread_tls);
+  if (t)
+    return t;
+  /* Main thread? */
+  t = (struct _pthread_v *) pop_pthread_mem ();
+
+  /* If cannot initialize main thread, then the only thing we can do is return null pthread_t */
+  if (!__xl_f || !t)
+    return 0;
+
+  t->p_state = PTHREAD_DEFAULT_ATTR /*| PTHREAD_CREATE_DETACHED*/;
+  t->tid = GetCurrentThreadId();
+  t->evStart = CreateEvent (NULL, 1, 0, NULL);
+  t->p_clock = PTHREAD_MUTEX_INITIALIZER;
+  replace_spin_keys (&t->spin_keys, new_spin_keys);
+  t->sched_pol = SCHED_OTHER;
+  t->h = NULL; //GetCurrentThread();
+  if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &t->h, 0, FALSE, DUPLICATE_SAME_ACCESS))
+    abort ();
+  t->sched.sched_priority = GetThreadPriority(t->h);
+  t->ended = 0;
+  t->thread_noposix = 1;
+
+  /* Save for later */
+  if (!TlsSetValue(_pthread_tls, t))
+    abort ();
+  return t;
+}
+
+pthread_t
+pthread_self (void)
+{
+  _pthread_v *t = __pthread_self_lite ();
+
+  if (!t)
+    return 0;
+  return t->x;
+}
+
+/* Internal helper for getting event handle of thread T.  */
+void *
+pthread_getevent ()
+{
+  _pthread_v *t = __pthread_self_lite ();
+  return (!t ? NULL : t->evStart);
+}
+
+/* Internal helper for getting thread handle of thread T.  */
+void *
+pthread_gethandle (pthread_t t)
+{
+  struct _pthread_v *tv = __pth_gpointer_locked (t);
+  return (!tv ? NULL : tv->h);
+}
+
+/* Internal helper for getting pointer of clean of current thread.  */
+struct _pthread_cleanup **
+pthread_getclean (void)
+{
+  struct _pthread_v *t = __pthread_self_lite ();
+  if (!t) return NULL;
+  return &t->clean;
+}
+
+int
+pthread_get_concurrency (int *val)
+{
+  *val = _pthread_concur;
+  return 0;
+}
+
+int
+pthread_set_concurrency (int val)
+{
+  _pthread_concur = val;
+  return 0;
+}
+
+void
+pthread_exit (void *res)
+{
+  _pthread_v *t = NULL;
+  unsigned rslt = (unsigned) ((intptr_t) res);
+  struct _pthread_v *id = __pthread_self_lite ();
+
+  id->ret_arg = res;
+
+  _pthread_cleanup_dest (id->x);
+  if (id->thread_noposix == 0)
+    longjmp(id->jb, 1);
+
+  /* Make sure we free ourselves if we are detached */
+  if ((t = (_pthread_v *)TlsGetValue(_pthread_tls)) != NULL)
+    {
+      if (!t->h)
+	{
+	  t->valid = DEAD_THREAD;
+	  if (t->evStart)
+	    CloseHandle (t->evStart);
+	  t->evStart = NULL;
+	  rslt = (unsigned) (size_t) t->ret_arg;
+	  push_pthread_mem(t);
+	  t = NULL;
+	  TlsSetValue (_pthread_tls, t);
+	}
+      else
+	{
+	  rslt = (unsigned) (size_t) t->ret_arg;
+	  t->ended = 1;
+	  if (t->evStart)
+	    CloseHandle (t->evStart);
+	  t->evStart = NULL;
+	  if ((t->p_state & PTHREAD_CREATE_DETACHED) == PTHREAD_CREATE_DETACHED)
+	    {
+	      t->valid = DEAD_THREAD;
+	      CloseHandle (t->h);
+	      t->h = NULL;
+	      push_pthread_mem(t);
+	      t = NULL;
+	      TlsSetValue(_pthread_tls, t);
+	    }
+	}
+    }
+  /* Time to die */
+  _endthreadex(rslt);
+}
+
+void
+_pthread_invoke_cancel (void)
+{
+  _pthread_cleanup *pcup;
+  struct _pthread_v *se = __pthread_self_lite ();
+  se->in_cancel = 1;
+  _pthread_setnobreak (1);
+  InterlockedDecrement(&_pthread_cancelling);
+
+  /* Call cancel queue */
+  for (pcup = se->clean; pcup; pcup = pcup->next)
+    {
+      pcup->func((pthread_once_t *)pcup->arg);
+    }
+
+  _pthread_setnobreak (0);
+  pthread_exit(PTHREAD_CANCELED);
+}
+
+int
+__pthread_shallcancel (void)
+{
+  struct _pthread_v *t;
+  if (!_pthread_cancelling)
+    return 0;
+  t = __pthread_self_lite ();
+  if (t == NULL)
+    return 0;
+  if (t->nobreak <= 0 && t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE))
+    return 1;
+  return 0;
+}
+
+void
+_pthread_setnobreak (int v)
+{
+  struct _pthread_v *t = __pthread_self_lite ();
+  if (t == NULL)
+    return;
+  if (v > 0)
+    InterlockedIncrement ((long*)&t->nobreak);
+  else
+    InterlockedDecrement((long*)&t->nobreak);
+}
+
+void
+pthread_testcancel (void)
+{
+  struct _pthread_v *self = __pthread_self_lite ();
+
+  if (!self || self->in_cancel)
+    return;
+  if (!_pthread_cancelling)
+    return;
+  pthread_mutex_lock (&self->p_clock);
+
+  if (self->cancelled && (self->p_state & PTHREAD_CANCEL_ENABLE) && self->nobreak <= 0)
+    {
+      self->in_cancel = 1;
+      self->p_state &= ~PTHREAD_CANCEL_ENABLE;
+      if (self->evStart)
+	ResetEvent (self->evStart);
+      pthread_mutex_unlock (&self->p_clock);
+      _pthread_invoke_cancel ();
+    }
+  pthread_mutex_unlock (&self->p_clock);
+}
+
+int
+pthread_cancel (pthread_t t)
+{
+  struct _pthread_v *tv = __pth_gpointer_locked (t);
+
+  if (tv == NULL)
+    return ESRCH;
+  CHECK_OBJECT(tv, ESRCH);
+  /*if (tv->ended) return ESRCH;*/
+  pthread_mutex_lock(&tv->p_clock);
+  if (pthread_equal(pthread_self(), t))
+    {
+      if(tv->cancelled)
+	{
+	  pthread_mutex_unlock(&tv->p_clock);
+	  return (tv->in_cancel ? ESRCH : 0);
+	}
+      tv->cancelled = 1;
+      InterlockedIncrement(&_pthread_cancelling);
+      if(tv->evStart) SetEvent(tv->evStart);
+      if ((tv->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) != 0 && (tv->p_state & PTHREAD_CANCEL_ENABLE) != 0)
+	{
+	  tv->p_state &= ~PTHREAD_CANCEL_ENABLE;
+	  tv->in_cancel = 1;
+	  pthread_mutex_unlock(&tv->p_clock);
+	  _pthread_invoke_cancel();
+	}
+      else
+	pthread_mutex_unlock(&tv->p_clock);
+      return 0;
+    }
+
+  if ((tv->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) != 0 && (tv->p_state & PTHREAD_CANCEL_ENABLE) != 0)
+    {
+      /* Dangerous asynchronous cancelling */
+      CONTEXT ctxt;
+
+      if(tv->in_cancel)
+	{
+	  pthread_mutex_unlock(&tv->p_clock);
+	  return (tv->in_cancel ? ESRCH : 0);
+	}
+      /* Already done? */
+      if(tv->cancelled || tv->in_cancel)
+	{
+	  /* ??? pthread_mutex_unlock (&tv->p_clock); */
+	  return ESRCH;
+	}
+
+      ctxt.ContextFlags = CONTEXT_CONTROL;
+
+      SuspendThread (tv->h);
+      if (WaitForSingleObject (tv->h, 0) == WAIT_TIMEOUT)
+	{
+	  GetThreadContext(tv->h, &ctxt);
+#ifdef _M_X64
+	  ctxt.Rip = (uintptr_t) _pthread_invoke_cancel;
+#elif defined(_M_IX86)
+	  ctxt.Eip = (uintptr_t) _pthread_invoke_cancel;
+#elif defined(_M_ARM) || defined(_M_ARM64)
+	  ctxt.Pc = (uintptr_t) _pthread_invoke_cancel;
+#else
+#error Unsupported architecture
+#endif
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+	  SetThreadContext (tv->h, &ctxt);
+#endif
+
+	  /* Also try deferred Cancelling */
+	  tv->cancelled = 1;
+	  tv->p_state &= ~PTHREAD_CANCEL_ENABLE;
+	  tv->in_cancel = 1;
+
+	  /* Notify everyone to look */
+	  InterlockedIncrement (&_pthread_cancelling);
+	  if (tv->evStart)
+	    SetEvent (tv->evStart);
+	  pthread_mutex_unlock (&tv->p_clock);
+
+	  ResumeThread (tv->h);
+	}
+    }
+  else
+    {
+      if (tv->cancelled == 0)
+	{
+	  /* Safe deferred Cancelling */
+	  tv->cancelled = 1;
+
+	  /* Notify everyone to look */
+	  InterlockedIncrement (&_pthread_cancelling);
+	  if (tv->evStart)
+	    SetEvent (tv->evStart);
+	}
+      else
+	{
+	  pthread_mutex_unlock (&tv->p_clock);
+	  return (tv->in_cancel ? ESRCH : 0);
+	}
+    }
+  pthread_mutex_unlock (&tv->p_clock);
+  return 0;
+}
+
+/* half-stubbed version as we don't really well support signals */
+int
+pthread_kill (pthread_t t, int sig)
+{
+  struct _pthread_v *tv;
+
+  pthread_mutex_lock (&mtx_pthr_locked);
+  tv = __pthread_get_pointer (t);
+  if (!tv || t != tv->x || tv->in_cancel || tv->ended || tv->h == NULL
+      || tv->h == INVALID_HANDLE_VALUE)
+  {
+    pthread_mutex_unlock (&mtx_pthr_locked);
+    return ESRCH;
+  }
+  pthread_mutex_unlock (&mtx_pthr_locked);
+  if (!sig)
+    return 0;
+  if (sig < SIGINT || sig > NSIG)
+    return EINVAL;
+  return pthread_cancel(t);
+}
+
+unsigned
+_pthread_get_state (const pthread_attr_t *attr, unsigned flag)
+{
+  return (attr->p_state & flag);
+}
+
+int
+_pthread_set_state (pthread_attr_t *attr, unsigned flag, unsigned val)
+{
+  if (~flag & val)
+    return EINVAL;
+  attr->p_state &= ~flag;
+  attr->p_state |= val;
+
+  return 0;
+}
+
+int
+pthread_attr_init (pthread_attr_t *attr)
+{
+  memset (attr, 0, sizeof (pthread_attr_t));
+  attr->p_state = PTHREAD_DEFAULT_ATTR;
+  attr->stack = NULL;
+  attr->s_size = 0;
+  return 0;
+}
+
+int
+pthread_attr_destroy (pthread_attr_t *attr)
+{
+  /* No need to do anything */
+  memset (attr, 0, sizeof(pthread_attr_t));
+  return 0;
+}
+
+int
+pthread_attr_setdetachstate (pthread_attr_t *a, int flag)
+{
+  return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag);
+}
+
+int
+pthread_attr_getdetachstate (const pthread_attr_t *a, int *flag)
+{
+  *flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED);
+  return 0;
+}
+
+int
+pthread_attr_setinheritsched (pthread_attr_t *a, int flag)
+{
+  if (!a || (flag != PTHREAD_INHERIT_SCHED && flag != PTHREAD_EXPLICIT_SCHED))
+    return EINVAL;
+  return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag);
+}
+
+int
+pthread_attr_getinheritsched (const pthread_attr_t *a, int *flag)
+{
+  *flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED);
+  return 0;
+}
+
+int
+pthread_attr_setscope (pthread_attr_t *a, int flag)
+{
+  return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag);
+}
+
+int
+pthread_attr_getscope (const pthread_attr_t *a, int *flag)
+{
+  *flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM);
+  return 0;
+}
+
+int
+pthread_attr_getstackaddr (const pthread_attr_t *attr, void **stack)
+{
+  *stack = attr->stack;
+  return 0;
+}
+
+int
+pthread_attr_setstackaddr (pthread_attr_t *attr, void *stack)
+{
+  attr->stack = stack;
+  return 0;
+}
+
+int
+pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size)
+{
+  *size = attr->s_size;
+  return 0;
+}
+
+int
+pthread_attr_setstacksize (pthread_attr_t *attr, size_t size)
+{
+  attr->s_size = size;
+  return 0;
+}
+
+static void
+test_cancel_locked (pthread_t t)
+{
+  struct _pthread_v *tv = __pth_gpointer_locked (t);
+
+  if (!tv || tv->in_cancel || tv->ended != 0 || (tv->p_state & PTHREAD_CANCEL_ENABLE) == 0)
+    return;
+  if ((tv->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) == 0)
+    return;
+  if (WaitForSingleObject(tv->evStart, 0) != WAIT_OBJECT_0)
+    return;
+  pthread_mutex_unlock (&tv->p_clock);
+  _pthread_invoke_cancel();
+}
+
+int
+pthread_setcancelstate (int state, int *oldstate)
+{
+  _pthread_v *t = __pthread_self_lite ();
+
+  if (!t || (state & PTHREAD_CANCEL_ENABLE) != state)
+    return EINVAL;
+
+  pthread_mutex_lock (&t->p_clock);
+  if (oldstate)
+    *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE;
+  t->p_state &= ~PTHREAD_CANCEL_ENABLE;
+  t->p_state |= state;
+  test_cancel_locked (t->x);
+  pthread_mutex_unlock (&t->p_clock);
+
+  return 0;
+}
+
+int
+pthread_setcanceltype (int type, int *oldtype)
+{
+  _pthread_v *t = __pthread_self_lite ();
+
+  if (!t || (type & PTHREAD_CANCEL_ASYNCHRONOUS) != type)
+    return EINVAL;
+
+  pthread_mutex_lock (&t->p_clock);
+  if (oldtype)
+    *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS;
+  t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
+  t->p_state |= type;
+  test_cancel_locked (t->x);
+  pthread_mutex_unlock (&t->p_clock);
+
+  return 0;
+}
+
+void _fpreset (void);
+
+#if defined(__i386__)
+/* Align ESP on 16-byte boundaries. */
+#  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
+__attribute__((force_align_arg_pointer))
+#  endif
+#endif
+int
+pthread_create_wrapper (void *args)
+{
+  unsigned rslt = 0;
+  struct _pthread_v *tv = (struct _pthread_v *)args;
+
+  _fpreset();
+
+  pthread_mutex_lock (&mtx_pthr_locked);
+  pthread_mutex_lock (&tv->p_clock);
+  _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
+  TlsSetValue(_pthread_tls, tv);
+  tv->tid = GetCurrentThreadId();
+  pthread_mutex_unlock (&tv->p_clock);
+
+
+  if (!setjmp(tv->jb))
+    {
+      intptr_t trslt = (intptr_t) 128;
+      /* Provide to this thread a default exception handler.  */
+      #ifdef __SEH__
+	asm ("\t.tl_start:\n"
+	  "\t.seh_handler __C_specific_handler, @except\n"
+	  "\t.seh_handlerdata\n"
+	  "\t.long 1\n"
+	  "\t.rva .tl_start, .tl_end, _gnu_exception_handler ,.tl_end\n"
+	  "\t.text"
+	  );
+      #endif      /* Call function and save return value */
+      pthread_mutex_unlock (&mtx_pthr_locked);
+      if (tv->func)
+        trslt = (intptr_t) tv->func(tv->ret_arg);
+      #ifdef __SEH__
+	asm ("\tnop\n\t.tl_end: nop\n");
+      #endif
+      pthread_mutex_lock (&mtx_pthr_locked);
+      tv->ret_arg = (void*) trslt;
+      /* Clean up destructors */
+      _pthread_cleanup_dest(tv->x);
+    }
+  else
+    pthread_mutex_lock (&mtx_pthr_locked);
+
+  pthread_mutex_lock (&tv->p_clock);
+  rslt = (unsigned) (size_t) tv->ret_arg;
+  /* Make sure we free ourselves if we are detached */
+  if (tv->evStart)
+    CloseHandle (tv->evStart);
+  tv->evStart = NULL;
+  if (!tv->h)
+    {
+      tv->valid = DEAD_THREAD;
+      pthread_mutex_unlock (&tv->p_clock);
+      pthread_mutex_destroy (&tv->p_clock);
+      push_pthread_mem (tv);
+      tv = NULL;
+      TlsSetValue (_pthread_tls, tv);
+    }
+  else
+    {
+      pthread_mutex_unlock (&tv->p_clock);
+      pthread_mutex_destroy (&tv->p_clock);
+      /* Reinitialise p_clock, since there may be attempts at
+         destroying it again in __dyn_tls_thread later on. */
+      tv->p_clock = PTHREAD_MUTEX_INITIALIZER;
+      tv->ended = 1;
+    }
+  while (pthread_mutex_unlock (&mtx_pthr_locked) == 0)
+   Sleep (0);
+  _endthreadex (rslt);
+  return rslt;
+}
+
+int
+pthread_create (pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg)
+{
+  HANDLE thrd = NULL;
+  int redo = 0;
+  struct _pthread_v *tv;
+  size_t ssize = 0;
+  pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER;
+
+  if ((tv = pop_pthread_mem ()) == NULL)
+    return EAGAIN;
+
+  if (th)
+    *th = tv->x;
+
+  /* Save data in pthread_t */
+  tv->ended = 0;
+  tv->ret_arg = arg;
+  tv->func = func;
+  tv->p_state = PTHREAD_DEFAULT_ATTR;
+  tv->h = INVALID_HANDLE_VALUE;
+  /* We retry it here a few times, as events are a limited resource ... */
+  do
+    {
+      tv->evStart = CreateEvent (NULL, 1, 0, NULL);
+      if (tv->evStart != NULL)
+	break;
+      Sleep ((!redo ? 0 : 20));
+    }
+  while (++redo <= 4);
+
+  tv->p_clock = PTHREAD_MUTEX_INITIALIZER;
+  replace_spin_keys (&tv->spin_keys, new_spin_keys);
+  tv->valid = LIFE_THREAD;
+  tv->sched.sched_priority = THREAD_PRIORITY_NORMAL;
+  tv->sched_pol = SCHED_OTHER;
+  if (tv->evStart == NULL)
+    {
+      if (th)
+       memset (th, 0, sizeof (pthread_t));
+      push_pthread_mem (tv);
+      return EAGAIN;
+    }
+
+  if (attr)
+    {
+      int inh = 0;
+      tv->p_state = attr->p_state;
+      ssize = attr->s_size;
+      pthread_attr_getinheritsched (attr, &inh);
+      if (inh)
+	{
+	  tv->sched.sched_priority = __pthread_self_lite ()->sched.sched_priority;
+	}
+      else
+	tv->sched.sched_priority = attr->param.sched_priority;
+    }
+
+  /* Make sure tv->h has value of INVALID_HANDLE_VALUE */
+  _ReadWriteBarrier();
+
+  thrd = (HANDLE) _beginthreadex(NULL, ssize, (unsigned int (__stdcall *)(void *))pthread_create_wrapper, tv, 0x4/*CREATE_SUSPEND*/, NULL);
+  if (thrd == INVALID_HANDLE_VALUE)
+    thrd = 0;
+  /* Failed */
+  if (!thrd)
+    {
+      if (tv->evStart)
+	CloseHandle (tv->evStart);
+      pthread_mutex_destroy (&tv->p_clock);
+      replace_spin_keys (&tv->spin_keys, new_spin_keys);
+      tv->evStart = NULL;
+      tv->h = 0;
+      if (th)
+        memset (th, 0, sizeof (pthread_t));
+      push_pthread_mem (tv);
+      return EAGAIN;
+    }
+  {
+    int pr = tv->sched.sched_priority;
+    if (pr <= THREAD_PRIORITY_IDLE) {
+	pr = THREAD_PRIORITY_IDLE;
+    } else if (pr <= THREAD_PRIORITY_LOWEST) {
+	pr = THREAD_PRIORITY_LOWEST;
+    } else if (pr >= THREAD_PRIORITY_TIME_CRITICAL) {
+	pr = THREAD_PRIORITY_TIME_CRITICAL;
+    } else if (pr >= THREAD_PRIORITY_HIGHEST) {
+	pr = THREAD_PRIORITY_HIGHEST;
+    }
+    SetThreadPriority (thrd, pr);
+  }
+  ResetEvent (tv->evStart);
+  if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0)
+    {
+      tv->h = 0;
+      ResumeThread (thrd);
+      CloseHandle (thrd);
+    }
+  else
+    {
+      tv->h = thrd;
+      ResumeThread (thrd);
+    }
+  Sleep (0);
+  return 0;
+}
+
+int
+pthread_join (pthread_t t, void **res)
+{
+  DWORD dwFlags;
+  struct _pthread_v *tv = __pth_gpointer_locked (t);
+  pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER;
+
+  if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags))
+    return ESRCH;
+  if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0)
+    return EINVAL;
+  if (pthread_equal(pthread_self(), t))
+    return EDEADLK;
+
+  /* pthread_testcancel (); */
+  if (tv->ended == 0 || (tv->h != NULL && tv->h != INVALID_HANDLE_VALUE))
+    WaitForSingleObject (tv->h, INFINITE);
+  CloseHandle (tv->h);
+  if (tv->evStart)
+    CloseHandle (tv->evStart);
+  tv->evStart = NULL;
+  /* Obtain return value */
+  if (res)
+    *res = tv->ret_arg;
+  pthread_mutex_destroy (&tv->p_clock);
+  replace_spin_keys (&tv->spin_keys, new_spin_keys);
+  push_pthread_mem (tv);
+
+  return 0;
+}
+
+int
+_pthread_tryjoin (pthread_t t, void **res)
+{
+  DWORD dwFlags;
+  struct _pthread_v *tv;
+  pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER;
+
+  pthread_mutex_lock (&mtx_pthr_locked);
+  tv = __pthread_get_pointer (t);
+
+  if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags))
+    {
+      pthread_mutex_unlock (&mtx_pthr_locked);
+      return ESRCH;
+    }
+
+  if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0)
+    {
+      pthread_mutex_unlock (&mtx_pthr_locked);
+      return EINVAL;
+    }
+  if (pthread_equal(pthread_self(), t))
+    {
+      pthread_mutex_unlock (&mtx_pthr_locked);
+      return EDEADLK;
+    }
+  if(tv->ended == 0 && WaitForSingleObject(tv->h, 0))
+    {
+      if (tv->ended == 0)
+        {
+	      pthread_mutex_unlock (&mtx_pthr_locked);
+	      /* pthread_testcancel (); */
+	      return EBUSY;
+	    }
+    }
+  CloseHandle (tv->h);
+  if (tv->evStart)
+    CloseHandle (tv->evStart);
+  tv->evStart = NULL;
+
+  /* Obtain return value */
+  if (res)
+    *res = tv->ret_arg;
+  pthread_mutex_destroy (&tv->p_clock);
+  replace_spin_keys (&tv->spin_keys, new_spin_keys);
+
+  push_pthread_mem (tv);
+
+  pthread_mutex_unlock (&mtx_pthr_locked);
+  /* pthread_testcancel (); */
+  return 0;
+}
+
+int
+pthread_detach (pthread_t t)
+{
+  int r = 0;
+  DWORD dwFlags;
+  struct _pthread_v *tv = __pth_gpointer_locked (t);
+  HANDLE dw;
+  pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER;
+
+  pthread_mutex_lock (&mtx_pthr_locked);
+  if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags))
+    {
+      pthread_mutex_unlock (&mtx_pthr_locked);
+      return ESRCH;
+    }
+  if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0)
+    {
+      pthread_mutex_unlock (&mtx_pthr_locked);
+      return EINVAL;
+    }
+  /* if (tv->ended) r = ESRCH; */
+  dw = tv->h;
+  tv->h = 0;
+  tv->p_state |= PTHREAD_CREATE_DETACHED;
+  _ReadWriteBarrier();
+  if (dw)
+    {
+      CloseHandle (dw);
+      if (tv->ended)
+	{
+	  if (tv->evStart)
+	    CloseHandle (tv->evStart);
+	  tv->evStart = NULL;
+	  pthread_mutex_destroy (&tv->p_clock);
+	  replace_spin_keys (&tv->spin_keys, new_spin_keys);
+	  push_pthread_mem (tv);
+	}
+    }
+  pthread_mutex_unlock (&mtx_pthr_locked);
+
+  return r;
+}
+
+static int dummy_concurrency_level = 0;
+
+int
+pthread_getconcurrency (void)
+{
+  return dummy_concurrency_level;
+}
+
+int
+pthread_setconcurrency (int new_level)
+{
+  dummy_concurrency_level = new_level;
+  return 0;
+}
+
+int
+pthread_setname_np (pthread_t thread, const char *name)
+{
+  struct _pthread_v *tv;
+  char *stored_name;
+
+  if (name == NULL)
+    return EINVAL;
+
+  tv = __pth_gpointer_locked (thread);
+  if (!tv || thread != tv->x || tv->in_cancel || tv->ended || tv->h == NULL
+      || tv->h == INVALID_HANDLE_VALUE)
+    return ESRCH;
+
+  stored_name = strdup (name);
+  if (stored_name == NULL)
+    return ENOMEM;
+
+  if (tv->thread_name != NULL)
+    free (tv->thread_name);
+
+  tv->thread_name = stored_name;
+  SetThreadName (tv->tid, name);
+  return 0;
+}
+
+int
+pthread_getname_np (pthread_t thread, char *name, size_t len)
+{
+  HRESULT result;
+  struct _pthread_v *tv;
+
+  if (name == NULL)
+    return EINVAL;
+
+  tv = __pth_gpointer_locked (thread);
+  if (!tv || thread != tv->x || tv->in_cancel || tv->ended || tv->h == NULL
+      || tv->h == INVALID_HANDLE_VALUE)
+    return ESRCH;
+
+  if (len < 1)
+    return ERANGE;
+
+  if (tv->thread_name == NULL)
+    {
+      name[0] = '\0';
+      return 0;
+    }
+
+  if (strlen (tv->thread_name) >= len)
+    return ERANGE;
+
+  result = StringCchCopyNA (name, len, tv->thread_name, len - 1);
+  if (SUCCEEDED (result))
+    return 0;
+
+  return ERANGE;
+}
diff --git a/libs/winpthreads/src/thread.h b/libs/winpthreads/src/thread.h
new file mode 100644
index 00000000000..729c5bc68ad
--- /dev/null
+++ b/libs/winpthreads/src/thread.h
@@ -0,0 +1,79 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WIN_PTHREAD_H
+#define WIN_PTHREAD_H
+
+#include <windows.h>
+#include <setjmp.h>
+#include "rwlock.h"
+
+#define LIFE_THREAD 0xBAB1F00D
+#define DEAD_THREAD 0xDEADBEEF
+#define EXCEPTION_SET_THREAD_NAME ((DWORD) 0x406D1388)
+
+typedef struct _pthread_v _pthread_v;
+struct _pthread_v
+{
+    unsigned int valid;
+    void *ret_arg;
+    void *(* func)(void *);
+    _pthread_cleanup *clean;
+    int nobreak;
+    HANDLE h;
+    HANDLE evStart;
+    pthread_mutex_t p_clock;
+    int cancelled : 2;
+    int in_cancel : 2;
+    int thread_noposix : 2;
+    unsigned int p_state;
+    unsigned int keymax;
+    void **keyval;
+    unsigned char *keyval_set;
+    char *thread_name;
+    pthread_spinlock_t spin_keys;
+    DWORD tid;
+    int rwlc;
+    pthread_rwlock_t rwlq[RWLS_PER_THREAD];
+    int sched_pol;
+    int ended;
+    struct sched_param sched;
+    jmp_buf jb;
+    struct _pthread_v *next;
+    pthread_t x; /* Internal posix handle.  */
+};
+
+typedef struct __pthread_idlist {
+  struct _pthread_v *ptr;
+  pthread_t id;
+} __pthread_idlist;
+
+int _pthread_tryjoin(pthread_t t, void **res);
+void _pthread_setnobreak(int);
+#ifdef WINPTHREAD_DBG
+void thread_print_set(int state);
+void thread_print(volatile pthread_t t, char *txt);
+#endif
+int  __pthread_shallcancel(void);
+struct _pthread_v *__pth_gpointer_locked (pthread_t id);
+
+#endif
diff --git a/libs/winpthreads/src/version.rc b/libs/winpthreads/src/version.rc
new file mode 100644
index 00000000000..43a61176377
--- /dev/null
+++ b/libs/winpthreads/src/version.rc
@@ -0,0 +1,62 @@
+/*
+   Copyright (c) 2011 mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#include <winver.h>
+#include "wpth_ver.h"
+
+#define WPTH_VERSIONINFO_NAME "WinPthreadGC\0"
+#ifdef _WIN64
+#define WPTH_VERSIONINFO_COMMENT "GNU C build -- MinGW-w64 64-bit\0"
+#else
+#define WPTH_VERSIONINFO_COMMENT "GNU C build -- MinGW-w64 32-bit\0"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+  FILEVERSION    WPTH_VERSION
+  PRODUCTVERSION WPTH_VERSION
+  FILEFLAGSMASK  VS_FFI_FILEFLAGSMASK
+  FILEFLAGS      0
+  FILEOS         VOS__WINDOWS32
+  FILETYPE       VFT_DLL
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "POSIX WinThreads for Windows\0"
+            VALUE "ProductVersion", WPTH_VERSION_STRING
+            VALUE "FileVersion", WPTH_VERSION_STRING
+            VALUE "InternalName", WPTH_VERSIONINFO_NAME
+            VALUE "OriginalFilename", WPTH_VERSIONINFO_NAME
+            VALUE "CompanyName", "MingW-W64 Project. All rights reserved.\0"
+            VALUE "LegalCopyright", "Copyright (C) MingW-W64 Project Members 2010-2011\0"
+            VALUE "Licence", "ZPL\0"
+            VALUE "Info", "http://mingw-w64.sourceforge.net/\0"
+	    VALUE "Comment", WPTH_VERSIONINFO_COMMENT
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
diff --git a/libs/winpthreads/src/winpthread_internal.h b/libs/winpthreads/src/winpthread_internal.h
new file mode 100644
index 00000000000..015e6ce9c9e
--- /dev/null
+++ b/libs/winpthreads/src/winpthread_internal.h
@@ -0,0 +1,27 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WINPTHREAD_INTERNAL_H
+#define WINPTHREAD_INTERNAL_H
+struct _pthread_v * WINPTHREAD_API __pth_gpointer_locked (pthread_t id);
+int pthread_delay_np_ms (DWORD to);
+#endif /*WINPTHREAD_INTERNAL_H*/
diff --git a/libs/winpthreads/src/wpth_ver.h b/libs/winpthreads/src/wpth_ver.h
new file mode 100644
index 00000000000..1089a612105
--- /dev/null
+++ b/libs/winpthreads/src/wpth_ver.h
@@ -0,0 +1,29 @@
+/*
+   Copyright (c) 2011-2016  mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef __WPTHREADS_VERSION__
+#define __WPTHREADS_VERSION__
+
+#define WPTH_VERSION 1,0,0,0
+#define WPTH_VERSION_STRING "1, 0, 0, 0\0"
+
+#endif
-- 
2.34.0




More information about the wine-devel mailing list