freedreno/cffdec: Stop open-coding enum parsing
[mesa.git] / include / c11 / threads_win32.h
index 5a63e90b3a711c451a850ed2a75d6b0c5ae7ca2a..326cfc467754624bb9072e77ed127bc97f689645 100644 (file)
@@ -3,12 +3,36 @@
  *
  * (C) Copyright yohhoy 2012.
  * Distributed under the Boost Software License, Version 1.0.
- * (See copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare [[derivative work]]s of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ *
+ * 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  */
+#ifndef assert
 #include <assert.h>
+#endif
 #include <limits.h>
 #include <errno.h>
 #include <process.h>  // MSVCRT
+#include <stdlib.h>
 
 /*
 Configuration macro:
@@ -51,6 +75,10 @@ Configuration macro:
 #error EMULATED_THREADS_USE_NATIVE_CV requires _WIN32_WINNT>=0x0600
 #endif
 
+/* Visual Studio 2015 and later */
+#ifdef _MSC_VER
+#define HAVE_TIMESPEC_GET
+#endif
 
 /*---------------------------- macros ----------------------------*/
 #ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
@@ -122,9 +150,9 @@ static unsigned __stdcall impl_thrd_routine(void *p)
     return (unsigned)code;
 }
 
-static DWORD impl_xtime2msec(const xtime *xt)
+static DWORD impl_timespec2msec(const struct timespec *ts)
 {
-    return (DWORD)((xt->sec * 1000u) + (xt->nsec / 1000));
+    return (DWORD)((ts->tv_sec * 1000U) + (ts->tv_nsec / 1000000L));
 }
 
 #ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
@@ -182,7 +210,7 @@ static void impl_cond_do_signal(cnd_t *cond, int broadcast)
         ReleaseSemaphore(cond->sem_queue, nsignal, NULL);
 }
 
-static int impl_cond_do_wait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
+static int impl_cond_do_wait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
 {
     int nleft = 0;
     int ngone = 0;
@@ -195,7 +223,7 @@ static int impl_cond_do_wait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
 
     mtx_unlock(mtx);
 
-    w = WaitForSingleObject(cond->sem_queue, xt ? impl_xtime2msec(xt) : INFINITE);
+    w = WaitForSingleObject(cond->sem_queue, ts ? impl_timespec2msec(ts) : INFINITE);
     timeout = (w == WAIT_TIMEOUT);
  
     EnterCriticalSection(&cond->monitor);
@@ -272,7 +300,7 @@ static void impl_tss_dtor_invoke()
 static inline void
 call_once(once_flag *flag, void (*func)(void))
 {
-    assert(!flag && !func);
+    assert(flag && func);
 #ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
     {
     struct impl_call_once_param param;
@@ -354,15 +382,15 @@ cnd_signal(cnd_t *cond)
 
 // 7.25.3.5
 static inline int
-cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
+cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *abs_time)
 {
-    if (!cond || !mtx || !xt) return thrd_error;
+    if (!cond || !mtx || !abs_time) return thrd_error;
 #ifdef EMULATED_THREADS_USE_NATIVE_CV
-    if (SleepConditionVariableCS(&cond->condvar, mtx, impl_xtime2msec(xt)))
+    if (SleepConditionVariableCS(&cond->condvar, mtx, impl_timespec2msec(abs_time)))
         return thrd_success;
     return (GetLastError() == ERROR_TIMEOUT) ? thrd_busy : thrd_error;
 #else
-    return impl_cond_do_wait(cond, mtx, xt);
+    return impl_cond_do_wait(cond, mtx, abs_time);
 #endif
 }
 
@@ -414,12 +442,12 @@ mtx_lock(mtx_t *mtx)
 
 // 7.25.4.4
 static inline int
-mtx_timedlock(mtx_t *mtx, const xtime *xt)
+mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
 {
     time_t expire, now;
-    if (!mtx || !xt) return thrd_error;
+    if (!mtx || !ts) return thrd_error;
     expire = time(NULL);
-    expire += xt->sec;
+    expire += ts->tv_sec;
     while (mtx_trylock(mtx) != thrd_success) {
         now = time(NULL);
         if (expire < now)
@@ -470,12 +498,46 @@ thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
     return thrd_success;
 }
 
+#if 0
 // 7.25.5.2
 static inline thrd_t
 thrd_current(void)
 {
-    return GetCurrentThread();
+    HANDLE hCurrentThread;
+    BOOL bRet;
+
+    /* GetCurrentThread() returns a pseudo-handle, which we need
+     * to pass to DuplicateHandle(). Only the resulting handle can be used
+     * from other threads.
+     *
+     * Note that neither handle can be compared to the one by thread_create.
+     * Only the thread IDs - as returned by GetThreadId() and GetCurrentThreadId()
+     * can be compared directly.
+     *
+     * Other potential solutions would be:
+     * - define thrd_t as a thread Ids, but this would mean we'd need to OpenThread for many operations
+     * - use malloc'ed memory for thrd_t. This would imply using TLS for current thread.
+     *
+     * Neither is particularly nice.
+     *
+     * Life would be much easier if C11 threads had different abstractions for
+     * threads and thread IDs, just like C++11 threads does...
+     */
+
+    bRet = DuplicateHandle(GetCurrentProcess(), // source process (pseudo) handle
+                           GetCurrentThread(), // source (pseudo) handle
+                           GetCurrentProcess(), // target process
+                           &hCurrentThread, // target handle
+                           0,
+                           FALSE,
+                           DUPLICATE_SAME_ACCESS);
+    assert(bRet);
+    if (!bRet) {
+       hCurrentThread = GetCurrentThread();
+    }
+    return hCurrentThread;
 }
+#endif
 
 // 7.25.5.3
 static inline int
@@ -489,7 +551,7 @@ thrd_detach(thrd_t thr)
 static inline int
 thrd_equal(thrd_t thr0, thrd_t thr1)
 {
-    return (thr0 == thr1);
+    return GetThreadId(thr0) == GetThreadId(thr1);
 }
 
 // 7.25.5.5
@@ -521,10 +583,11 @@ thrd_join(thrd_t thr, int *res)
 
 // 7.25.5.7
 static inline void
-thrd_sleep(const xtime *xt)
+thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
 {
-    assert(xt);
-    Sleep(impl_xtime2msec(xt));
+    assert(time_point);
+    assert(!remaining); /* not implemented */
+    Sleep(impl_timespec2msec(time_point));
 }
 
 // 7.25.5.8
@@ -575,14 +638,16 @@ tss_set(tss_t key, void *val)
 
 /*-------------------- 7.25.7 Time functions --------------------*/
 // 7.25.6.1
+#ifndef HAVE_TIMESPEC_GET
 static inline int
-xtime_get(xtime *xt, int base)
+timespec_get(struct timespec *ts, int base)
 {
-    if (!xt) return 0;
+    if (!ts) return 0;
     if (base == TIME_UTC) {
-        xt->sec = time(NULL);
-        xt->nsec = 0;
+        ts->tv_sec = time(NULL);
+        ts->tv_nsec = 0;
         return base;
     }
     return 0;
 }
+#endif