blob: bf1a47069b4a218ca2c2eb3984e910da8ac53000 [file] [log] [blame]
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +05301#include <chrono>
2#include <systemd/sd-event.h>
3#include <phosphor-logging/log.hpp>
4#include "timer.hpp"
5namespace phosphor
6{
7namespace watchdog
8{
9
10// Initializes the timer object
11void Timer::initialize()
12{
13 // This can not be called more than once.
14 if (eventSource.get())
15 {
16 // TODO: Need to throw elog exception stating its already added.
17 throw std::runtime_error("Timer already initialized");
18 }
19
20 // Add infinite expiration time
21 decltype(eventSource.get()) sourcePtr = nullptr;
22 auto r = sd_event_add_time(event.get(),
23 &sourcePtr,
24 CLOCK_MONOTONIC, // Time base
25 UINT64_MAX, // Expire time - way long time
26 0, // Use default event accuracy
27 timeoutHandler, // Callback handler on timeout
28 this); // User data
29 eventSource.reset(sourcePtr);
30
31 if (r < 0)
32 {
33 // TODO: throw elog exception
34 throw std::runtime_error("Timer initialization failed");
35 }
36
37 // Disable the timer for now
38 setEnabled<std::false_type>();
39}
40
41// callback handler on timeout
42int Timer::timeoutHandler(sd_event_source* eventSource,
43 uint64_t usec, void* userData)
44{
45 using namespace phosphor::logging;
46
47 auto timer = static_cast<Timer*>(userData);
48 timer->expire = true;
49
50 log<level::INFO>("Timer Expired");
51
52 //TODO: Need to call user callback function.
53 return 0;
54}
55
56// Gets the time from steady_clock
57std::chrono::microseconds Timer::getCurrentTime()
58{
59 using namespace std::chrono;
60 auto usec = steady_clock::now().time_since_epoch();
61 return duration_cast<microseconds>(usec);
62}
63
64// Sets the expiration time and arms the timer
65void Timer::start(std::chrono::microseconds usec)
66{
67 // Get the current MONOTONIC time and add the delta
68 auto expireTime = getCurrentTime() + usec;
69
70 // Set the time
71 auto r = sd_event_source_set_time(eventSource.get(),
72 expireTime.count());
73 if (r < 0)
74 {
75 // TODO throw elog exception
76 throw std::runtime_error("Error setting the expiration time");
77 }
78}
79
80// Returns current timer enablement type
81int Timer::getEnabled() const
82{
83 int enabled{};
84 auto r = sd_event_source_get_enabled(eventSource.get(), &enabled);
85 if (r < 0)
86 {
87 // TODO: Need to throw elog exception
88 throw std::runtime_error("Error geting current time enablement state");
89 }
90 return enabled;
91}
92
93// Enables / disables the timer
94void Timer::setEnabled(int type)
95{
96 auto r = sd_event_source_set_enabled(eventSource.get(), type);
97 if (r < 0)
98 {
99 // TODO: Need to throw elog exception
100 throw std::runtime_error("Error altering enabled property");
101 }
102}
103
104// Returns time remaining before expiration
105std::chrono::microseconds Timer::getRemaining() const
106{
107 uint64_t next = 0;
108 auto r = sd_event_source_get_time(eventSource.get(), &next);
109 if (r < 0)
110 {
111 // TODO: Need to throw elog exception
112 throw std::runtime_error("Error altering enabled property");
113 }
114 return std::chrono::microseconds(next);
115}
116
117} // namespace watchdog
118} // namespace phosphor