blob: 0c82df15593b97e8c74ce32dd33c9d41acde022a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#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;
// systemd service to kick start a target.
constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
// Enable or disable watchdog
bool Watchdog::enabled(bool value)
{
if (this->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 (this->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 (this->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;
}
// Optional callback function on timer expiration
void Watchdog::timeOutHandler()
{
if (!target.empty())
{
auto method = bus.new_method_call(SYSTEMD_SERVICE,
SYSTEMD_ROOT,
SYSTEMD_INTERFACE,
"StartUnit");
method.append(target);
method.append("replace");
bus.call_noreply(method);
}
return;
}
} // namespace watchdog
} // namepsace phosphor
|