Matter SDK Coverage Report
Current view: top level - system - SystemClock.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 75.0 % 8 6
Test Date: 2025-01-17 19:00:11 Functions: 75.0 % 4 3

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020 Project CHIP Authors
       4              :  *    Copyright (c) 2018 Nest Labs, Inc.
       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              :  *      This is an internal header file that defines the interface to a platform-supplied
      22              :  *      function for retrieving the current system time.
      23              :  */
      24              : 
      25              : #pragma once
      26              : 
      27              : // Include configuration headers
      28              : #include <system/SystemConfig.h>
      29              : 
      30              : // Include dependent headers
      31              : #include <lib/support/DLLUtil.h>
      32              : #include <lib/support/TimeUtils.h>
      33              : #include <system/SystemError.h>
      34              : 
      35              : #if CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS || CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS
      36              : #include <sys/time.h>
      37              : #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS || CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS
      38              : 
      39              : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKETS
      40              : #include <zephyr/net/socket.h>
      41              : #endif
      42              : 
      43              : #include <chrono>
      44              : #include <stdint.h>
      45              : 
      46              : #if CHIP_DEVICE_LAYER_TARGET_DARWIN || CHIP_DEVICE_LAYER_TARGET_LINUX
      47              : #define CHIP_DEVICE_LAYER_USE_ATOMICS_FOR_CLOCK 1
      48              : #endif // CHIP_DEVICE_LAYER_TARGET_DARWIN || CHIP_DEVICE_LAYER_TARGET_LINUX
      49              : 
      50              : #ifndef CHIP_DEVICE_LAYER_USE_ATOMICS_FOR_CLOCK
      51              : #define CHIP_DEVICE_LAYER_USE_ATOMICS_FOR_CLOCK 0
      52              : #endif
      53              : 
      54              : namespace chip {
      55              : namespace System {
      56              : 
      57              : namespace Clock {
      58              : 
      59              : /*
      60              :  * We use `std::chrono::duration` for clock types to provide type safety. But unlike the predefined std types
      61              :  * (`std::chrono::milliseconds` et al), CHIP uses unsigned base types, and types are explicity sized, with
      62              :  * smaller-size types available for members and arguments where appropriate.
      63              :  *
      64              :  * Most conversions are handled by the types transparently. To convert with possible loss of information, use
      65              :  * `std::chrono::duration_cast<>()`.
      66              :  */
      67              : 
      68              : using Microseconds64 = std::chrono::duration<uint64_t, std::micro>;
      69              : using Microseconds32 = std::chrono::duration<uint32_t, std::micro>;
      70              : 
      71              : using Milliseconds64 = std::chrono::duration<uint64_t, std::milli>;
      72              : using Milliseconds32 = std::chrono::duration<uint32_t, std::milli>;
      73              : using Milliseconds16 = std::chrono::duration<uint16_t, std::milli>;
      74              : 
      75              : using Seconds64 = std::chrono::duration<uint64_t>;
      76              : using Seconds32 = std::chrono::duration<uint32_t>;
      77              : using Seconds16 = std::chrono::duration<uint16_t>;
      78              : 
      79              : inline constexpr Seconds16 kZero{ 0 };
      80              : 
      81              : namespace Literals {
      82              : 
      83              : constexpr Microseconds64 operator""_us(unsigned long long int us)
      84              : {
      85              :     return Microseconds64(us);
      86              : }
      87              : constexpr Microseconds64 operator""_us64(unsigned long long int us)
      88              : {
      89              :     return Microseconds64(us);
      90              : }
      91              : constexpr Microseconds32 operator""_us32(unsigned long long int us)
      92              : {
      93              :     return Microseconds32(us);
      94              : }
      95              : 
      96          692 : constexpr Milliseconds64 operator""_ms(unsigned long long int ms)
      97              : {
      98          692 :     return Milliseconds64(ms);
      99              : }
     100              : constexpr Milliseconds64 operator""_ms64(unsigned long long int ms)
     101              : {
     102              :     return Milliseconds64(ms);
     103              : }
     104        24033 : constexpr Milliseconds32 operator""_ms32(unsigned long long int ms)
     105              : {
     106        24033 :     return Milliseconds32(ms);
     107              : }
     108              : constexpr Milliseconds16 operator""_ms16(unsigned long long int ms)
     109              : {
     110              :     return Milliseconds16(ms);
     111              : }
     112              : 
     113              : constexpr Seconds64 operator""_s(unsigned long long int s)
     114              : {
     115              :     return Seconds64(s);
     116              : }
     117              : constexpr Seconds64 operator""_s64(unsigned long long int s)
     118              : {
     119              :     return Seconds64(s);
     120              : }
     121              : constexpr Seconds32 operator""_s32(unsigned long long int s)
     122              : {
     123              :     return Seconds32(s);
     124              : }
     125            0 : constexpr Seconds16 operator""_s16(unsigned long long int s)
     126              : {
     127            0 :     return Seconds16(s);
     128              : }
     129              : 
     130              : } // namespace Literals
     131              : 
     132              : /**
     133              :  * Type for System time stamps.
     134              :  */
     135              : using Timestamp = Milliseconds64;
     136              : 
     137              : /**
     138              :  * Type for System time offsets (i.e. `StartTime()` duration).
     139              :  *
     140              :  * It is required of platforms that time stamps from `GetMonotonic…()` have the high bit(s) zero,
     141              :  * so the sum of a `Milliseconds64` time stamp and `Milliseconds32` offset will never overflow.
     142              :  */
     143              : using Timeout = Milliseconds32;
     144              : 
     145              : class ClockBase
     146              : {
     147              : public:
     148              :     virtual ~ClockBase() = default;
     149              : 
     150              :     /**
     151              :      * Returns a monotonic system time.
     152              :      *
     153              :      * This function returns an elapsed time since an arbitrary, platform-defined epoch.
     154              :      * The value returned is guaranteed to be ever-increasing (i.e. never wrapping or decreasing) between
     155              :      * reboots of the system.  Additionally, the underlying time source is guaranteed to tick
     156              :      * continuously during any system sleep modes that do not entail a restart upon wake.
     157              :      *
     158              :      * Although some platforms may choose to return a value that measures the time since boot for the
     159              :      * system, applications must *not* rely on this.
     160              :      *
     161              :      * WARNING: *** It is up to each platform to ensure that GetMonotonicTimestamp can be
     162              :      *              called safely in a re-entrant way from multiple contexts if making use
     163              :      *              of this method from the application, outside the Matter stack execution
     164              :      *              serialization context. ***
     165              :      */
     166              :     virtual Timestamp GetMonotonicTimestamp();
     167              : 
     168              :     /**
     169              :      * Returns a monotonic system time in units of microseconds, from the platform.
     170              :      *
     171              :      * This function returns an elapsed time in microseconds since an arbitrary, platform-defined epoch.
     172              :      * The value returned MUST BE guaranteed to be ever-increasing (i.e. never wrapping or decreasing) until
     173              :      * reboot of the system.  Additionally, the underlying time source is guaranteed to tick
     174              :      * continuously during any system sleep modes that do not entail a restart upon wake.
     175              :      *
     176              :      * Although some platforms may choose to return a value that measures the time since boot for the
     177              :      * system, applications must *not* rely on this.
     178              :      *
     179              :      * Applications must not rely on the time returned by GetMonotonicMicroseconds64() actually having
     180              :      * granularity finer than milliseconds.
     181              :      *
     182              :      * Platform implementations *must* use the same epoch for GetMonotonicMicroseconds64() and GetMonotonicMilliseconds64().
     183              :      *
     184              :      * Platforms *must* use an epoch such that the upper bit of a value returned by GetMonotonicMicroseconds64() is zero
     185              :      * for the expected operational life of the system.
     186              :      *
     187              :      * @returns Elapsed time in microseconds since an arbitrary, platform-defined epoch.
     188              :      */
     189              :     virtual Microseconds64 GetMonotonicMicroseconds64() = 0;
     190              : 
     191              :     /**
     192              :      * Returns a monotonic system time in units of microseconds, from the platform.
     193              :      *
     194              :      * This function returns an elapsed time in milliseconds since an arbitrary, platform-defined epoch.
     195              :      * The value returned MUST BE guaranteed to be ever-increasing (i.e. never wrapping or decreasing) until
     196              :      * reboot of the system.  Additionally, the underlying time source is guaranteed to tick
     197              :      * continuously during any system sleep modes that do not entail a restart upon wake.
     198              :      *
     199              :      * Although some platforms may choose to return a value that measures the time since boot for the
     200              :      * system, applications must *not* rely on this.
     201              :      *
     202              :      * Platform implementations *must* use the same epoch for GetMonotonicMicroseconds64() and GetMonotonicMilliseconds64().
     203              :      * (As a consequence of this, and the requirement for GetMonotonicMicroseconds64() to return high bit zero, values
     204              :      * returned by GetMonotonicMilliseconds64() will have the high ten bits zero.)
     205              :      *
     206              :      * @returns             Elapsed time in milliseconds since an arbitrary, platform-defined epoch.
     207              :      */
     208              :     virtual Milliseconds64 GetMonotonicMilliseconds64() = 0;
     209              : 
     210              :     /**
     211              :      * @brief
     212              :      *   Platform-specific function for getting the current real (civil) time in microsecond Unix time
     213              :      *   format.
     214              :      *
     215              :      * This function is expected to return the local platform's notion of current real time, expressed
     216              :      * as a Unix time value scaled to microseconds.  The underlying clock is required to tick at a
     217              :      * rate of least at whole seconds (values of 1,000,000), but may tick faster.
     218              :      *
     219              :      * On those platforms that are capable of tracking real time, GetClock_RealTime() must return the
     220              :      * error CHIP_ERROR_REAL_TIME_NOT_SYNCED whenever the system is unsynchronized with real time.
     221              :      *
     222              :      * Platforms that are incapable of tracking real time should not implement the GetClock_RealTime()
     223              :      * function, thereby forcing link-time failures of features that depend on access to real time.
     224              :      * Alternatively, such platforms may supply an implementation of GetClock_RealTime() that returns
     225              :      * the error CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE.
     226              :      *
     227              :      * This function is expected to be thread-safe on any platform that employs threading.
     228              :      *
     229              :      * @note
     230              :      *   This function is reserved for internal use by the System Clock.  Users of the System
     231              :      *   Clock should call System::Clock::GetClock_RealTime().
     232              :      *
     233              :      * @param[out] aCurTime                  The current time, expressed as Unix time scaled to microseconds.
     234              :      *
     235              :      * @retval #CHIP_NO_ERROR       If the method succeeded.
     236              :      * @retval #CHIP_ERROR_REAL_TIME_NOT_SYNCED
     237              :      *                                      If the platform is capable of tracking real time, but is
     238              :      *                                      is currently unsynchronized.
     239              :      * @retval #CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE
     240              :      *                                      If the platform is incapable of tracking real time.
     241              :      */
     242              :     virtual CHIP_ERROR GetClock_RealTime(Microseconds64 & aCurTime) = 0;
     243              : 
     244              :     /**
     245              :      * @brief
     246              :      *   Platform-specific function for getting the current real (civil) time in millisecond Unix time
     247              :      *   format.
     248              :      *
     249              :      * This function is expected to return the local platform's notion of current real time, expressed
     250              :      * as a Unix time value scaled to milliseconds.
     251              :      *
     252              :      * See the documentation for GetClock_RealTime() for details on the expected behavior.
     253              :      *
     254              :      * @note
     255              :      *   This function is reserved for internal use by the System Clock.  Users of the System
     256              :      *   Clock should call System::Clock::GetClock_RealTimeMS().
     257              :      *
     258              :      * @param[out] aCurTime                  The current time, expressed as Unix time scaled to milliseconds.
     259              :      *
     260              :      * @retval #CHIP_NO_ERROR       If the method succeeded.
     261              :      * @retval #CHIP_ERROR_REAL_TIME_NOT_SYNCED
     262              :      *                                      If the platform is capable of tracking real time, but is
     263              :      *                                      is currently unsynchronized.
     264              :      * @retval #CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE
     265              :      *                                      If the platform is incapable of tracking real time.
     266              :      */
     267              :     virtual CHIP_ERROR GetClock_RealTimeMS(Milliseconds64 & aCurTime) = 0;
     268              : 
     269              :     /**
     270              :      * @brief
     271              :      *   Platform-specific function for setting the current real (civil) time.
     272              :      *
     273              :      * This function set the local platform's notion of current real time.  The new current
     274              :      * time is expressed as a Unix time value scaled to microseconds.
     275              :      *
     276              :      * Once set, underlying platform clock is expected to track real time with a granularity of at least whole
     277              :      * seconds.
     278              :      *
     279              :      * On platforms that support tracking real time, the SetClock_RealTime() function must return the error
     280              :      * CHIP_ERROR_ACCESS_DENIED if the calling application does not have the privilege to set the
     281              :      * current time.
     282              :      *
     283              :      * Platforms that are incapable of tracking real time, or do not offer the ability to set real time,
     284              :      * should not implement the SetClock_RealTime() function, thereby forcing link-time failures of features
     285              :      * that depend on setting real time.  Alternatively, such platforms may supply an implementation of
     286              :      * SetClock_RealTime() that returns the error CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE.
     287              :      *
     288              :      * This function is expected to be thread-safe on any platform that employs threading.
     289              :      *
     290              :      * @note
     291              :      *   This function is reserved for internal use by the System Clock.  Users of the System
     292              :      *   Clock should call System::Clock::GetClock_RealTimeMS().
     293              :      *
     294              :      * @param[in] aNewCurTime                The new current time, expressed as Unix time scaled to microseconds.
     295              :      *
     296              :      * @retval #CHIP_NO_ERROR       If the method succeeded.
     297              :      * @retval #CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE
     298              :      *                                      If the platform is incapable of tracking real time.
     299              :      * @retval #CHIP_ERROR_ACCESS_DENIED
     300              :      *                                      If the calling application does not have the privilege to set the
     301              :      *                                      current time.
     302              :      */
     303              :     virtual CHIP_ERROR SetClock_RealTime(Microseconds64 aNewCurTime) = 0;
     304              : 
     305              : protected:
     306              :     uint64_t mLastTimestamp = 0;
     307              : };
     308              : 
     309              : // Currently we have a single implementation class, ClockImpl, whose members are implemented in build-specific files.
     310              : class ClockImpl : public ClockBase
     311              : {
     312              : public:
     313              :     ~ClockImpl() override = default;
     314              :     Microseconds64 GetMonotonicMicroseconds64() override;
     315              :     Milliseconds64 GetMonotonicMilliseconds64() override;
     316              :     CHIP_ERROR GetClock_RealTime(Microseconds64 & aCurTime) override;
     317              :     CHIP_ERROR GetClock_RealTimeMS(Milliseconds64 & aCurTime) override;
     318              :     CHIP_ERROR SetClock_RealTime(Microseconds64 aNewCurTime) override;
     319              : };
     320              : 
     321              : namespace Internal {
     322              : 
     323              : // This should only be used via SystemClock() below.
     324              : extern ClockBase * gClockBase;
     325              : 
     326              : inline void SetSystemClockForTesting(Clock::ClockBase * clock)
     327              : {
     328              :     Clock::Internal::gClockBase = clock;
     329              : }
     330              : 
     331              : // Provide a mock implementation for use by unit tests.
     332              : class MockClock : public ClockImpl
     333              : {
     334              : public:
     335              :     Microseconds64 GetMonotonicMicroseconds64() override { return mSystemTime; }
     336              :     Milliseconds64 GetMonotonicMilliseconds64() override { return std::chrono::duration_cast<Milliseconds64>(mSystemTime); }
     337              :     CHIP_ERROR GetClock_RealTime(Microseconds64 & aCurTime) override
     338              :     {
     339              :         aCurTime = mRealTime;
     340              :         return CHIP_NO_ERROR;
     341              :     }
     342              :     CHIP_ERROR GetClock_RealTimeMS(Milliseconds64 & aCurTime) override
     343              :     {
     344              :         aCurTime = std::chrono::duration_cast<Milliseconds64>(mRealTime);
     345              :         return CHIP_NO_ERROR;
     346              :     }
     347              :     CHIP_ERROR SetClock_RealTime(Microseconds64 aNewCurTime) override
     348              :     {
     349              :         mRealTime = aNewCurTime;
     350              :         return CHIP_NO_ERROR;
     351              :     }
     352              : 
     353              :     void SetMonotonic(Milliseconds64 timestamp)
     354              :     {
     355              :         mSystemTime = timestamp;
     356              : #if CHIP_DEVICE_LAYER_USE_ATOMICS_FOR_CLOCK
     357              :         __atomic_store_n(&mLastTimestamp, timestamp.count(), __ATOMIC_SEQ_CST);
     358              : #endif // CHIP_DEVICE_LAYER_USE_ATOMICS_FOR_CLOCK
     359              :     }
     360              : 
     361              :     void AdvanceMonotonic(Milliseconds64 increment) { mSystemTime += increment; }
     362              :     void AdvanceRealTime(Milliseconds64 increment) { mRealTime += increment; }
     363              : 
     364              :     Microseconds64 mSystemTime = Clock::kZero;
     365              :     Microseconds64 mRealTime   = Clock::kZero;
     366              : };
     367              : 
     368              : } // namespace Internal
     369              : 
     370              : #if CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS || CHIP_SYSTEM_CONFIG_USE_SOCKETS
     371              : Microseconds64 TimevalToMicroseconds(const timeval & in);
     372              : void ToTimeval(Microseconds64 in, timeval & out);
     373              : #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS || CHIP_SYSTEM_CONFIG_USE_SOCKETS
     374              : 
     375              : } // namespace Clock
     376              : 
     377          884 : inline Clock::ClockBase & SystemClock()
     378              : {
     379          884 :     return *Clock::Internal::gClockBase;
     380              : }
     381              : 
     382              : } // namespace System
     383              : } // namespace chip
        

Generated by: LCOV version 2.0-1