From a49c61f1a7a062e989a6ba970353e0b0540a0fee Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sat, 8 Sep 2012 20:43:08 +0200 Subject: [PATCH] Updated TinyCThread. --- support/tinycthread.c | 90 +++++++++++++++++++++---------------------- support/tinycthread.h | 89 ++++++++++++++++++++++++++++-------------- 2 files changed, 106 insertions(+), 73 deletions(-) diff --git a/support/tinycthread.c b/support/tinycthread.c index 9bee2cb5..ced7cf3f 100644 --- a/support/tinycthread.c +++ b/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 @@ -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_ diff --git a/support/tinycthread.h b/support/tinycthread.h index 8069e3f3..1a9c805c 100644 --- a/support/tinycthread.h +++ b/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 @@ -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_ */