use monotonic time source in convar->timed_wait, and in the scheduler using it
This commit is contained in:
parent
3f310c0d1f
commit
3d5818ec38
14
configure.in
14
configure.in
|
@ -927,6 +927,20 @@ AC_TRY_COMPILE(
|
||||||
[AC_MSG_RESULT([no])]
|
[AC_MSG_RESULT([no])]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dnl check if pthread_condattr_setclock(CLOCK_MONOTONE) is supported
|
||||||
|
saved_LIBS=$LIBS
|
||||||
|
LIBS="-lpthread"
|
||||||
|
AC_MSG_CHECKING([for pthread_condattr_setclock(CLOCK_MONOTONE)])
|
||||||
|
AC_TRY_RUN(
|
||||||
|
[#include <pthread.h>
|
||||||
|
int main() { pthread_condattr_t attr;
|
||||||
|
pthread_condattr_init(&attr);
|
||||||
|
return pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);}],
|
||||||
|
[AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_CONDATTR_CLOCK_MONOTONIC])],
|
||||||
|
[AC_MSG_RESULT([no])]
|
||||||
|
)
|
||||||
|
LIBS=$saved_LIBS
|
||||||
|
|
||||||
AC_CHECK_FUNCS(prctl)
|
AC_CHECK_FUNCS(prctl)
|
||||||
|
|
||||||
AC_CHECK_HEADERS(sys/sockio.h)
|
AC_CHECK_HEADERS(sys/sockio.h)
|
||||||
|
|
|
@ -190,7 +190,7 @@ static job_requeue_t schedule(private_scheduler_t * this)
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
time_monotonic(&now);
|
||||||
|
|
||||||
if ((event = peek_event(this)) != NULL)
|
if ((event = peek_event(this)) != NULL)
|
||||||
{
|
{
|
||||||
|
@ -290,7 +290,7 @@ static void schedule_job(private_scheduler_t *this, job_t *job, u_int32_t s)
|
||||||
{
|
{
|
||||||
timeval_t tv;
|
timeval_t tv;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
time_monotonic(&tv);
|
||||||
tv.tv_sec += s;
|
tv.tv_sec += s;
|
||||||
|
|
||||||
schedule_job_tv(this, job, tv);
|
schedule_job_tv(this, job, tv);
|
||||||
|
@ -303,7 +303,7 @@ static void schedule_job_ms(private_scheduler_t *this, job_t *job, u_int32_t ms)
|
||||||
{
|
{
|
||||||
timeval_t tv, add;
|
timeval_t tv, add;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
time_monotonic(&tv);
|
||||||
add.tv_sec = ms / 1000;
|
add.tv_sec = ms / 1000;
|
||||||
add.tv_usec = (ms % 1000) * 1000;
|
add.tv_usec = (ms % 1000) * 1000;
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,9 @@ struct scheduler_t {
|
||||||
/**
|
/**
|
||||||
* Adds a event to the queue, using an absolut time.
|
* Adds a event to the queue, using an absolut time.
|
||||||
*
|
*
|
||||||
|
* The passed timeval should be calculated based on the time_monotonic()
|
||||||
|
* function.
|
||||||
|
*
|
||||||
* @param job job to schedule
|
* @param job job to schedule
|
||||||
* @param time absolut time to schedule job
|
* @param time absolut time to schedule job
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -167,7 +167,9 @@ bool mkdir_p(const char *path, mode_t mode)
|
||||||
*/
|
*/
|
||||||
time_t time_monotonic(timeval_t *tv)
|
time_t time_monotonic(timeval_t *tv)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_CLOCK_GETTIME)
|
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CONDATTR_CLOCK_MONOTONIC)
|
||||||
|
/* as we use time_monotonic() for condvar operations, we use the
|
||||||
|
* monotonic time source only if it is also supported by pthread. */
|
||||||
timespec_t ts;
|
timespec_t ts;
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||||
|
@ -179,11 +181,12 @@ time_t time_monotonic(timeval_t *tv)
|
||||||
}
|
}
|
||||||
return ts.tv_sec;
|
return ts.tv_sec;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_CLOCK_MONOTONIC */
|
#endif /* HAVE_CLOCK_MONOTONIC && HAVE_CONDATTR_CLOCK_MONOTONIC */
|
||||||
/* Fallback to non-monotonic timestamps:
|
/* Fallback to non-monotonic timestamps:
|
||||||
* On MAC OS X, creating monotonic timestamps is rather difficult. We
|
* On MAC OS X, creating monotonic timestamps is rather difficult. We
|
||||||
* could use mach_absolute_time() and catch sleep/wakeup notifications.
|
* could use mach_absolute_time() and catch sleep/wakeup notifications.
|
||||||
* We stick to the simpler (non-monotonic) gettimeofday() for now. */
|
* We stick to the simpler (non-monotonic) gettimeofday() for now.
|
||||||
|
* But keep in mind: we need the same time source here as in condvar! */
|
||||||
if (!tv)
|
if (!tv)
|
||||||
{
|
{
|
||||||
return time(NULL);
|
return time(NULL);
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct lock_profile_t {
|
||||||
/**
|
/**
|
||||||
* how long threads have waited for the lock in this mutex so far
|
* how long threads have waited for the lock in this mutex so far
|
||||||
*/
|
*/
|
||||||
struct timeval waited;
|
timeval_t waited;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* backtrace where mutex has been created
|
* backtrace where mutex has been created
|
||||||
|
@ -81,10 +81,10 @@ static void profiler_init(lock_profile_t *profile)
|
||||||
|
|
||||||
#define profiler_start(profile) { \
|
#define profiler_start(profile) { \
|
||||||
struct timeval _start, _end, _diff; \
|
struct timeval _start, _end, _diff; \
|
||||||
gettimeofday(&_start, NULL);
|
time_monotonic(&_start);
|
||||||
|
|
||||||
#define profiler_end(profile) \
|
#define profiler_end(profile) \
|
||||||
gettimeofday(&_end, NULL); \
|
time_monotonic(&_end); \
|
||||||
timersub(&_end, &_start, &_diff); \
|
timersub(&_end, &_start, &_diff); \
|
||||||
timeradd(&(profile)->waited, &_diff, &(profile)->waited); }
|
timeradd(&(profile)->waited, &_diff, &(profile)->waited); }
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex,
|
||||||
timeval_t tv;
|
timeval_t tv;
|
||||||
u_int s, ms;
|
u_int s, ms;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
time_monotonic(&tv);
|
||||||
|
|
||||||
s = timeout / 1000;
|
s = timeout / 1000;
|
||||||
ms = timeout % 1000;
|
ms = timeout % 1000;
|
||||||
|
@ -419,17 +419,23 @@ condvar_t *condvar_create(condvar_type_t type)
|
||||||
case CONDVAR_TYPE_DEFAULT:
|
case CONDVAR_TYPE_DEFAULT:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
pthread_condattr_t condattr;
|
||||||
private_condvar_t *this = malloc_thing(private_condvar_t);
|
private_condvar_t *this = malloc_thing(private_condvar_t);
|
||||||
|
|
||||||
this->public.wait = (void(*)(condvar_t*, mutex_t *mutex))_wait;
|
this->public.wait = (void(*)(condvar_t*, mutex_t *mutex))_wait;
|
||||||
this->public.timed_wait = (bool(*)(condvar_t*, mutex_t *mutex, u_int timeout))timed_wait;
|
this->public.timed_wait = (bool(*)(condvar_t*, mutex_t *mutex, u_int timeout))timed_wait;
|
||||||
this->public.timed_wait_abs = (bool(*)(condvar_t*, mutex_t *mutex, timeval_t time))timed_wait_abs;
|
this->public.timed_wait_abs = (bool(*)(condvar_t*, mutex_t *mutex, timeval_t time))timed_wait_abs;
|
||||||
this->public.signal = (void(*)(condvar_t*))_signal;
|
this->public.signal = (void(*)(condvar_t*))_signal;
|
||||||
this->public.broadcast = (void(*)(condvar_t*))broadcast;
|
this->public.broadcast = (void(*)(condvar_t*))broadcast;
|
||||||
this->public.destroy = (void(*)(condvar_t*))condvar_destroy;
|
this->public.destroy = (void(*)(condvar_t*))condvar_destroy;
|
||||||
|
|
||||||
pthread_cond_init(&this->condvar, NULL);
|
pthread_condattr_init(&condattr);
|
||||||
|
#ifdef HAVE_CONDATTR_CLOCK_MONOTONIC
|
||||||
|
pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
|
||||||
|
#endif
|
||||||
|
pthread_cond_init(&this->condvar, &condattr);
|
||||||
|
pthread_condattr_destroy(&condattr);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,11 +98,11 @@ struct mutex_t {
|
||||||
* Release the lock on the mutex.
|
* Release the lock on the mutex.
|
||||||
*/
|
*/
|
||||||
void (*unlock)(mutex_t *this);
|
void (*unlock)(mutex_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a mutex instance.
|
* Destroy a mutex instance.
|
||||||
*/
|
*/
|
||||||
void (*destroy)(mutex_t *this);
|
void (*destroy)(mutex_t *this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,12 +128,15 @@ struct condvar_t {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait on a condvar until it gets signalized, or times out.
|
* Wait on a condvar until it gets signalized, or times out.
|
||||||
*
|
*
|
||||||
|
* The passed timeval should be calculated based on the time_monotonic()
|
||||||
|
* function.
|
||||||
|
*
|
||||||
* @param mutex mutex to release while waiting
|
* @param mutex mutex to release while waiting
|
||||||
* @param time absolute time until timeout
|
* @param tv absolute time until timeout
|
||||||
* @return TRUE if timed out, FALSE otherwise
|
* @return TRUE if timed out, FALSE otherwise
|
||||||
*/
|
*/
|
||||||
bool (*timed_wait_abs)(condvar_t *this, mutex_t *mutex, timeval_t timeout);
|
bool (*timed_wait_abs)(condvar_t *this, mutex_t *mutex, timeval_t tv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wake up a single thread in a condvar.
|
* Wake up a single thread in a condvar.
|
||||||
|
|
Loading…
Reference in New Issue