src: replace clock_gettime()/gettimeofday() with g_get_real_time()

g_get_real_time() returns the time since epoch in microseconds.
It uses gettimeofday() internally while libvirt used clock_gettime
because it is declared async signal safe. In practice gettimeofday
is also async signal safe *provided* the timezone parameter is
NULL. This is indeed the case in g_get_real_time().

Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2019-12-20 16:19:30 +00:00
parent f7df985684
commit f5e9bdb87f
9 changed files with 39 additions and 105 deletions

View File

@ -73,13 +73,10 @@ virDomainMomentDefDispose(void *obj)
int int
virDomainMomentDefPostParse(virDomainMomentDefPtr def) virDomainMomentDefPostParse(virDomainMomentDefPtr def)
{ {
struct timeval tv; def->creationTime = g_get_real_time() / (1000*1000);
gettimeofday(&tv, NULL);
if (!def->name) if (!def->name)
def->name = g_strdup_printf("%lld", (long long)tv.tv_sec); def->name = g_strdup_printf("%lld", def->creationTime);
def->creationTime = tv.tv_sec;
return 0; return 0;
} }

View File

@ -235,9 +235,9 @@ libxlTimeoutRegisterEventHook(void *priv,
void *xl_priv) void *xl_priv)
{ {
libxlOSEventHookInfoPtr info; libxlOSEventHookInfoPtr info;
struct timeval now; gint64 now_us;
struct timeval res; gint64 abs_us;
static struct timeval zero; gint64 res_ms;
int timeout; int timeout;
if (VIR_ALLOC(info) < 0) if (VIR_ALLOC(info) < 0)
@ -246,15 +246,16 @@ libxlTimeoutRegisterEventHook(void *priv,
info->ctx = priv; info->ctx = priv;
info->xl_priv = xl_priv; info->xl_priv = xl_priv;
gettimeofday(&now, NULL); now_us = g_get_real_time();
timersub(&abs_t, &now, &res); abs_us = (abs_t.tv_sec * (1000LL*1000LL)) + abs_t.tv_usec;
/* Ensure timeout is not overflowed */ if (now_us >= abs_us) {
if (timercmp(&res, &zero, <)) {
timeout = 0; timeout = 0;
} else if (res.tv_sec > INT_MAX / 1000) {
timeout = INT_MAX;
} else { } else {
timeout = res.tv_sec * 1000 + (res.tv_usec + 999) / 1000; res_ms = (abs_us - now_us) / 1000;
if (res_ms > INT_MAX)
timeout = INT_MAX;
else
timeout = res_ms;
} }
info->id = virEventAddTimeout(timeout, libxlTimerCallback, info->id = virEventAddTimeout(timeout, libxlTimerCallback,
info, libxlOSEventHookInfoFree); info, libxlOSEventHookInfoFree);

View File

@ -715,7 +715,6 @@ qemuBackupBegin(virDomainObjPtr vm,
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver); g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver);
g_autoptr(virDomainBackupDef) def = NULL; g_autoptr(virDomainBackupDef) def = NULL;
g_autofree char *suffix = NULL; g_autofree char *suffix = NULL;
struct timeval tv;
bool pull = false; bool pull = false;
virDomainMomentObjPtr chk = NULL; virDomainMomentObjPtr chk = NULL;
g_autoptr(virDomainCheckpointDef) chkdef = NULL; g_autoptr(virDomainCheckpointDef) chkdef = NULL;
@ -749,8 +748,8 @@ qemuBackupBegin(virDomainObjPtr vm,
suffix = g_strdup(chkdef->parent.name); suffix = g_strdup(chkdef->parent.name);
} else { } else {
gettimeofday(&tv, NULL); gint64 now_us = g_get_real_time();
suffix = g_strdup_printf("%lld", (long long)tv.tv_sec); suffix = g_strdup_printf("%lld", (long long)now_us/(1000*1000));
} }
if (def->type == VIR_DOMAIN_BACKUP_TYPE_PULL) if (def->type == VIR_DOMAIN_BACKUP_TYPE_PULL)

View File

@ -2052,29 +2052,19 @@ testDomainGetHostname(virDomainPtr domain,
static int testDomainGetInfo(virDomainPtr domain, static int testDomainGetInfo(virDomainPtr domain,
virDomainInfoPtr info) virDomainInfoPtr info)
{ {
struct timeval tv;
virDomainObjPtr privdom; virDomainObjPtr privdom;
int ret = -1;
if (!(privdom = testDomObjFromDomain(domain))) if (!(privdom = testDomObjFromDomain(domain)))
return -1; return -1;
if (gettimeofday(&tv, NULL) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("getting time of day"));
goto cleanup;
}
info->state = virDomainObjGetState(privdom, NULL); info->state = virDomainObjGetState(privdom, NULL);
info->memory = privdom->def->mem.cur_balloon; info->memory = privdom->def->mem.cur_balloon;
info->maxMem = virDomainDefGetMemoryTotal(privdom->def); info->maxMem = virDomainDefGetMemoryTotal(privdom->def);
info->nrVirtCpu = virDomainDefGetVcpus(privdom->def); info->nrVirtCpu = virDomainDefGetVcpus(privdom->def);
info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); info->cpuTime = g_get_real_time() * 1000;
ret = 0;
cleanup:
virDomainObjEndAPI(&privdom); virDomainObjEndAPI(&privdom);
return ret; return 0;
} }
static int static int
@ -2933,7 +2923,6 @@ static int testDomainGetVcpus(virDomainPtr domain,
size_t i; size_t i;
int hostcpus; int hostcpus;
int ret = -1; int ret = -1;
struct timeval tv;
unsigned long long statbase; unsigned long long statbase;
virBitmapPtr allcpumap = NULL; virBitmapPtr allcpumap = NULL;
@ -2948,13 +2937,7 @@ static int testDomainGetVcpus(virDomainPtr domain,
def = privdom->def; def = privdom->def;
if (gettimeofday(&tv, NULL) < 0) { statbase = g_get_real_time();
virReportSystemError(errno,
"%s", _("getting time of day"));
goto cleanup;
}
statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec;
hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo); hostcpus = VIR_NODEINFO_MAXCPUS(privconn->nodeInfo);
if (!(allcpumap = virBitmapNew(hostcpus))) if (!(allcpumap = virBitmapNew(hostcpus)))
@ -4963,7 +4946,6 @@ static int testDomainBlockStats(virDomainPtr domain,
virDomainBlockStatsPtr stats) virDomainBlockStatsPtr stats)
{ {
virDomainObjPtr privdom; virDomainObjPtr privdom;
struct timeval tv;
unsigned long long statbase; unsigned long long statbase;
int ret = -1; int ret = -1;
@ -4985,19 +4967,13 @@ static int testDomainBlockStats(virDomainPtr domain,
goto error; goto error;
} }
if (gettimeofday(&tv, NULL) < 0) {
virReportSystemError(errno,
"%s", _("getting time of day"));
goto error;
}
/* No significance to these numbers, just enough to mix it up*/ /* No significance to these numbers, just enough to mix it up*/
statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec; statbase = g_get_real_time();
stats->rd_req = statbase / 10; stats->rd_req = statbase / 10;
stats->rd_bytes = statbase / 20; stats->rd_bytes = statbase / 20;
stats->wr_req = statbase / 30; stats->wr_req = statbase / 30;
stats->wr_bytes = statbase / 40; stats->wr_bytes = statbase / 40;
stats->errs = tv.tv_sec / 2; stats->errs = statbase / (1000LL * 1000LL * 2);
ret = 0; ret = 0;
error: error:
@ -5136,7 +5112,6 @@ testDomainInterfaceStats(virDomainPtr domain,
virDomainInterfaceStatsPtr stats) virDomainInterfaceStatsPtr stats)
{ {
virDomainObjPtr privdom; virDomainObjPtr privdom;
struct timeval tv;
unsigned long long statbase; unsigned long long statbase;
virDomainNetDefPtr net = NULL; virDomainNetDefPtr net = NULL;
int ret = -1; int ret = -1;
@ -5151,22 +5126,16 @@ testDomainInterfaceStats(virDomainPtr domain,
if (!(net = virDomainNetFind(privdom->def, device))) if (!(net = virDomainNetFind(privdom->def, device)))
goto error; goto error;
if (gettimeofday(&tv, NULL) < 0) {
virReportSystemError(errno,
"%s", _("getting time of day"));
goto error;
}
/* No significance to these numbers, just enough to mix it up*/ /* No significance to these numbers, just enough to mix it up*/
statbase = (tv.tv_sec * 1000UL * 1000UL) + tv.tv_usec; statbase = g_get_real_time();
stats->rx_bytes = statbase / 10; stats->rx_bytes = statbase / 10;
stats->rx_packets = statbase / 100; stats->rx_packets = statbase / 100;
stats->rx_errs = tv.tv_sec / 1; stats->rx_errs = statbase / (1000LL * 1000LL * 1);
stats->rx_drop = tv.tv_sec / 2; stats->rx_drop = statbase / (1000LL * 1000LL * 2);
stats->tx_bytes = statbase / 20; stats->tx_bytes = statbase / 20;
stats->tx_packets = statbase / 110; stats->tx_packets = statbase / 110;
stats->tx_errs = tv.tv_sec / 3; stats->tx_errs = statbase / (1000LL * 1000LL * 3);
stats->tx_drop = tv.tv_sec / 4; stats->tx_drop = statbase / (1000LL * 1000LL * 4);
ret = 0; ret = 0;
error: error:

View File

@ -43,11 +43,6 @@
VIR_LOG_INIT("util.time"); VIR_LOG_INIT("util.time");
/* We prefer clock_gettime if available because that is officially
* async signal safe according to POSIX. Many platforms lack it
* though, so fallback to gettimeofday everywhere else
*/
/** /**
* virTimeMillisNowRaw: * virTimeMillisNowRaw:
* @now: filled with current time in milliseconds * @now: filled with current time in milliseconds
@ -59,22 +54,7 @@ VIR_LOG_INIT("util.time");
*/ */
int virTimeMillisNowRaw(unsigned long long *now) int virTimeMillisNowRaw(unsigned long long *now)
{ {
#ifdef HAVE_CLOCK_GETTIME *now = g_get_real_time() / 1000;
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
return -1;
*now = (ts.tv_sec * 1000ull) + (ts.tv_nsec / (1000ull * 1000ull));
#else
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0)
return -1;
*now = (tv.tv_sec * 1000ull) + (tv.tv_usec / 1000ull);
#endif
return 0; return 0;
} }

View File

@ -262,20 +262,14 @@ startJob(void)
static int static int
finishJob(const char *name, int handle, int timer) finishJob(const char *name, int handle, int timer)
{ {
unsigned long long now_us;
struct timespec waitTime; struct timespec waitTime;
int rc; int rc;
#if HAVE_MACH_CLOCK_ROUTINES
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); now_us = g_get_real_time();
clock_get_time(cclock, &mts); waitTime.tv_sec = now_us / (1000*1000);
mach_port_deallocate(mach_task_self(), cclock); waitTime.tv_nsec = (now_us % ((now_us / (1000*1000)))) * 1000;
waitTime.tv_sec = mts.tv_sec;
waitTime.tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_REALTIME, &waitTime);
#endif
waitTime.tv_sec += 5; waitTime.tv_sec += 5;
rc = 0; rc = 0;
while (!eventThreadJobDone && rc == 0) while (!eventThreadJobDone && rc == 0)

View File

@ -4289,7 +4289,7 @@ virshWatchJob(vshControl *ctl,
struct sigaction old_sig_action; struct sigaction old_sig_action;
struct pollfd pollfd[2] = {{.fd = pipe_fd, .events = POLLIN, .revents = 0}, struct pollfd pollfd[2] = {{.fd = pipe_fd, .events = POLLIN, .revents = 0},
{.fd = STDIN_FILENO, .events = POLLIN, .revents = 0}}; {.fd = STDIN_FILENO, .events = POLLIN, .revents = 0}};
struct timeval start, curr; unsigned long long start_us, curr_us;
virDomainJobInfo jobinfo; virDomainJobInfo jobinfo;
int ret = -1; int ret = -1;
char retchar; char retchar;
@ -4311,7 +4311,7 @@ virshWatchJob(vshControl *ctl,
if (!vshTTYAvailable(ctl)) if (!vshTTYAvailable(ctl))
npollfd = 1; npollfd = 1;
GETTIMEOFDAY(&start); start_us = g_get_real_time();
while (1) { while (1) {
ret = poll((struct pollfd *)&pollfd, npollfd, 500); ret = poll((struct pollfd *)&pollfd, npollfd, 500);
if (ret > 0) { if (ret > 0) {
@ -4345,10 +4345,8 @@ virshWatchJob(vshControl *ctl,
goto cleanup; goto cleanup;
} }
GETTIMEOFDAY(&curr); curr_us = g_get_real_time();
if (timeout_ms && (((int)(curr.tv_sec - start.tv_sec) * 1000 + if (timeout_ms && ((curr_us - start_us)/1000) > timeout_ms) {
(int)(curr.tv_usec - start.tv_usec) / 1000) >
timeout_ms)) {
/* suspend the domain when migration timeouts. */ /* suspend the domain when migration timeouts. */
vshDebug(ctl, VSH_ERR_DEBUG, "%s timeout", label); vshDebug(ctl, VSH_ERR_DEBUG, "%s timeout", label);
if (timeout_func) if (timeout_func)

View File

@ -1286,11 +1286,10 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
bool ret = true; bool ret = true;
while (cmd) { while (cmd) {
struct timeval before, after; gint64 before, after;
bool enable_timing = ctl->timing; bool enable_timing = ctl->timing;
if (enable_timing) before = g_get_real_time();
GETTIMEOFDAY(&before);
if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) || if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) ||
(hooks && hooks->connHandler && hooks->connHandler(ctl))) { (hooks && hooks->connHandler && hooks->connHandler(ctl))) {
@ -1300,8 +1299,7 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
ret = false; ret = false;
} }
if (enable_timing) after = g_get_real_time();
GETTIMEOFDAY(&after);
/* try to automatically catch disconnections */ /* try to automatically catch disconnections */
if (!ret && if (!ret &&
@ -1321,8 +1319,7 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
return ret; return ret;
if (enable_timing) { if (enable_timing) {
double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) + double diff_ms = (after - before) / 1000.0;
((after.tv_usec - before.tv_usec) / 1000.0));
vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms); vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms);
} else { } else {

View File

@ -31,7 +31,6 @@
#define VIR_FROM_THIS VIR_FROM_NONE #define VIR_FROM_THIS VIR_FROM_NONE
#define GETTIMEOFDAY(T) gettimeofday(T, NULL)
#define VSH_MAX_XML_FILE (10*1024*1024) #define VSH_MAX_XML_FILE (10*1024*1024)
#define VSH_MATCH(FLAG) (flags & (FLAG)) #define VSH_MATCH(FLAG) (flags & (FLAG))