blob: c626536a0367c2d1521342f3ecf7b8ca0791d194 [file] [log] [blame]
Vishwanatha Subbannad27e71e2017-02-01 18:02:38 +05301#include <chrono>
Vishwanatha Subbannabcb76882017-01-25 16:29:43 +05302#include <phosphor-logging/log.hpp>
3#include "timer.hpp"
4namespace phosphor
5{
6namespace ipmi
7{
8
9using namespace phosphor::logging;
10
11// Initializes the timer object
12void Timer::initialize()
13{
14 // This can not be called more than once.
15 if (eventSource)
16 {
17 throw std::runtime_error("Timer already initialized");
18 }
19
20 // Add infinite expiration time
21 auto r = sd_event_add_time(timeEvent, &eventSource,
22 CLOCK_MONOTONIC, // Time base
Vishwanatha Subbannad27e71e2017-02-01 18:02:38 +053023 UINT64_MAX, // Expire time - way long time
Vishwanatha Subbannabcb76882017-01-25 16:29:43 +053024 0, // Use default event accuracy
25 timeoutHandler, // Callback handler on timeout
26 this); // User data
27 if (r < 0)
28 {
29 log<level::ERR>("Failure to set initial expiration time value",
30 entry("ERROR=%s", strerror(-r)));
31
32 throw std::runtime_error("Timer initialization failed");
33 }
34
35 // Disable the timer for now
Vishwanatha Subbannad27e71e2017-02-01 18:02:38 +053036 r = setTimer(SD_EVENT_OFF);
Vishwanatha Subbannabcb76882017-01-25 16:29:43 +053037 if (r < 0)
38 {
39 log<level::ERR>("Failure to disable timer",
40 entry("ERROR=%s", strerror(-r)));
41
Vishwanatha Subbannad27e71e2017-02-01 18:02:38 +053042 throw std::runtime_error("Disabling the timer failed");
Vishwanatha Subbannabcb76882017-01-25 16:29:43 +053043 }
44 return;
45}
46
47/** @brief callback handler on timeout */
48int Timer::timeoutHandler(sd_event_source* eventSource,
49 uint64_t usec, void* userData)
50{
51 auto timer = static_cast<Timer*>(userData);
52 timer->expired = true;
53
54 log<level::INFO>("Timer expired");
55 return 0;
56}
57
Vishwanatha Subbannad27e71e2017-02-01 18:02:38 +053058// Gets the time from steady_clock
59std::chrono::microseconds Timer::getTime()
60{
61 using namespace std::chrono;
62 auto usec = steady_clock::now().time_since_epoch();
63 return duration_cast<microseconds>(usec);
64}
65
66// Enables or disables the timer
67int Timer::setTimer(int action)
68{
69 return sd_event_source_set_enabled(eventSource, action);
70}
71
72// Sets the time and arms the timer
73int Timer::startTimer(std::chrono::microseconds timeValue)
74{
75 // Disable the timer
76 setTimer(SD_EVENT_OFF);
77
78 // Get the current MONOTONIC time and add the delta
79 auto expireTime = getTime() + timeValue;
80
81 // Set the time
82 auto r = sd_event_source_set_time(eventSource, expireTime.count());
83 if (r < 0)
84 {
85 log<level::ERR>("Failure to set timer",
86 entry("ERROR=%s", strerror(-r)));
87 return r;
88 }
89
90 // A ONESHOT timer means that when the timer goes off,
91 // its moves to disabled state.
92 r = setTimer(SD_EVENT_ONESHOT);
93 if (r < 0)
94 {
95 log<level::ERR>("Failure to start timer",
96 entry("ERROR=%s", strerror(-r)));
97 }
98 return r;
99}
100
Vishwanatha Subbannabcb76882017-01-25 16:29:43 +0530101} // namespace ipmi
102} // namespace phosphor