blob: d2574333b2a53a40cd5c23f8158b2d757d59e0c8 [file] [log] [blame]
Ratan Gupta4f80c1a2017-09-03 18:01:22 +05301#include "timer.hpp"
Patrick Venture189d44e2018-07-09 12:30:59 -07002
3#include <chrono>
4#include <phosphor-logging/elog-errors.hpp>
5#include <phosphor-logging/log.hpp>
6#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta4f80c1a2017-09-03 18:01:22 +05307
8namespace phosphor
9{
10namespace network
11{
12
13using namespace phosphor::logging;
14using namespace sdbusplus::xyz::openbmc_project::Common::Error;
15// Initializes the timer object
16void Timer::initialize()
17{
18 // This can not be called more than once.
19 if (eventSource)
20 {
21 log<level::ERR>("Timer already initialized");
22 elog<InternalFailure>();
23 }
24
Gunnar Mills57d9c502018-09-14 14:42:34 -050025 auto r = sd_event_default(&timeEvent);
Ratan Gupta4f80c1a2017-09-03 18:01:22 +053026 if (r < 0)
27 {
28 log<level::ERR>("Failure in creating the sd_event",
29 entry("ERROR=%d", r));
30
31 elog<InternalFailure>();
32 }
33
34 // Add infinite expiration time
Gunnar Mills57d9c502018-09-14 14:42:34 -050035 r = sd_event_add_time(timeEvent, &eventSource,
Ratan Gupta4f80c1a2017-09-03 18:01:22 +053036 CLOCK_MONOTONIC, // Time base
37 UINT64_MAX, // Expire time - way long time
38 0, // Use default event accuracy
39 timeoutHandler, // Callback handler on timeout
40 this); // User data
41 if (r < 0)
42 {
43 log<level::ERR>("Failure to set initial expiration time value",
44 entry("ERROR=%d", r));
45
46 elog<InternalFailure>();
47 }
48
49 // Disable the timer for now
50 r = setTimer(SD_EVENT_OFF);
51 if (r < 0)
52 {
Gunnar Mills57d9c502018-09-14 14:42:34 -050053 log<level::ERR>("Failure to disable timer", entry("ERROR=%d", r));
Ratan Gupta4f80c1a2017-09-03 18:01:22 +053054
55 elog<InternalFailure>();
56 }
57 return;
58}
59
60/** @brief callback handler on timeout */
Gunnar Mills57d9c502018-09-14 14:42:34 -050061int Timer::timeoutHandler(sd_event_source* eventSource, uint64_t usec,
62 void* userData)
Ratan Gupta4f80c1a2017-09-03 18:01:22 +053063{
64 auto timer = static_cast<Timer*>(userData);
65 timer->expired = true;
66
67 // Call optional user call back function if available
68 if (timer->userCallBack)
69 {
70 timer->userCallBack();
71 }
72
Ratan Guptae05083a2017-09-16 07:12:11 +053073 sd_event_source_set_enabled(eventSource, SD_EVENT_OFF);
Ratan Gupta4f80c1a2017-09-03 18:01:22 +053074 return 0;
75}
76
77// Gets the time from steady_clock
78std::chrono::microseconds Timer::getTime()
79{
80 using namespace std::chrono;
81 auto usec = steady_clock::now().time_since_epoch();
82 return duration_cast<microseconds>(usec);
83}
84
85// Enables or disables the timer
86int Timer::setTimer(int action)
87{
88 return sd_event_source_set_enabled(eventSource, action);
89}
90
91// Sets the time and arms the timer
92int Timer::startTimer(std::chrono::microseconds timeValue)
93{
94 // Disable the timer
95 setTimer(SD_EVENT_OFF);
96 expired = false;
97
98 // Get the current MONOTONIC time and add the delta
99 auto expireTime = getTime() + timeValue;
100
101 // Set the time
102 auto r = sd_event_source_set_time(eventSource, expireTime.count());
103 if (r < 0)
104 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500105 log<level::ERR>("Failure to set timer", entry("ERROR=%d", r));
Ratan Gupta4f80c1a2017-09-03 18:01:22 +0530106
107 elog<InternalFailure>();
108 }
109
110 // A ONESHOT timer means that when the timer goes off,
111 // its moves to disabled state.
112 r = setTimer(SD_EVENT_ONESHOT);
113 if (r < 0)
114 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500115 log<level::ERR>("Failure to start timer", entry("ERROR=%d", r));
Ratan Gupta4f80c1a2017-09-03 18:01:22 +0530116
117 elog<InternalFailure>();
118 }
119 return r;
120}
121
122} // namespace network
123} // namespace phosphor