blob: 7d3519dc2046d4323f72f4eaa3f48357bb87ed5f [file] [log] [blame]
Paul Stewarte6927402012-01-23 16:11:30 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartc2350ee2011-10-19 12:28:40 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/shill_time.h"
6
Paul Stewarte6927402012-01-23 16:11:30 -08007#include <time.h>
8
Darin Petkov0c65bdd2012-12-05 13:42:41 +01009#include <base/stringprintf.h>
10
11using std::string;
12
Paul Stewartc2350ee2011-10-19 12:28:40 -070013namespace shill {
14
Ben Chanbbdef5f2012-04-23 13:58:15 -070015namespace {
Ben Chanf9b18562012-08-13 16:57:24 -070016
17// As Time may be instantiated by MemoryLogMessage during a callback of
18// AtExitManager, it needs to be a leaky singleton to avoid
19// AtExitManager::RegisterCallback() from potentially being called within a
20// callback of AtExitManager, which will lead to a crash. Making Time leaky is
21// fine as it does not need to clean up or release any resource at destruction.
22base::LazyInstance<Time>::Leaky g_time = LAZY_INSTANCE_INITIALIZER;
23
Ben Chanbbdef5f2012-04-23 13:58:15 -070024} // namespace
Paul Stewartc2350ee2011-10-19 12:28:40 -070025
26Time::Time() { }
27
28Time::~Time() { }
29
30Time* Time::GetInstance() {
31 return g_time.Pointer();
32}
33
Paul Stewarte6927402012-01-23 16:11:30 -080034int Time::GetTimeMonotonic(struct timeval *tv) {
35 struct timespec ts;
36 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
37 return -1;
38 }
39
40 tv->tv_sec = ts.tv_sec;
41 tv->tv_usec = ts.tv_nsec / 1000;
42 return 0;
43}
44
Paul Stewartc2350ee2011-10-19 12:28:40 -070045int Time::GetTimeOfDay(struct timeval *tv, struct timezone *tz) {
46 return gettimeofday(tv, tz);
47}
48
Darin Petkov0c65bdd2012-12-05 13:42:41 +010049Timestamp Time::GetNow() {
50 struct timeval now_monotonic = (const struct timeval){ 0 };
51 GetTimeMonotonic(&now_monotonic);
52 struct timeval now_wall_clock = (const struct timeval){ 0 };
53 GetTimeOfDay(&now_wall_clock, NULL);
54 struct tm local_time = (const struct tm){ 0 };
55 localtime_r(&now_wall_clock.tv_sec, &local_time);
56 // There're two levels of formatting -- first most of the timestamp is printed
57 // into |format|, then the resulting string is used to insert the microseconds
58 // (note the %%06u format string).
59 char format[64];
60 size_t length = strftime(format, sizeof(format),
61 "%Y-%m-%dT%H:%M:%S.%%06u%z", &local_time);
62 string wall_clock = "<unknown>";
63 if (length && length < sizeof(format)) {
64 wall_clock = base::StringPrintf(format, now_wall_clock.tv_usec);
65 }
66 return Timestamp(now_monotonic, wall_clock);
67}
68
Paul Stewartc2350ee2011-10-19 12:28:40 -070069} // namespace shill