threads: update for late C11 changes
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Sun, 22 Oct 2017 15:38:45 +0000 (17:38 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Thu, 9 Nov 2017 10:57:22 +0000 (11:57 +0100)
C11 threads were changed to use struct timespec instead of xtime, and
thrd_sleep got a second argument.

See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1554.htm and
http://en.cppreference.com/w/c/thread/{thrd_sleep,cnd_timedwait,mtx_timedlock}

Note that cnd_timedwait is spec'd to be relative to TIME_UTC / CLOCK_REALTIME.

v2: Fix Windows build errors. Tested with a default Appveyor config
    that uses Visual Studio 2013. Judging from Brian's email and
    random internet sources, Visual Studio 2015 does have timespec
    and timespec_get, hence the _MSC_VER-based guard which I have
    not tested.

Cc: Jose Fonseca <jfonseca@vmware.com>
Cc: Brian Paul <brianp@vmware.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com> (v1)
include/c11/threads.h
include/c11/threads_posix.h
include/c11/threads_win32.h
src/egl/drivers/dri2/egl_dri2.c

index 573348d8091777c340b18ecd986c972339b7eaa3..3c3f23a8ab8e79d97578fb17c48b45338cb3a3b0 100644 (file)
@@ -30,9 +30,6 @@
 #define EMULATED_THREADS_H_INCLUDED_
 
 #include <time.h>
-#ifdef _MSC_VER
-#include <thr/xtimec.h>  // for xtime
-#endif
 
 #ifndef TIME_UTC
 #define TIME_UTC 1
 typedef void (*tss_dtor_t)(void*);
 typedef int (*thrd_start_t)(void*);
 
-#ifndef _MSC_VER
-struct xtime {
-    time_t sec;
-    long nsec;
-};
-typedef struct xtime xtime;
-#endif
-
 
 /*-------------------- enumeration constants --------------------*/
 enum {
index 43e803ee8d18cabbeefad73d132c16ef87f0af78..7bf6a0f6ef6f053aaee3e9e234908ddfae4adbb5 100644 (file)
@@ -132,19 +132,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)
 {
-    struct timespec abs_time;
     int rt;
 
     assert(mtx != NULL);
     assert(cond != NULL);
-    assert(xt != NULL);
+    assert(abs_time != NULL);
 
-    abs_time.tv_sec = xt->sec;
-    abs_time.tv_nsec = xt->nsec;
-
-    rt = pthread_cond_timedwait(cond, mtx, &abs_time);
+    rt = pthread_cond_timedwait(cond, mtx, abs_time);
     if (rt == ETIMEDOUT)
         return thrd_busy;
     return (rt == 0) ? thrd_success : thrd_error;
@@ -235,24 +231,21 @@ thrd_yield(void);
 
 // 7.25.4.4
 static inline int
-mtx_timedlock(mtx_t *mtx, const xtime *xt)
+mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
 {
     assert(mtx != NULL);
-    assert(xt != NULL);
+    assert(ts != NULL);
 
     {
 #ifdef EMULATED_THREADS_USE_NATIVE_TIMEDLOCK
-    struct timespec ts;
     int rt;
-    ts.tv_sec = xt->sec;
-    ts.tv_nsec = xt->nsec;
-    rt = pthread_mutex_timedlock(mtx, &ts);
+    rt = pthread_mutex_timedlock(mtx, ts);
     if (rt == 0)
         return thrd_success;
     return (rt == ETIMEDOUT) ? thrd_busy : thrd_error;
 #else
     time_t expire = time(NULL);
-    expire += xt->sec;
+    expire += ts->tv_sec;
     while (mtx_trylock(mtx) != thrd_success) {
         time_t now = time(NULL);
         if (expire < now)
@@ -342,13 +335,10 @@ 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)
 {
-    struct timespec req;
-    assert(xt);
-    req.tv_sec = xt->sec;
-    req.tv_nsec = xt->nsec;
-    nanosleep(&req, NULL);
+    assert(time_point != NULL);
+    nanosleep(time_point, remaining);
 }
 
 // 7.25.5.8
@@ -392,14 +382,15 @@ tss_set(tss_t key, void *val)
 
 /*-------------------- 7.25.7 Time functions --------------------*/
 // 7.25.6.1
+#if 0
 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;
+        clock_gettime(CLOCK_REALTIME, ts);
         return base;
     }
     return 0;
 }
+#endif
index af7df4b9ef5759dcb85ef880fa5f2553597169e0..77d923aaf492e91feee278558216485350543b85 100644 (file)
@@ -75,6 +75,17 @@ Configuration macro:
 #error EMULATED_THREADS_USE_NATIVE_CV requires _WIN32_WINNT>=0x0600
 #endif
 
+/* Visual Studio 2015 and later */
+#if _MSC_VER >= 1900
+#define HAVE_TIMESPEC
+#endif
+
+#ifndef HAVE_TIMESPEC
+struct timespec {
+    time_t tv_sec;
+    long tv_nsec;
+};
+#endif
 
 /*---------------------------- macros ----------------------------*/
 #ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
@@ -146,9 +157,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 / 1000000L));
+    return (DWORD)((ts->tv_sec * 1000U) + (ts->tv_nsec / 1000000L));
 }
 
 #ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
@@ -206,7 +217,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;
@@ -219,7 +230,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);
@@ -378,15 +389,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
 }
 
@@ -438,12 +449,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)
@@ -579,10 +590,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
@@ -633,14 +645,16 @@ tss_set(tss_t key, void *val)
 
 /*-------------------- 7.25.7 Time functions --------------------*/
 // 7.25.6.1
+#ifndef HAVE_TIMESPEC
 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
index b486be748735b7adf7856f96022c4307a00f2c43..9e0feea9869db0b7c3a4ae4b499143fc475b7ec7 100644 (file)
@@ -3064,10 +3064,6 @@ dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
    struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
    unsigned wait_flags = 0;
 
-   /* timespecs for cnd_timedwait */
-   struct timespec current;
-   xtime expire;
-
    EGLint ret = EGL_CONDITION_SATISFIED_KHR;
 
    /* The EGL_KHR_fence_sync spec states:
@@ -3108,19 +3104,25 @@ dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
       } else {
          /* if reusable sync has not been yet signaled */
          if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) {
+            /* timespecs for cnd_timedwait */
+            struct timespec current;
+            struct timespec expire;
+
+            /* We override the clock to monotonic when creating the condition
+             * variable. */
             clock_gettime(CLOCK_MONOTONIC, &current);
 
             /* calculating when to expire */
-            expire.nsec = timeout % 1000000000L;
-            expire.sec = timeout / 1000000000L;
+            expire.tv_nsec = timeout % 1000000000L;
+            expire.tv_sec = timeout / 1000000000L;
 
-            expire.nsec += current.tv_nsec;
-            expire.sec += current.tv_sec;
+            expire.tv_nsec += current.tv_nsec;
+            expire.tv_sec += current.tv_sec;
 
             /* expire.nsec now is a number between 0 and 1999999998 */
-            if (expire.nsec > 999999999L) {
-               expire.sec++;
-               expire.nsec -= 1000000000L;
+            if (expire.tv_nsec > 999999999L) {
+               expire.tv_sec++;
+               expire.tv_nsec -= 1000000000L;
             }
 
             mtx_lock(&dri2_sync->mutex);