diff options
author | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-05-29 19:39:08 +0530 |
---|---|---|
committer | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-06-02 16:37:48 +0530 |
commit | d7a3f13ef17e34a39bae3ff482c15181e40cc0d7 (patch) | |
tree | 47c1d40b652828101541f216b0f9282e61c4519c | |
parent | 7e146557a27508a07ce2abeaf22871daab94c6d8 (diff) | |
download | phosphor-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.am | 17 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | mainapp.cpp | 22 | ||||
-rw-r--r-- | watchdog.cpp | 96 | ||||
-rw-r--r-- | watchdog.hpp | 92 |
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 |