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 40 Time::Time() { } 41 42 Time::~Time() { } 43 44 Time* Time::GetInstance() { 45 return g_time.Pointer(); 46 } 47 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 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 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 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 90 int Time::GetTimeOfDay(struct timeval* tv, struct timezone* tz) { 91 return gettimeofday(tv, tz); 92 } 93 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 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 133 time_t Time::GetSecondsSinceEpoch() const { 134 return time(nullptr); 135 } 136 137 } // namespace shill 138