• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/net/shill_time.h"
18 
19 #include <string.h>
20 #include <time.h>
21 
22 #include <base/format_macros.h>
23 #include <base/strings/stringprintf.h>
24 
25 using std::string;
26 
27 namespace shill {
28 
29 namespace {
30 
31 // As Time may be instantiated by MemoryLogMessage during a callback of
32 // AtExitManager, it needs to be a leaky singleton to avoid
33 // AtExitManager::RegisterCallback() from potentially being called within a
34 // callback of AtExitManager, which will lead to a crash. Making Time leaky is
35 // fine as it does not need to clean up or release any resource at destruction.
36 base::LazyInstance<Time>::Leaky g_time = LAZY_INSTANCE_INITIALIZER;
37 
38 }  // namespace
39 
Time()40 Time::Time() { }
41 
~Time()42 Time::~Time() { }
43 
GetInstance()44 Time* Time::GetInstance() {
45   return g_time.Pointer();
46 }
47 
GetSecondsMonotonic(time_t * seconds)48 bool Time::GetSecondsMonotonic(time_t* seconds) {
49   struct timeval now;
50   if (GetTimeMonotonic(&now) < 0) {
51     return false;
52   } else {
53     *seconds = now.tv_sec;
54     return true;
55   }
56 }
57 
GetSecondsBoottime(time_t * seconds)58 bool Time::GetSecondsBoottime(time_t* seconds) {
59   struct timeval now;
60   if (GetTimeBoottime(&now) < 0) {
61     return false;
62   } else {
63     *seconds = now.tv_sec;
64     return true;
65   }
66 }
67 
GetTimeMonotonic(struct timeval * tv)68 int Time::GetTimeMonotonic(struct timeval* tv) {
69   struct timespec ts;
70   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
71     return -1;
72   }
73 
74   tv->tv_sec = ts.tv_sec;
75   tv->tv_usec = ts.tv_nsec / 1000;
76   return 0;
77 }
78 
GetTimeBoottime(struct timeval * tv)79 int Time::GetTimeBoottime(struct timeval* tv) {
80   struct timespec ts;
81   if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
82     return -1;
83   }
84 
85   tv->tv_sec = ts.tv_sec;
86   tv->tv_usec = ts.tv_nsec / 1000;
87   return 0;
88 }
89 
GetTimeOfDay(struct timeval * tv,struct timezone * tz)90 int Time::GetTimeOfDay(struct timeval* tv, struct timezone* tz) {
91   return gettimeofday(tv, tz);
92 }
93 
GetNow()94 Timestamp Time::GetNow() {
95   struct timeval now_monotonic = {};
96   struct timeval now_boottime = {};
97   struct timeval now_wall_clock = {};
98   struct tm local_time = {};
99   string wall_clock_string;
100 
101   GetTimeMonotonic(&now_monotonic);
102   GetTimeBoottime(&now_boottime);
103   GetTimeOfDay(&now_wall_clock, nullptr);
104   localtime_r(&now_wall_clock.tv_sec, &local_time);
105   wall_clock_string = FormatTime(local_time, now_wall_clock.tv_usec);
106 
107   return Timestamp(now_monotonic, now_boottime, wall_clock_string);
108 }
109 
110 // static
FormatTime(const struct tm & date_time,suseconds_t usec)111 string Time::FormatTime(const struct tm& date_time, suseconds_t usec) {
112   char date_time_string[64];
113   size_t date_time_length;
114   date_time_length = strftime(date_time_string, sizeof(date_time_string),
115                               "%Y-%m-%dT%H:%M:%S %z", &date_time);
116 
117   // Stitch in the microseconds, to provider finer resolution than
118   // strftime allows.
119   string full_string = "<unknown>";
120   char* split_pos = static_cast<char*>(
121       memchr(date_time_string, ' ', sizeof(date_time_string)));
122   if (date_time_length && date_time_length < sizeof(date_time_string) &&
123       split_pos) {
124     *split_pos = '\0';
125     full_string =
126         base::StringPrintf("%s.%06" PRIu64 "%s", date_time_string,
127                            static_cast<uint64_t>(usec), split_pos + 1);
128   }
129 
130   return full_string;
131 }
132 
GetSecondsSinceEpoch() const133 time_t Time::GetSecondsSinceEpoch() const {
134   return time(nullptr);
135 }
136 
137 }  // namespace shill
138