summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-05-29 19:39:08 +0530
committerVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-06-02 16:37:48 +0530
commitd7a3f13ef17e34a39bae3ff482c15181e40cc0d7 (patch)
tree47c1d40b652828101541f216b0f9282e61c4519c
parent7e146557a27508a07ce2abeaf22871daab94c6d8 (diff)
downloadphosphor-watchdog-d7a3f13ef17e34a39bae3ff482c15181e40cc0d7.tar.gz
phosphor-watchdog-d7a3f13ef17e34a39bae3ff482c15181e40cc0d7.zip
Implement Watchdog interface
This commit gives concrete implementation of the interface. Change-Id: I3951c5811c8e6cff87c87842a1e3c538463bfde7 Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
-rw-r--r--Makefile.am17
-rw-r--r--configure.ac3
-rw-r--r--mainapp.cpp22
-rw-r--r--watchdog.cpp96
-rw-r--r--watchdog.hpp92
5 files changed, 220 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index 888f8cf..cd58d99 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,13 +1,20 @@
sbin_PROGRAMS = phosphor-watchdog
-noinst_HEADERS = timer.hpp
+noinst_HEADERS = timer.hpp \
+ watchdog.hpp
-phosphor_watchdog_SOURCES = \
+phosphor_watchdog_SOURCES = \
argument.cpp \
- timer.cpp \
+ timer.cpp \
+ watchdog.cpp \
mainapp.cpp
phosphor_watchdog_LDFLAGS = $(SYSTEMD_LIBS) \
- ${PHOSPHOR_LOGGING_LIBS}
+ ${PHOSPHOR_LOGGING_LIBS} \
+ ${SDBUSPLUS_LIBS} \
+ ${PHOSPHOR_DBUS_INTERFACES_LIBS}
+
phosphor_watchdog_CXXFLAGS = $(SYSTEMD_CFLAGS)\
- ${PHOSPHOR_LOGGING_CFLAGS}
+ ${PHOSPHOR_LOGGING_CFLAGS} \
+ ${SDBUSPLUS_CFLAGS} \
+ ${PHOSPHOR_DBUS_INTERFACES_CFLAGS}
diff --git a/configure.ac b/configure.ac
index 2f06b7b..878b30d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,8 +18,11 @@ AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
# For linking
LT_INIT
+# Check for needed modules
PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221], [], [AC_MSG_ERROR(["systemd required and not found"])])
PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],, [AC_MSG_ERROR([Could not find phosphor-logging...openbmc/phosphor-logging package required])])
+PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, [AC_MSG_ERROR([Could not find sdbusplus...openbmc/sdbusplus package required])])
+PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],, [AC_MSG_ERROR([Could not find phosphor-dbus-interfaces...openbmc/phosphor-dbus-interfaces package required])])
# Create configured output
AC_CONFIG_FILES([Makefile])
diff --git a/mainapp.cpp b/mainapp.cpp
index 4ab811c..b9e6121 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -17,7 +17,7 @@
#include <iostream>
#include <phosphor-logging/log.hpp>
#include "argument.hpp"
-#include "timer.hpp"
+#include "watchdog.hpp"
static void exitWithError(const char* err, char** argv)
{
@@ -62,11 +62,23 @@ int main(int argc, char** argv)
phosphor::watchdog::EventPtr eventP{event};
event = nullptr;
- // TODO: Creating the timer object would be inside watchdog implementation.
- // Putting this here for completion of this piece
- phosphor::watchdog::Timer timer(eventP);
+ // Get a handle to system dbus.
+ auto bus = sdbusplus::bus::new_default();
- while(!timer.expired())
+ // Add systemd object manager.
+ sdbusplus::server::manager::manager(bus, path.c_str());
+
+ // Attach the bus to sd_event to service user requests
+ bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
+
+ // Create a watchdog object
+ phosphor::watchdog::Watchdog watchdog(bus, path.c_str(), eventP);
+
+ // Claim the bus
+ bus.request_name(service.c_str());
+
+ // Wait until the timer has expired
+ while(!watchdog.timerExpired())
{
// -1 denotes wait for ever
r = sd_event_run(eventP.get(), (uint64_t)-1);
diff --git a/watchdog.cpp b/watchdog.cpp
new file mode 100644
index 0000000..c9e9919
--- /dev/null
+++ b/watchdog.cpp
@@ -0,0 +1,96 @@
+#include <chrono>
+#include <phosphor-logging/log.hpp>
+#include "watchdog.hpp"
+
+namespace phosphor
+{
+namespace watchdog
+{
+using namespace std::chrono;
+using namespace std::chrono_literals;
+using namespace phosphor::logging;
+
+// Enable or disable watchdog
+bool Watchdog::enabled(bool value)
+{
+ if (WatchdogInherits::enabled() != value)
+ {
+ if (value)
+ {
+ // Start ONESHOT timer. Timer handles all in usec
+ auto usec = duration_cast<microseconds>(
+ milliseconds(this->interval()));
+ // Update new expiration
+ timer.start(usec);
+
+ // Enable timer
+ timer.setEnabled<std::true_type>();
+
+ log<level::INFO>("watchdog: enabled and started",
+ entry("INTERVAL=%llu", this->interval()));
+ }
+ else
+ {
+ timer.setEnabled<std::false_type>();
+ log<level::INFO>("watchdog: disabled");
+ }
+ }
+ return WatchdogInherits::enabled(value);
+}
+
+// Get the remaining time before timer expires.
+// If the timer is disabled, returns 0
+uint64_t Watchdog::timeRemaining() const
+{
+ uint64_t timeRemain = 0;
+
+ if (WatchdogInherits::enabled())
+ {
+ // timer may have already expired and disabled
+ if (timer.getEnabled() != SD_EVENT_OFF)
+ {
+ // the one-shot timer does not expire yet
+ auto expiry = duration_cast<milliseconds>(
+ timer.getRemaining());
+
+ // convert to msec per interface expectation.
+ auto timeNow = duration_cast<milliseconds>(
+ Timer::getCurrentTime());
+
+ // Its possible that timer may have expired by now.
+ // So need to cross verify.
+ timeRemain = (expiry > timeNow) ?
+ (expiry - timeNow).count() : 0;
+ }
+ }
+ return timeRemain;
+}
+
+// Reset the timer to a new expiration value
+uint64_t Watchdog::timeRemaining(uint64_t value)
+{
+ if (WatchdogInherits::enabled())
+ {
+ // Disable the timer
+ timer.setEnabled<std::false_type>();
+
+ // Timer handles all in microseconds and hence converting
+ auto usec = duration_cast<microseconds>(
+ milliseconds(value));
+ // Update new expiration
+ timer.start(usec);
+
+ // Enable the timer.
+ timer.setEnabled<std::true_type>();
+
+ log<level::INFO>("watchdog: reset timer",
+ entry("VALUE=%llu", value));
+
+ // Update Base class data.
+ return WatchdogInherits::timeRemaining(value);
+ }
+ return 0;
+}
+
+} // namespace watchdog
+} // namepsace phosphor
diff --git a/watchdog.hpp b/watchdog.hpp
new file mode 100644
index 0000000..47484af
--- /dev/null
+++ b/watchdog.hpp
@@ -0,0 +1,92 @@
+#pragma once
+
+#include <systemd/sd-event.h>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <xyz/openbmc_project/State/Watchdog/server.hpp>
+#include "timer.hpp"
+
+namespace phosphor
+{
+namespace watchdog
+{
+using WatchdogInherits = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::State::server::Watchdog>;
+
+/** @class Watchdog
+ * @brief OpenBMC watchdog implementation.
+ * @details A concrete implementation for the
+ * xyz.openbmc_project.State.Watchdog DBus API.
+ */
+class Watchdog : public WatchdogInherits
+{
+ public:
+ Watchdog() = delete;
+ ~Watchdog() = default;
+ Watchdog(const Watchdog&) = delete;
+ Watchdog& operator=(const Watchdog&) = delete;
+ Watchdog(Watchdog&&) = delete;
+ Watchdog& operator=(Watchdog &&) = delete;
+
+ /** @brief Constructs the Watchdog object
+ *
+ * @param[in] bus - DBus bus to attach to
+ * @param[in] objPath - Object path to attach to
+ * @param[in] event - reference to sd_event unique pointer
+ */
+ Watchdog(sdbusplus::bus::bus& bus,
+ const char* objPath,
+ EventPtr& event) :
+ WatchdogInherits(bus, objPath),
+ bus(bus),
+ timer(event)
+ {
+ // Nothing
+ }
+
+ /** @brief Enable or disable watchdog
+ * If a watchdog state is changed from disable to enable,
+ * the watchdog timer is set with the default expiration
+ * interval and it starts counting down.
+ * If a watchdog is already enabled, setting @value to true
+ * has no effect.
+ *
+ * @param[in] value - 'true' to enable. 'false' to disable
+ *
+ * @return : applied value if success, previous value otherwise
+ */
+ bool enabled(bool value) override;
+
+ /** @brief Gets the remaining time before watchdog expires.
+ *
+ * @return 0 if watchdog is disabled or expired.
+ * Remaining time in milliseconds otherwise.
+ */
+ uint64_t timeRemaining() const override;
+
+ /** @brief Reset timer to expire after new timeout in milliseconds.
+ *
+ * @param[in] value - the time in miliseconds after which
+ * the watchdog will expire
+ *
+ * @return: updated timeout value if watchdog is enabled.
+ * 0 otherwise.
+ */
+ uint64_t timeRemaining(uint64_t value) override;
+
+ /** @brief Tells if the referenced timer is expired or not */
+ inline auto timerExpired() const
+ {
+ return timer.expired();
+ }
+
+ private:
+ /** @brief sdbusplus handle */
+ sdbusplus::bus::bus& bus;
+
+ /** @brief Contained timer object */
+ Timer timer;
+};
+
+} // namespace watchdog
+} // namespace phosphor
OpenPOWER on IntegriCloud