blob: 2825855c157acf9365db9f319164fd4b5c5a8b94 [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>
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +05304#include <phosphor-logging/elog.hpp>
5#include <phosphor-logging/elog-errors.hpp>
6#include <xyz/openbmc_project/Common/error.hpp>
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +05307#include "timer.hpp"
8namespace phosphor
9{
10namespace watchdog
11{
12
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +053013// For throwing exception
14using namespace phosphor::logging;
15using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
16 Error::InternalFailure;
17
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +053018// Initializes the timer object
19void Timer::initialize()
20{
21 // This can not be called more than once.
22 if (eventSource.get())
23 {
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +053024 log<level::ERR>("Timer already initialized");
25 elog<InternalFailure>();
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +053026 }
27
28 // Add infinite expiration time
29 decltype(eventSource.get()) sourcePtr = nullptr;
30 auto r = sd_event_add_time(event.get(),
31 &sourcePtr,
32 CLOCK_MONOTONIC, // Time base
33 UINT64_MAX, // Expire time - way long time
34 0, // Use default event accuracy
35 timeoutHandler, // Callback handler on timeout
36 this); // User data
37 eventSource.reset(sourcePtr);
38
39 if (r < 0)
40 {
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +053041 log<level::ERR>("Timer initialization failed");
42 elog<InternalFailure>();
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +053043 }
44
45 // Disable the timer for now
46 setEnabled<std::false_type>();
47}
48
49// callback handler on timeout
50int Timer::timeoutHandler(sd_event_source* eventSource,
51 uint64_t usec, void* userData)
52{
53 using namespace phosphor::logging;
54
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +053055 log<level::INFO>("Timer Expired");
56
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +053057 auto timer = static_cast<Timer*>(userData);
58 timer->expire = true;
59
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +053060 // Call an optional callback function
61 if(timer->userCallBack)
62 {
63 timer->userCallBack();
64 }
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +053065 return 0;
66}
67
68// Gets the time from steady_clock
69std::chrono::microseconds Timer::getCurrentTime()
70{
71 using namespace std::chrono;
72 auto usec = steady_clock::now().time_since_epoch();
73 return duration_cast<microseconds>(usec);
74}
75
76// Sets the expiration time and arms the timer
77void Timer::start(std::chrono::microseconds usec)
78{
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +053079 using namespace std::chrono;
80
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +053081 // Get the current MONOTONIC time and add the delta
82 auto expireTime = getCurrentTime() + usec;
83
84 // Set the time
85 auto r = sd_event_source_set_time(eventSource.get(),
86 expireTime.count());
87 if (r < 0)
88 {
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +053089 log<level::ERR>("Error setting the expiration time",
90 entry("MSEC=%llu",duration_cast<milliseconds>(usec).count()));
91 elog<InternalFailure>();
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +053092 }
93}
94
95// Returns current timer enablement type
96int Timer::getEnabled() const
97{
98 int enabled{};
99 auto r = sd_event_source_get_enabled(eventSource.get(), &enabled);
100 if (r < 0)
101 {
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +0530102 log<level::ERR>("Error geting current timer type enablement state");
103 elog<InternalFailure>();
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +0530104 }
105 return enabled;
106}
107
108// Enables / disables the timer
109void Timer::setEnabled(int type)
110{
111 auto r = sd_event_source_set_enabled(eventSource.get(), type);
112 if (r < 0)
113 {
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +0530114 log<level::ERR>("Error setting the timer type",
115 entry("TYPE=%d",type));
116 elog<InternalFailure>();
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +0530117 }
118}
119
120// Returns time remaining before expiration
121std::chrono::microseconds Timer::getRemaining() const
122{
123 uint64_t next = 0;
124 auto r = sd_event_source_get_time(eventSource.get(), &next);
125 if (r < 0)
126 {
Vishwanatha Subbanna4d5ef3f2017-05-31 18:54:22 +0530127 log<level::ERR>("Error fetching remaining time to expire");
128 elog<InternalFailure>();
Vishwanatha Subbanna7e146552017-05-29 17:03:33 +0530129 }
130 return std::chrono::microseconds(next);
131}
132
133} // namespace watchdog
134} // namespace phosphor