blob: 0aaf7d80f2ae9540f3ca237459da9916636df04f [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");
76 return 0;
77}
78
79// Gets the time from steady_clock
80std::chrono::microseconds Timer::getTime()
81{
82 using namespace std::chrono;
83 auto usec = steady_clock::now().time_since_epoch();
84 return duration_cast<microseconds>(usec);
85}
86
87// Enables or disables the timer
88int Timer::setTimer(int action)
89{
90 return sd_event_source_set_enabled(eventSource, action);
91}
92
93// Sets the time and arms the timer
94int Timer::startTimer(std::chrono::microseconds timeValue)
95{
96 // Disable the timer
97 setTimer(SD_EVENT_OFF);
98 expired = false;
99
100 // Get the current MONOTONIC time and add the delta
101 auto expireTime = getTime() + timeValue;
102
103 // Set the time
104 auto r = sd_event_source_set_time(eventSource, expireTime.count());
105 if (r < 0)
106 {
107 log<level::ERR>("Failure to set timer",
108 entry("ERROR=%d", r));
109
110 elog<InternalFailure>();
111 }
112
113 // A ONESHOT timer means that when the timer goes off,
114 // its moves to disabled state.
115 r = setTimer(SD_EVENT_ONESHOT);
116 if (r < 0)
117 {
118 log<level::ERR>("Failure to start timer",
119 entry("ERROR=%d", r));
120
121 elog<InternalFailure>();
122 }
123 return r;
124}
125
126} // namespace network
127} // namespace phosphor