Skip to content
Permalink
Browse files
fix emulated/simulated time offset issue in timerfd
  • Loading branch information
robgjansen committed Jan 31, 2018
1 parent 50720e8 commit 106f711a2dceb82ea968dad7fb8863adce762585
Showing with 34 additions and 12 deletions.
  1. +6 −1 src/main/core/support/shd-definitions.h
  2. +0 −3 src/main/host/descriptor/shd-epoll.c
  3. +5 −0 src/main/host/descriptor/shd-tcp.c
  4. +23 −8 src/main/host/descriptor/shd-timer.c
@@ -70,7 +70,12 @@ typedef guint64 EmulatedTime;
* The number of nanoseconds from the epoch to January 1st, 2000 at 12:00am UTC.
* This is used to emulate to applications that we are in a recent time.
*/
#define EMULATED_TIME_OFFSET G_GUINT64_CONSTANT(946684800) * SIMTIME_ONE_SECOND
#define EMULATED_TIME_OFFSET (G_GUINT64_CONSTANT(946684800) * SIMTIME_ONE_SECOND)

/**
* Conversion from emulated time to simulated time.
*/
#define EMULATED_TIME_TO_SIMULATED_TIME(emtime) ((SimulationTime)(emtime-EMULATED_TIME_OFFSET))

#ifdef DEBUG
/**
@@ -77,7 +77,6 @@ struct _Epoll {
/* holds the wrappers for the descriptors we are watching for events */
GHashTable* watching;

SimulationTime lastWaitTime;
Process* ownerProcess;
gint osEpollDescriptor;

@@ -469,8 +468,6 @@ gint epoll_getEvents(Epoll* epoll, struct epoll_event* eventArray, gint eventArr
MAGIC_ASSERT(epoll);
utility_assert(nEvents);

epoll->lastWaitTime = worker_getCurrentTime();

/* return the available events in the eventArray, making sure not to
* overflow. the number of actual events is returned in nEvents. */
gint eventIndex = 0;
@@ -1204,6 +1204,11 @@ void tcp_getInfo(TCP* tcp, struct tcp_info *tcpinfo) {
// tcpinfo->tcpi_fackets;

/* Times. */
/* TODO not sure if these are "how long ago the events happened" or an absolute time.
* They can't possibly be since the epoch, since there are only 32 bits and we are
* returning microseconds.
* FIXME If absolute time, these should be the emulated time, not the simulated time.
*/
tcpinfo->tcpi_last_data_sent = (u_int32_t)(tcp->info.lastDataSent/SIMTIME_ONE_MICROSECOND);
tcpinfo->tcpi_last_ack_sent = (u_int32_t)(tcp->info.lastAckSent/SIMTIME_ONE_MICROSECOND);
tcpinfo->tcpi_last_data_recv = (u_int32_t)(tcp->info.lastDataReceived/SIMTIME_ONE_MICROSECOND);
@@ -115,6 +115,7 @@ gint timer_getTime(Timer* timer, struct itimerspec *curr_value) {
return -1;
}

/* returns relative time */
_timer_getCurrentTime(timer, &(curr_value->it_value));
_timer_getCurrentInterval(timer, &(curr_value->it_interval));

@@ -129,13 +130,23 @@ static void _timer_disarm(Timer* timer) {
debug("timer fd %i disarmed", timer->super.handle);
}

static SimulationTime _timer_timespecToSimTime(const struct timespec* config) {
static SimulationTime _timer_timespecToSimTime(const struct timespec* config, gboolean configTimeIsEmulatedTime) {
utility_assert(config);

SimulationTime nsecs = config->tv_sec * SIMTIME_ONE_SECOND;
nsecs += (SimulationTime) config->tv_nsec;
SimulationTime simNanoSecs = 0;

return nsecs;
if(configTimeIsEmulatedTime) {
/* the time that was passed in represents an emulated time, so we need to adjust */
EmulatedTime emNanoSecs = (EmulatedTime)(config->tv_sec * SIMTIME_ONE_SECOND);
emNanoSecs += (EmulatedTime) config->tv_nsec;
simNanoSecs = EMULATED_TIME_TO_SIMULATED_TIME(emNanoSecs);
} else {
/* the config is a relative time, so we just use simtime directly */
simNanoSecs = (SimulationTime)(config->tv_sec * SIMTIME_ONE_SECOND);
simNanoSecs += (SimulationTime) config->tv_nsec;
}

return simNanoSecs;
}

static void _timer_setCurrentTime(Timer* timer, const struct timespec* config, gint flags) {
@@ -145,8 +156,10 @@ static void _timer_setCurrentTime(Timer* timer, const struct timespec* config, g
SimulationTime now = worker_getCurrentTime();

if(flags == TFD_TIMER_ABSTIME) {
/* config time specifies an absolute time. */
timer->nextExpireTime = _timer_timespecToSimTime(config);
/* config time specifies an absolute time.
* the plugin only knows about emulated time, so we need to convert it
* back to simulated time to make sure we expire at the right time. */
timer->nextExpireTime = _timer_timespecToSimTime(config, TRUE);

/* the man page does not specify what happens if the time
* they gave us is in the past. on linux, the result is an
@@ -156,15 +169,16 @@ static void _timer_setCurrentTime(Timer* timer, const struct timespec* config, g
}
} else {
/* config time is relative to current time */
timer->nextExpireTime = now + _timer_timespecToSimTime(config);
timer->nextExpireTime = now + _timer_timespecToSimTime(config, FALSE);
}
}

static void _timer_setCurrentInterval(Timer* timer, const struct timespec* config) {
MAGIC_ASSERT(timer);
utility_assert(config);

timer->expireInterval = _timer_timespecToSimTime(config);
/* config time for intervals is always just a raw number of seconds and nanos */
timer->expireInterval = _timer_timespecToSimTime(config, FALSE);
}

static void _timer_expire(Timer* timer, gpointer data);
@@ -283,6 +297,7 @@ gint timer_setTime(Timer* timer, gint flags,

/* first get the old value if requested */
if(old_value) {
/* old value is always relative, even if TFD_TIMER_ABSTIME is set */
timer_getTime(timer, old_value);
}

0 comments on commit 106f711

Please sign in to comment.