Implemented fallback functions for pthread_timedjoin_np and

pthread_mutex_timedlock functions for systems without PTHREAD_GNU_EXT
Now returning WAIT_TIMEOUT if the operation timed out.
This commit is contained in:
Armin Novak 2013-10-23 12:09:09 +02:00
parent 0b8c7ce447
commit 7704788474

View File

@ -47,6 +47,65 @@
#include "../pipe/pipe.h"
/* Drop in replacement for the linux pthread_timedjoin_np and
* pthread_mutex_timedlock functions.
* TODO: Reduce cost penalty. */
#if !defined(HAVE_PTHREAD_GNU_EXT)
#include <pthread.h>
#include <errno.h>
static int pthread_timedjoin_np(pthread_t td, void **res,
struct timespec *timeout)
{
struct timeval timenow;
struct timespec sleepytime;
/* This is just to avoid a completely busy wait */
sleepytime.tv_sec = 0;
sleepytime.tv_nsec = 10000000; /* 10ms */
do
{
if (pthread_kill(td, 0))
return pthread_join(td, res);
nanosleep(&sleepytime, NULL);
gettimeofday (&timenow, NULL);
if (timenow.tv_sec >= timeout->tv_sec &&
(timenow.tv_usec * 1000) >= timeout->tv_nsec) {
return ETIMEDOUT;
}
}
while (TRUE);
return ETIMEDOUT;
}
static int pthread_mutex_timedlock(pthread_mutex_t *mutex,
const struct timespec *timeout)
{
struct timeval timenow;
struct timespec sleepytime;
int retcode;
/* This is just to avoid a completely busy wait */
sleepytime.tv_sec = 0;
sleepytime.tv_nsec = 10000000; /* 10ms */
while ((retcode = pthread_mutex_trylock (mutex)) == EBUSY) {
gettimeofday (&timenow, NULL);
if (timenow.tv_sec >= timeout->tv_sec &&
(timenow.tv_usec * 1000) >= timeout->tv_nsec) {
return ETIMEDOUT;
}
nanosleep (&sleepytime, NULL);
}
return retcode;
}
#endif
static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds)
{
ts->tv_sec += dwMilliseconds / 1000L;
@ -79,24 +138,30 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
if (dwMilliseconds != INFINITE)
{
#if HAVE_PTHREAD_GNU_EXT
struct timespec timeout;
/* pthread_timedjoin_np returns ETIMEDOUT in case the timeout is 0,
* so set it to the smallest value to get a proper return value. */
if (dwMilliseconds == 0)
dwMilliseconds ++;
clock_gettime(CLOCK_REALTIME, &timeout);
ts_add_ms(&timeout, dwMilliseconds);
status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout);
#else
fprintf(stderr, "[ERROR] %s: Thread timeouts not implemented.\n", __func__);
assert(0);
#endif
if (ETIMEDOUT == status)
{
return WAIT_TIMEOUT;
}
}
else
status = pthread_join(thread->thread, &thread_status);
if (status != 0)
{
fprintf(stderr, "WaitForSingleObject: pthread_join failure: [%d] %s\n",
status, strerror(status));
}
if (thread_status)
thread->dwExitCode = ((DWORD) (size_t) thread_status);
@ -108,7 +173,6 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
mutex = (WINPR_MUTEX*) Object;
#if HAVE_PTHREAD_GNU_EXT
if (dwMilliseconds != INFINITE)
{
struct timespec timeout;
@ -119,7 +183,6 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
pthread_mutex_timedlock(&mutex->mutex, &timeout);
}
else
#endif
{
pthread_mutex_lock(&mutex->mutex);
}