On Tue, Oct 1, 2019 at 12:17 AM Hans-Kristian Arntzen <post@arntzen-software.no> wrote:
+
+typedef struct pthread
+{
+    HANDLE thread;
+    DWORD id;
+} pthread_t;
+
+typedef struct pthread_mutex
+{
+    CRITICAL_SECTION *lock;
+} pthread_mutex_t;
+
+typedef struct pthread_cond
+{
+    CONDITION_VARIABLE *cond;
+} pthread_cond_t;
+
+struct vkd3d_pthread_wrapper_struct
+{
+    void * (*routine)(void *);
+    void *arg;
+};
+
+static DWORD WINAPI win32_thread_wrapper_routine(struct vkd3d_pthread_wrapper_struct *wrapper)
+{
+    struct vkd3d_pthread_wrapper_struct tmp = *wrapper;
+    vkd3d_free(wrapper);
+    tmp.routine(tmp.arg);
+    return 0;
+}


FWIW, ZStandard avoids complications with thread wrapping by declaring the function pointer and arg within its pthread_t struct:
https://github.com/facebook/zstd/blob/dev/lib/common/threading.h