blob: 4e8fd9a77e4343f8e1c1e078ee16f53035aed963 [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
Andrew Geissler8622f692017-04-02 18:19:00 -050054 // Call optional user call back function if available
55 if(timer->userCallBack)
56 {
57 timer->userCallBack();
58 }
59
Vishwanatha Subbannabcb76882017-01-25 16:29:43 +053060 log<level::INFO>("Timer expired");
61 return 0;
62}
63
Vishwanatha Subbannad27e71e2017-02-01 18:02:38 +053064// Gets the time from steady_clock
65std::chrono::microseconds Timer::getTime()
66{
67 using namespace std::chrono;
68 auto usec = steady_clock::now().time_since_epoch();
69 return duration_cast<microseconds>(usec);
70}
71
72// Enables or disables the timer
73int Timer::setTimer(int action)
74{
75 return sd_event_source_set_enabled(eventSource, action);
76}
77
78// Sets the time and arms the timer
79int Timer::startTimer(std::chrono::microseconds timeValue)
80{
81 // Disable the timer
82 setTimer(SD_EVENT_OFF);
83
84 // Get the current MONOTONIC time and add the delta
85 auto expireTime = getTime() + timeValue;
86
87 // Set the time
88 auto r = sd_event_source_set_time(eventSource, expireTime.count());
89 if (r < 0)
90 {
91 log<level::ERR>("Failure to set timer",
92 entry("ERROR=%s", strerror(-r)));
93 return r;
94 }
95
96 // A ONESHOT timer means that when the timer goes off,
97 // its moves to disabled state.
98 r = setTimer(SD_EVENT_ONESHOT);
99 if (r < 0)
100 {
101 log<level::ERR>("Failure to start timer",
102 entry("ERROR=%s", strerror(-r)));
103 }
104 return r;
105}
106
Vishwanatha Subbannabcb76882017-01-25 16:29:43 +0530107} // namespace ipmi
108} // namespace phosphor