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:
parent
0b8c7ce447
commit
7704788474
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user