summaryrefslogtreecommitdiffstats
path: root/timer.cpp
diff options
context:
space:
mode:
authorAndrew Geissler <andrewg@us.ibm.com>2017-04-03 13:31:13 -0500
committerAndrew Geissler <andrewg@us.ibm.com>2017-05-09 12:51:59 -0500
commit8315970370d63b101bd0bd579bc1f697a3c8d07c (patch)
tree856438abae898d4edd29a6df9e6ccf5e1c28aa20 /timer.cpp
parent857f54b71198dcb5a1d5acae98f0c0cb78298694 (diff)
downloadphosphor-host-ipmid-8315970370d63b101bd0bd579bc1f697a3c8d07c.tar.gz
phosphor-host-ipmid-8315970370d63b101bd0bd579bc1f697a3c8d07c.zip
Add timeout support to host control
On timeout, send error signal for all commands within the queue Change-Id: Ic995fd4b057bd83f121a3deec405a26e0991e9a2 Signed-off-by: Andrew Geissler <andrewg@us.ibm.com>
Diffstat (limited to 'timer.cpp')
-rw-r--r--timer.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/timer.cpp b/timer.cpp
new file mode 100644
index 0000000..4e8fd9a
--- /dev/null
+++ b/timer.cpp
@@ -0,0 +1,108 @@
+#include <chrono>
+#include <phosphor-logging/log.hpp>
+#include "timer.hpp"
+namespace phosphor
+{
+namespace ipmi
+{
+
+using namespace phosphor::logging;
+
+// Initializes the timer object
+void Timer::initialize()
+{
+ // This can not be called more than once.
+ if (eventSource)
+ {
+ throw std::runtime_error("Timer already initialized");
+ }
+
+ // Add infinite expiration time
+ auto r = sd_event_add_time(timeEvent, &eventSource,
+ CLOCK_MONOTONIC, // Time base
+ UINT64_MAX, // Expire time - way long time
+ 0, // Use default event accuracy
+ timeoutHandler, // Callback handler on timeout
+ this); // User data
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to set initial expiration time value",
+ entry("ERROR=%s", strerror(-r)));
+
+ throw std::runtime_error("Timer initialization failed");
+ }
+
+ // Disable the timer for now
+ r = setTimer(SD_EVENT_OFF);
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to disable timer",
+ entry("ERROR=%s", strerror(-r)));
+
+ throw std::runtime_error("Disabling the timer failed");
+ }
+ return;
+}
+
+/** @brief callback handler on timeout */
+int Timer::timeoutHandler(sd_event_source* eventSource,
+ uint64_t usec, void* userData)
+{
+ auto timer = static_cast<Timer*>(userData);
+ timer->expired = true;
+
+ // Call optional user call back function if available
+ if(timer->userCallBack)
+ {
+ timer->userCallBack();
+ }
+
+ log<level::INFO>("Timer expired");
+ return 0;
+}
+
+// Gets the time from steady_clock
+std::chrono::microseconds Timer::getTime()
+{
+ using namespace std::chrono;
+ auto usec = steady_clock::now().time_since_epoch();
+ return duration_cast<microseconds>(usec);
+}
+
+// Enables or disables the timer
+int Timer::setTimer(int action)
+{
+ return sd_event_source_set_enabled(eventSource, action);
+}
+
+// Sets the time and arms the timer
+int Timer::startTimer(std::chrono::microseconds timeValue)
+{
+ // Disable the timer
+ setTimer(SD_EVENT_OFF);
+
+ // Get the current MONOTONIC time and add the delta
+ auto expireTime = getTime() + timeValue;
+
+ // Set the time
+ auto r = sd_event_source_set_time(eventSource, expireTime.count());
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to set timer",
+ entry("ERROR=%s", strerror(-r)));
+ return r;
+ }
+
+ // A ONESHOT timer means that when the timer goes off,
+ // its moves to disabled state.
+ r = setTimer(SD_EVENT_ONESHOT);
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to start timer",
+ entry("ERROR=%s", strerror(-r)));
+ }
+ return r;
+}
+
+} // namespace ipmi
+} // namespace phosphor
OpenPOWER on IntegriCloud