xref: /openbmc/phosphor-watchdog/src/watchdog.hpp (revision 923a9080fdbed58d233b307a1f9e6965530ddfa1)
142506393SWilliam A. Kennington III #pragma once
242506393SWilliam A. Kennington III 
342506393SWilliam A. Kennington III #include <sdbusplus/bus.hpp>
442506393SWilliam A. Kennington III #include <sdbusplus/server/object.hpp>
542506393SWilliam A. Kennington III #include <sdeventplus/event.hpp>
642506393SWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp>
76ac6a347SPatrick Williams #include <xyz/openbmc_project/State/Watchdog/server.hpp>
86ac6a347SPatrick Williams 
96ac6a347SPatrick Williams #include <functional>
106ac6a347SPatrick Williams #include <optional>
119ef0d0fbSWilly Tu #include <string_view>
1242506393SWilliam A. Kennington III #include <unordered_map>
1342506393SWilliam A. Kennington III #include <utility>
1442506393SWilliam A. Kennington III 
1542506393SWilliam A. Kennington III namespace phosphor
1642506393SWilliam A. Kennington III {
1742506393SWilliam A. Kennington III namespace watchdog
1842506393SWilliam A. Kennington III {
1942506393SWilliam A. Kennington III 
2042506393SWilliam A. Kennington III constexpr auto DEFAULT_MIN_INTERVAL_MS = 0;
2142506393SWilliam A. Kennington III namespace Base = sdbusplus::xyz::openbmc_project::State::server;
2273bd5277SPatrick Williams using WatchdogInherits = sdbusplus::server::object_t<Base::Watchdog>;
2342506393SWilliam A. Kennington III 
2442506393SWilliam A. Kennington III /** @class Watchdog
2542506393SWilliam A. Kennington III  *  @brief OpenBMC watchdog implementation.
2642506393SWilliam A. Kennington III  *  @details A concrete implementation for the
2742506393SWilliam A. Kennington III  *  xyz.openbmc_project.State.Watchdog DBus API.
2842506393SWilliam A. Kennington III  */
2942506393SWilliam A. Kennington III class Watchdog : public WatchdogInherits
3042506393SWilliam A. Kennington III {
3142506393SWilliam A. Kennington III   public:
3242506393SWilliam A. Kennington III     Watchdog() = delete;
3342506393SWilliam A. Kennington III     ~Watchdog() = default;
3442506393SWilliam A. Kennington III     Watchdog(const Watchdog&) = delete;
3542506393SWilliam A. Kennington III     Watchdog& operator=(const Watchdog&) = delete;
3642506393SWilliam A. Kennington III     Watchdog(Watchdog&&) = delete;
3742506393SWilliam A. Kennington III     Watchdog& operator=(Watchdog&&) = delete;
3842506393SWilliam A. Kennington III 
3942506393SWilliam A. Kennington III     /** @brief Type used to hold the name of a systemd target.
4042506393SWilliam A. Kennington III      */
4142506393SWilliam A. Kennington III     using TargetName = std::string;
4242506393SWilliam A. Kennington III 
4342506393SWilliam A. Kennington III     /** @brief Type used to store the mapping of a Watchdog timeout
4442506393SWilliam A. Kennington III      *         action to a systemd target.
4542506393SWilliam A. Kennington III      */
4642506393SWilliam A. Kennington III     using ActionTargetMap = std::unordered_map<Action, TargetName>;
4742506393SWilliam A. Kennington III 
4842506393SWilliam A. Kennington III     /** @brief Type used to specify the parameters of a fallback watchdog
4942506393SWilliam A. Kennington III      */
5042506393SWilliam A. Kennington III     struct Fallback
5142506393SWilliam A. Kennington III     {
5242506393SWilliam A. Kennington III         Action action;
5342506393SWilliam A. Kennington III         uint64_t interval;
5442506393SWilliam A. Kennington III         bool always;
5542506393SWilliam A. Kennington III     };
5642506393SWilliam A. Kennington III 
5742506393SWilliam A. Kennington III     /** @brief Constructs the Watchdog object
5842506393SWilliam A. Kennington III      *
5942506393SWilliam A. Kennington III      *  @param[in] bus              - DBus bus to attach to.
6042506393SWilliam A. Kennington III      *  @param[in] objPath          - Object path to attach to.
6142506393SWilliam A. Kennington III      *  @param[in] event            - reference to sdeventplus::Event loop
6242506393SWilliam A. Kennington III      *  @param[in] actionTargets    - map of systemd targets called on timeout
63afc369adSAndrew Geissler      *  @param[in] fallback         - fallback watchdog
64afc369adSAndrew Geissler      *  @param[in] minInterval      - minimum intervale value allowed
65afc369adSAndrew Geissler      *  @param[in] defaultInterval  - default interval to start with
66d1b1e79bSWilliam A. Kennington III      *  @param[in] exitAfterTimeout - should the event loop be terminated
6742506393SWilliam A. Kennington III      */
Watchdog(sdbusplus::bus_t & bus,const char * objPath,const sdeventplus::Event & event,ActionTargetMap && actionTargetMap={},std::optional<Fallback> && fallback=std::nullopt,uint64_t minInterval=DEFAULT_MIN_INTERVAL_MS,uint64_t defaultInterval=0,bool exitAfterTimeout=false)6873bd5277SPatrick Williams     Watchdog(sdbusplus::bus_t& bus, const char* objPath,
6942506393SWilliam A. Kennington III              const sdeventplus::Event& event,
7042506393SWilliam A. Kennington III              ActionTargetMap&& actionTargetMap = {},
7142506393SWilliam A. Kennington III              std::optional<Fallback>&& fallback = std::nullopt,
72afc369adSAndrew Geissler              uint64_t minInterval = DEFAULT_MIN_INTERVAL_MS,
73d1b1e79bSWilliam A. Kennington III              uint64_t defaultInterval = 0, bool exitAfterTimeout = false) :
74*923a9080SPatrick Williams         WatchdogInherits(bus, objPath), bus(bus),
75*923a9080SPatrick Williams         actionTargetMap(std::move(actionTargetMap)), fallback(fallback),
76*923a9080SPatrick Williams         minInterval(minInterval),
779ef0d0fbSWilly Tu         timer(event, std::bind(&Watchdog::timeOutHandler, this)),
78d1b1e79bSWilliam A. Kennington III         objPath(objPath), exitAfterTimeout(exitAfterTimeout)
7942506393SWilliam A. Kennington III     {
80afc369adSAndrew Geissler         // Use default if passed in otherwise just use default that comes
81afc369adSAndrew Geissler         // with object
82afc369adSAndrew Geissler         if (defaultInterval)
83afc369adSAndrew Geissler         {
84afc369adSAndrew Geissler             interval(defaultInterval);
85afc369adSAndrew Geissler         }
86afc369adSAndrew Geissler         else
87afc369adSAndrew Geissler         {
8842506393SWilliam A. Kennington III             interval(interval());
89afc369adSAndrew Geissler         }
9042506393SWilliam A. Kennington III         // We need to poke the enable mechanism to make sure that the timer
9142506393SWilliam A. Kennington III         // enters the fallback state if the fallback is always enabled.
9242506393SWilliam A. Kennington III         tryFallbackOrDisable();
9342506393SWilliam A. Kennington III     }
9442506393SWilliam A. Kennington III 
9542506393SWilliam A. Kennington III     /** @brief Resets the TimeRemaining to the configured Interval
9642506393SWilliam A. Kennington III      *         Optionally enables the watchdog.
9742506393SWilliam A. Kennington III      *
9842506393SWilliam A. Kennington III      *  @param[in] enableWatchdog - Should the call enable the watchdog
9942506393SWilliam A. Kennington III      */
10042506393SWilliam A. Kennington III     void resetTimeRemaining(bool enableWatchdog) override;
10142506393SWilliam A. Kennington III 
10242506393SWilliam A. Kennington III     /** @brief Since we are overriding the setter-enabled but not the
10342506393SWilliam A. Kennington III      *         getter-enabled, we need to have this using in order to
10442506393SWilliam A. Kennington III      *         allow passthrough usage of the getter-enabled.
10542506393SWilliam A. Kennington III      */
10642506393SWilliam A. Kennington III     using Base::Watchdog::enabled;
10742506393SWilliam A. Kennington III 
10842506393SWilliam A. Kennington III     /** @brief Enable or disable watchdog
10942506393SWilliam A. Kennington III      *         If a watchdog state is changed from disable to enable,
11042506393SWilliam A. Kennington III      *         the watchdog timer is set with the default expiration
11142506393SWilliam A. Kennington III      *         interval and it starts counting down.
11242506393SWilliam A. Kennington III      *         If a watchdog is already enabled, setting @value to true
11342506393SWilliam A. Kennington III      *         has no effect.
11442506393SWilliam A. Kennington III      *
11542506393SWilliam A. Kennington III      *  @param[in] value - 'true' to enable. 'false' to disable
11642506393SWilliam A. Kennington III      *
11742506393SWilliam A. Kennington III      *  @return : applied value if success, previous value otherwise
11842506393SWilliam A. Kennington III      */
11942506393SWilliam A. Kennington III     bool enabled(bool value) override;
12042506393SWilliam A. Kennington III 
12142506393SWilliam A. Kennington III     /** @brief Gets the remaining time before watchdog expires.
12242506393SWilliam A. Kennington III      *
12342506393SWilliam A. Kennington III      *  @return 0 if watchdog is expired.
12442506393SWilliam A. Kennington III      *          Remaining time in milliseconds otherwise.
12542506393SWilliam A. Kennington III      */
12642506393SWilliam A. Kennington III     uint64_t timeRemaining() const override;
12742506393SWilliam A. Kennington III 
12842506393SWilliam A. Kennington III     /** @brief Reset timer to expire after new timeout in milliseconds.
12942506393SWilliam A. Kennington III      *
13042506393SWilliam A. Kennington III      *  @param[in] value - the time in milliseconds after which
13142506393SWilliam A. Kennington III      *                     the watchdog will expire
13242506393SWilliam A. Kennington III      *
13342506393SWilliam A. Kennington III      *  @return: updated timeout value if watchdog is enabled.
13442506393SWilliam A. Kennington III      *           0 otherwise.
13542506393SWilliam A. Kennington III      */
13642506393SWilliam A. Kennington III     uint64_t timeRemaining(uint64_t value) override;
13742506393SWilliam A. Kennington III 
13842506393SWilliam A. Kennington III     /** @brief Get value of Interval
13942506393SWilliam A. Kennington III      *
14042506393SWilliam A. Kennington III      *
14142506393SWilliam A. Kennington III      *  @return: current interval
14242506393SWilliam A. Kennington III      *
14342506393SWilliam A. Kennington III      */
14442506393SWilliam A. Kennington III     using WatchdogInherits::interval;
14542506393SWilliam A. Kennington III 
14642506393SWilliam A. Kennington III     /** @brief Set value of Interval
14742506393SWilliam A. Kennington III      *
14842506393SWilliam A. Kennington III      *  @param[in] value - interval time to set
14942506393SWilliam A. Kennington III      *
15042506393SWilliam A. Kennington III      *  @return: interval that was set
15142506393SWilliam A. Kennington III      *
15242506393SWilliam A. Kennington III      */
153cf4ce3c1SWilly Tu     uint64_t interval(uint64_t value) override;
15442506393SWilliam A. Kennington III 
15542506393SWilliam A. Kennington III     /** @brief Tells if the referenced timer is expired or not */
timerExpired() const15642506393SWilliam A. Kennington III     inline auto timerExpired() const
15742506393SWilliam A. Kennington III     {
15842506393SWilliam A. Kennington III         return timer.hasExpired();
15942506393SWilliam A. Kennington III     }
16042506393SWilliam A. Kennington III 
16142506393SWilliam A. Kennington III     /** @brief Tells if the timer is running or not */
timerEnabled() const16242506393SWilliam A. Kennington III     inline bool timerEnabled() const
16342506393SWilliam A. Kennington III     {
16442506393SWilliam A. Kennington III         return timer.isEnabled();
16542506393SWilliam A. Kennington III     }
16642506393SWilliam A. Kennington III 
16742506393SWilliam A. Kennington III   private:
16842506393SWilliam A. Kennington III     /** @brief sdbusplus handle */
16973bd5277SPatrick Williams     sdbusplus::bus_t& bus;
17042506393SWilliam A. Kennington III 
17142506393SWilliam A. Kennington III     /** @brief Map of systemd units to be started when the timer expires */
17242506393SWilliam A. Kennington III     ActionTargetMap actionTargetMap;
17342506393SWilliam A. Kennington III 
17442506393SWilliam A. Kennington III     /** @brief Fallback timer options */
17542506393SWilliam A. Kennington III     std::optional<Fallback> fallback;
17642506393SWilliam A. Kennington III 
17742506393SWilliam A. Kennington III     /** @brief Minimum watchdog interval value */
17842506393SWilliam A. Kennington III     uint64_t minInterval;
17942506393SWilliam A. Kennington III 
18042506393SWilliam A. Kennington III     /** @brief Contained timer object */
18142506393SWilliam A. Kennington III     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
18242506393SWilliam A. Kennington III 
18342506393SWilliam A. Kennington III     /** @brief Optional Callback handler on timer expirartion */
18442506393SWilliam A. Kennington III     void timeOutHandler();
18542506393SWilliam A. Kennington III 
18642506393SWilliam A. Kennington III     /** @brief Attempt to enter the fallback watchdog or disables it */
18742506393SWilliam A. Kennington III     void tryFallbackOrDisable();
1889ef0d0fbSWilly Tu 
1899ef0d0fbSWilly Tu     /** @brief Object path of the watchdog */
1909ef0d0fbSWilly Tu     std::string_view objPath;
191d1b1e79bSWilliam A. Kennington III 
192d1b1e79bSWilliam A. Kennington III     /** @brief Do we terminate after exit */
193d1b1e79bSWilliam A. Kennington III     bool exitAfterTimeout;
19442506393SWilliam A. Kennington III };
19542506393SWilliam A. Kennington III 
19642506393SWilliam A. Kennington III } // namespace watchdog
19742506393SWilliam A. Kennington III } // namespace phosphor
198