2
0
Camilla Berglund 13 жил өмнө
parent
commit
a49c61f1a7
2 өөрчлөгдсөн 106 нэмэгдсэн , 73 устгасан
  1. 45 45
      support/tinycthread.c
  2. 61 28
      support/tinycthread.h

+ 45 - 45
support/tinycthread.c

@@ -21,13 +21,6 @@ freely, subject to the following restrictions:
     distribution.
 */
 
-/* Activate some POSIX functionality (e.g. recursive mutexes) */
-#define _GNU_SOURCE
-#if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 500)
-  #undef _XOPEN_SOURCE
-  #define _XOPEN_SOURCE 500
-#endif
-
 #include "tinycthread.h"
 #include <stdlib.h>
 
@@ -99,9 +92,11 @@ int mtx_lock(mtx_t *mtx)
 #endif
 }
 
-int mtx_timedlock(mtx_t *mtx, const xtime *xt)
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
 {
   /* FIXME! */
+  (void)mtx;
+  (void)ts;
   return thrd_error;
 }
 
@@ -290,21 +285,21 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx)
 #endif
 }
 
-int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
 {
 #if defined(_TTHREAD_WIN32_)
-  xtime now;
-  DWORD delta;
-  xtime_get(&now, TIME_UTC);
-  delta = (xt->sec - now.sec) * 1000 +
-          (xt->nsec - now.nsec + 500000) / 1000000;
-  return _cnd_timedwait_win32(cond, mtx, delta);
+  struct timespec now;
+  if (clock_gettime(TIME_UTC, &now) == 0)
+  {
+    DWORD delta = (ts->tv_sec - now.tv_sec) * 1000 +
+                  (ts->tv_nsec - now.tv_nsec + 500000) / 1000000;
+    return _cnd_timedwait_win32(cond, mtx, delta);
+  }
+  else
+    return thrd_error;
 #else
-  struct timespec ts;
   int ret;
-  ts.tv_sec = xt->sec;
-  ts.tv_nsec = xt->nsec;
-  ret = pthread_cond_timedwait(cond, mtx, &ts);
+  ret = pthread_cond_timedwait(cond, mtx, ts);
   if (ret == ETIMEDOUT)
   {
     return thrd_timeout;
@@ -322,9 +317,9 @@ typedef struct {
 
 /* Thread wrapper function. */
 #if defined(_TTHREAD_WIN32_)
-unsigned WINAPI _thrd_wrapper_function(void * aArg)
+static unsigned WINAPI _thrd_wrapper_function(void * aArg)
 #elif defined(_TTHREAD_POSIX_)
-void * _thrd_wrapper_function(void * aArg)
+static void * _thrd_wrapper_function(void * aArg)
 #endif
 {
   thrd_start_t fun;
@@ -401,6 +396,7 @@ thrd_t thrd_current(void)
 int thrd_detach(thrd_t thr)
 {
   /* FIXME! */
+  (void)thr;
   return thrd_error;
 }
 
@@ -460,9 +456,9 @@ int thrd_join(thrd_t thr, int *res)
   return thrd_success;
 }
 
-void thrd_sleep(const xtime *xt)
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
 {
-  xtime now;
+  struct timespec now;
 #if defined(_TTHREAD_WIN32_)
   DWORD delta;
 #else
@@ -470,20 +466,21 @@ void thrd_sleep(const xtime *xt)
 #endif
 
   /* Get the current time */
-  xtime_get(&now, TIME_UTC);
+  if (clock_gettime(TIME_UTC, &now) != 0)
+    return -2;  // FIXME: Some specific error code?
 
 #if defined(_TTHREAD_WIN32_)
   /* Delta in milliseconds */
-  delta = (xt->sec - now.sec) * 1000 +
-          (xt->nsec - now.nsec + 500000) / 1000000;
+  delta = (time_point->tv_sec - now.tv_sec) * 1000 +
+          (time_point->tv_nsec - now.tv_nsec + 500000) / 1000000;
   if (delta > 0)
   {
     Sleep(delta);
   }
 #else
   /* Delta in microseconds */
-  delta = (xt->sec - now.sec) * 1000000L +
-          (xt->nsec - now.nsec + 500L) / 1000L;
+  delta = (time_point->tv_sec - now.tv_sec) * 1000000L +
+          (time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
 
   /* On some systems, the usleep argument must be < 1000000 */
   while (delta > 999999L)
@@ -496,6 +493,14 @@ void thrd_sleep(const xtime *xt)
     usleep((useconds_t)delta);
   }
 #endif
+
+  /* We don't support waking up prematurely (yet) */
+  if (remaining)
+  {
+    remaining->tv_sec = 0;
+    remaining->tv_nsec = 0;
+  }
+  return 0;
 }
 
 void thrd_yield(void)
@@ -563,26 +568,21 @@ int tss_set(tss_t key, void *val)
   return thrd_success;
 }
 
-int xtime_get(xtime *xt, int base)
+#if defined(_TTHREAD_EMULATE_CLOCK_GETTIME_)
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts)
 {
-  if (base == TIME_UTC)
-  {
 #if defined(_TTHREAD_WIN32_)
-    struct _timeb tb;
-    _ftime(&tb);
-    xt->sec = (time_t)tb.time;
-    xt->nsec = 1000000 * (long)tb.millitm;
+  struct _timeb tb;
+  _ftime(&tb);
+  ts->tv_sec = (time_t)tb.time;
+  ts->tv_nsec = 1000000L * (long)tb.millitm;
 #else
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    xt->sec = (time_t)tv.tv_sec;
-    xt->nsec = 1000 * (long)tv.tv_usec;
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  ts->tv_sec = (time_t)tv.tv_sec;
+  ts->tv_nsec = 1000L * (long)tv.tv_usec;
 #endif
-    return base;
-  }
-  else
-  {
-    return 0;
-  }
+  return 0;
 }
+#endif // _TTHREAD_EMULATE_CLOCK_GETTIME_
 

+ 61 - 28
support/tinycthread.h

@@ -57,6 +57,22 @@ freely, subject to the following restrictions:
   #define _TTHREAD_PLATFORM_DEFINED_
 #endif
 
+/* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
+#if defined(_TTHREAD_POSIX_)
+  #undef _FEATURES_H
+  #if !defined(_GNU_SOURCE)
+    #define _GNU_SOURCE
+  #endif
+  #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
+    #undef _POSIX_C_SOURCE
+    #define _POSIX_C_SOURCE 199309L
+  #endif
+  #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
+    #undef _XOPEN_SOURCE
+    #define _XOPEN_SOURCE 500
+  #endif
+#endif
+
 /* Generic includes */
 #include <time.h>
 
@@ -75,10 +91,42 @@ freely, subject to the following restrictions:
   #endif
 #endif
 
+/* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
+   it's quite likely that libc does not support it either. Hence, fall back to
+   the only other supported time specifier: CLOCK_REALTIME (and if that fails,
+   we're probably emulating clock_gettime anyway, so anything goes). */
+#ifndef TIME_UTC
+  #ifdef CLOCK_REALTIME
+    #define TIME_UTC CLOCK_REALTIME
+  #else
+    #define TIME_UTC 0
+  #endif
+#endif
+
+/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
+#if defined(_TTHREAD_WIN32_)
+#define _TTHREAD_EMULATE_CLOCK_GETTIME_
+/* Emulate struct timespec */
+struct _ttherad_timespec {
+  time_t tv_sec;
+  long   tv_nsec;
+};
+#define timespec _ttherad_timespec
+
+/* Emulate clockid_t */
+typedef int _tthread_clockid_t;
+#define clockid_t _tthread_clockid_t
+
+/* Emulate clock_gettime */
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
+#define clock_gettime _tthread_clock_gettime
+#endif
+
+
 /** TinyCThread version (major number). */
 #define TINYCTHREAD_VERSION_MAJOR 1
 /** TinyCThread version (minor number). */
-#define TINYCTHREAD_VERSION_MINOR 0
+#define TINYCTHREAD_VERSION_MINOR 1
 /** TinyCThread version (full version). */
 #define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
 
@@ -101,7 +149,7 @@ freely, subject to the following restrictions:
 * @hideinitializer
 */
 
-/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 or */
+/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
 #if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
  #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
   #define _Thread_local __thread
@@ -126,12 +174,6 @@ freely, subject to the following restrictions:
 #define mtx_try       4
 #define mtx_recursive 8
 
-/** Time specification */
-typedef struct {
-  time_t sec;   /**< Seconds */
-  long nsec;    /**< Nanoseconds */
-} xtime;
-
 /* Mutex */
 #if defined(_TTHREAD_WIN32_)
 typedef struct {
@@ -174,7 +216,7 @@ int mtx_lock(mtx_t *mtx);
 
 /** NOT YET IMPLEMENTED.
 */
-int mtx_timedlock(mtx_t *mtx, const xtime *xt);
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
 
 /** Try to lock the given mutex.
 * The specified mutex shall support either test and return or timeout. If the
@@ -260,7 +302,7 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx);
 * specified in the call was reached without acquiring the requested resource, or
 * @ref thrd_error if the request could not be honored.
 */
-int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt);
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
 
 /* Thread */
 #if defined(_TTHREAD_WIN32_)
@@ -326,11 +368,16 @@ void thrd_exit(int res);
 int thrd_join(thrd_t thr, int *res);
 
 /** Put the calling thread to sleep.
-* Suspend execution of the calling thread until after the time specified by the
-* xtime object.
-* @param xt A point in time at which the thread will resume (absolute time).
+* Suspend execution of the calling thread.
+* @param time_point A point in time at which the thread will resume (absolute time).
+* @param remaining If non-NULL, this parameter will hold the remaining time until
+*                  time_point upon return. This will typically be zero, but if
+*                  the thread was woken up by a signal that is not ignored before
+*                  time_point was reached @c remaining will hold a positive
+*                  time.
+* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
 */
-void thrd_sleep(const xtime *xt);
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
 
 /** Yield execution to another thread.
 * Permit other threads to run, even if the current thread would ordinarily
@@ -385,20 +432,6 @@ void *tss_get(tss_t key);
 */
 int tss_set(tss_t key, void *val);
 
-/* Timing */
-enum
-{
-  TIME_UTC = 1
-};
-
-/** Get the current time.
-* Set the xtime object to hold the current time based on the given time base.
-* @param xt Will be filled out with the current time.
-* @param base Time base (must be @c TIME_UTC).
-* @return The non-zero value @c base if the function is successful, otherwise
-* it returns zero.
-*/
-int xtime_get(xtime *xt, int base);
 
 #endif /* _TINYTHREAD_H_ */