Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / Linux / SystemTimeSupport.cpp
1 /*
2  *
3  *    Copyright (c) 2018 Nest Labs, Inc.
4  *    All rights reserved.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *          Provides implementations of the CHIP System Layer platform
22  *          time/clock functions that are suitable for use on the Posix platform.
23  */
24
25 #include <platform/internal/CHIPDeviceLayerInternal.h>
26
27 #include <support/TimeUtils.h>
28 #include <support/logging/CHIPLogging.h>
29
30 #include <chrono>
31 #include <errno.h>
32 #include <inttypes.h>
33 #include <sys/time.h>
34
35 namespace chip {
36 namespace System {
37 namespace Platform {
38 namespace Layer {
39
40 uint64_t GetClock_Monotonic()
41 {
42     std::chrono::microseconds epoch =
43         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch());
44     // count() is nominally signed, but for a monotonic clock it cannot be
45     // negative.
46     return static_cast<uint64_t>(epoch.count());
47 }
48
49 uint64_t GetClock_MonotonicMS()
50 {
51     std::chrono::milliseconds epoch =
52         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
53     // count() is nominally signed, but for a monotonic clock it cannot be
54     // negative.
55     return static_cast<uint64_t>(epoch.count());
56 }
57
58 uint64_t GetClock_MonotonicHiRes()
59 {
60     std::chrono::microseconds epoch =
61         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch());
62     // count() is nominally signed, but for a monotonic clock it cannot be
63     // negative.
64     return static_cast<uint64_t>(epoch.count());
65 }
66
67 System::Error GetClock_RealTime(uint64_t & curTime)
68 {
69     struct timeval tv;
70     int res = gettimeofday(&tv, nullptr);
71     if (res != 0)
72     {
73         return MapErrorPOSIX(errno);
74     }
75     if (tv.tv_sec < CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD)
76     {
77         return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
78     }
79     if (tv.tv_usec < 0)
80     {
81         return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
82     }
83     static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative tv_sec values!");
84     curTime = (static_cast<uint64_t>(tv.tv_sec) * UINT64_C(1000000)) + static_cast<uint64_t>(tv.tv_usec);
85     return CHIP_SYSTEM_NO_ERROR;
86 }
87
88 System::Error GetClock_RealTimeMS(uint64_t & curTime)
89 {
90     struct timeval tv;
91     int res = gettimeofday(&tv, nullptr);
92     if (res != 0)
93     {
94         return MapErrorPOSIX(errno);
95     }
96     if (tv.tv_sec < CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD)
97     {
98         return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
99     }
100     if (tv.tv_usec < 0)
101     {
102         return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
103     }
104     static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative tv_sec values!");
105     curTime = (static_cast<uint64_t>(tv.tv_sec) * UINT64_C(1000)) + (static_cast<uint64_t>(tv.tv_usec) / 1000);
106     return CHIP_SYSTEM_NO_ERROR;
107 }
108
109 System::Error SetClock_RealTime(uint64_t newCurTime)
110 {
111     struct timeval tv;
112     tv.tv_sec  = static_cast<time_t>(newCurTime / UINT64_C(1000000));
113     tv.tv_usec = static_cast<long>(newCurTime % UINT64_C(1000000));
114     int res    = settimeofday(&tv, nullptr);
115     if (res != 0)
116     {
117         return (errno == EPERM) ? CHIP_SYSTEM_ERROR_ACCESS_DENIED : MapErrorPOSIX(errno);
118     }
119 #if CHIP_PROGRESS_LOGGING
120     {
121         const time_t timep = tv.tv_sec;
122         struct tm calendar;
123         localtime_r(&timep, &calendar);
124         ChipLogProgress(
125             DeviceLayer,
126             "Real time clock set to %ld (%04" PRId16 "/%02" PRId8 "/%02" PRId8 " %02" PRId8 ":%02" PRId8 ":%02" PRId8 " UTC)",
127             tv.tv_sec, calendar.tm_year, calendar.tm_mon, calendar.tm_mday, calendar.tm_hour, calendar.tm_min, calendar.tm_sec);
128     }
129 #endif // CHIP_PROGRESS_LOGGING
130     return CHIP_SYSTEM_NO_ERROR;
131 }
132
133 } // namespace Layer
134 } // namespace Platform
135 } // namespace System
136 } // namespace chip