blob: afd4b8d8e6fec2fe17a97701410bca2cca324ea7 [file] [log] [blame]
Ratan Gupta4f80c1a2017-09-03 18:01:22 +05301#include <chrono>
2#include <phosphor-logging/log.hpp>
3#include <phosphor-logging/elog-errors.hpp>
4
5#include "timer.hpp"
6#include "xyz/openbmc_project/Common/error.hpp"
7
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
25 auto r = sd_event_default(&timeEvent);
26 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
35 r = sd_event_add_time(timeEvent,
36 &eventSource,
37 CLOCK_MONOTONIC, // Time base
38 UINT64_MAX, // Expire time - way long time
39 0, // Use default event accuracy
40 timeoutHandler, // Callback handler on timeout
41 this); // User data
42 if (r < 0)
43 {
44 log<level::ERR>("Failure to set initial expiration time value",
45 entry("ERROR=%d", r));
46
47 elog<InternalFailure>();
48 }
49
50 // Disable the timer for now
51 r = setTimer(SD_EVENT_OFF);
52 if (r < 0)
53 {
54 log<level::ERR>("Failure to disable timer",
55 entry("ERROR=%d", r));
56
57 elog<InternalFailure>();
58 }
59 return;
60}
61
62/** @brief callback handler on timeout */
63int Timer::timeoutHandler(sd_event_source* eventSource,
64 uint64_t usec, void* userData)
65{
66 auto timer = static_cast<Timer*>(userData);
67 timer->expired = true;
68
69 // Call optional user call back function if available
70 if (timer->userCallBack)
71 {
72 timer->userCallBack();
73 }
74
75 log<level::INFO>("Timer expired");
Ratan Guptae05083a2017-09-16 07:12:11 +053076 sd_event_source_set_enabled(eventSource, SD_EVENT_OFF);
Ratan Gupta4f80c1a2017-09-03 18:01:22 +053077 return 0;
78}
79
80// Gets the time from steady_clock
81std::chrono::microseconds Timer::getTime()
82{
83 using namespace std::chrono;
84 auto usec = steady_clock::now().time_since_epoch();
85 return duration_cast<microseconds>(usec);
86}
87
88// Enables or disables the timer
89int Timer::setTimer(int action)
90{
91 return sd_event_source_set_enabled(eventSource, action);
92}
93
94// Sets the time and arms the timer
95int Timer::startTimer(std::chrono::microseconds timeValue)
96{
97 // Disable the timer
98 setTimer(SD_EVENT_OFF);
99 expired = false;
100
101 // Get the current MONOTONIC time and add the delta
102 auto expireTime = getTime() + timeValue;
103
104 // Set the time
105 auto r = sd_event_source_set_time(eventSource, expireTime.count());
106 if (r < 0)
107 {
108 log<level::ERR>("Failure to set timer",
109 entry("ERROR=%d", r));
110
111 elog<InternalFailure>();
112 }
113
114 // A ONESHOT timer means that when the timer goes off,
115 // its moves to disabled state.
116 r = setTimer(SD_EVENT_ONESHOT);
117 if (r < 0)
118 {
119 log<level::ERR>("Failure to start timer",
120 entry("ERROR=%d", r));
121
122 elog<InternalFailure>();
123 }
124 return r;
125}
126
127} // namespace network
128} // namespace phosphor