blob: 06965de1fc9ec7670b3c9ea22aab1b796fcb89f5 [file] [log] [blame]
Ratan Gupta40801362018-03-12 16:21:37 +05301#include <chrono>
2#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
23 UINT64_MAX, // Expire time - way long time
24 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
36 r = setTimer(SD_EVENT_OFF);
37 if (r < 0)
38 {
39 log<level::ERR>("Failure to disable timer",
40 entry("ERROR=%s", strerror(-r)));
41
42 throw std::runtime_error("Disabling the timer failed");
43 }
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 // Call optional user call back function if available
56 if(timer->userCallBack)
57 {
58 timer->userCallBack();
59 }
60
61 sd_event_source_set_enabled(eventSource, SD_EVENT_OFF);
62 return 0;
63}
64
65// Gets the time from steady_clock
66std::chrono::microseconds Timer::getTime()
67{
68 using namespace std::chrono;
69 auto usec = steady_clock::now().time_since_epoch();
70 return duration_cast<microseconds>(usec);
71}
72
73// Enables or disables the timer
74int Timer::setTimer(int action)
75{
76 return sd_event_source_set_enabled(eventSource, action);
77}
78
79// Sets the time and arms the timer
80int Timer::startTimer(std::chrono::microseconds timeValue)
81{
82 // Disable the timer
83 setTimer(SD_EVENT_OFF);
84 expired = false;
85
86 // Get the current MONOTONIC time and add the delta
87 auto expireTime = getTime() + timeValue;
88
89 // Set the time
90 auto r = sd_event_source_set_time(eventSource, expireTime.count());
91 if (r < 0)
92 {
93 log<level::ERR>("Failure to set timer",
94 entry("ERROR=%s", strerror(-r)));
95 return r;
96 }
97
98 // A ONESHOT timer means that when the timer goes off,
99 // its moves to disabled state.
100 r = setTimer(SD_EVENT_ONESHOT);
101 if (r < 0)
102 {
103 log<level::ERR>("Failure to start timer",
104 entry("ERROR=%s", strerror(-r)));
105 }
106 return r;
107}
108
109} // namespace ipmi
110} // namespace phosphor