22 pc_failsafe_cb cb =
nullptr;
23 void *cb_arg =
nullptr;
28size_t u32_dec(uint32_t v,
char *out)
34 tmp[n++] = (char)(
'0' + v % 10);
37 for (
size_t i = 0; i < n; i++)
39 out[i] = tmp[n - 1 - i];
45void pc_failsafe_reset(
void)
49 s_fs.lines[i] = pc_lifeline{};
52 s_fs.cb_arg =
nullptr;
55int pc_failsafe_register_at(
const char *name, uint32_t deadline_ms, uint32_t now)
59 if (!s_fs.lines[i].armed)
61 s_fs.lines[i].name = name;
62 s_fs.lines[i].deadline_ms = deadline_ms;
63 s_fs.lines[i].last_feed_ms = now;
64 s_fs.lines[i].armed =
true;
65 s_fs.lines[i].breached =
false;
72int pc_failsafe_register(
const char *name, uint32_t deadline_ms)
74 return pc_failsafe_register_at(name, deadline_ms,
pc_millis());
77bool pc_failsafe_feed_at(
int id, uint32_t now)
83 s_fs.lines[id].last_feed_ms = now;
84 s_fs.lines[id].breached =
false;
88bool pc_failsafe_feed(
int id)
90 return pc_failsafe_feed_at(
id,
pc_millis());
93void pc_failsafe_on_breach(pc_failsafe_cb cb,
void *arg)
99uint32_t pc_failsafe_check_at(uint32_t now)
104 pc_lifeline &l = s_fs.lines[i];
109 if (!pc_lifeline_overdue(now, l.last_feed_ms, l.deadline_ms))
121 s_fs.cb(i, l.name, s_fs.cb_arg);
127uint32_t pc_failsafe_check(
void)
129 return pc_failsafe_check_at(
pc_millis());
133static void fs_put(
char *out,
size_t cap,
size_t *n,
const char *s)
135 while (*s && *n + 1 < cap)
141static void fs_put_u32(
char *out,
size_t cap,
size_t *n, uint32_t v)
144 size_t k = u32_dec(v, b);
145 for (
size_t i = 0; i < k && *n + 1 < cap; i++)
151int pc_failsafe_json_at(uint32_t now,
char *out,
size_t cap)
154 if (!out || cap == 0)
159 fs_put(out, cap, &n,
"{\"lifelines\":[");
163 const pc_lifeline &l = s_fs.lines[i];
170 fs_put(out, cap, &n,
",");
173 fs_put(out, cap, &n,
"{\"name\":\"");
174 fs_put(out, cap, &n, l.name ? l.name :
"");
175 fs_put(out, cap, &n,
"\",\"overdue\":");
176 fs_put(out, cap, &n, pc_lifeline_overdue(now, l.last_feed_ms, l.deadline_ms) ?
"true" :
"false");
177 fs_put(out, cap, &n,
",\"age_ms\":");
178 fs_put_u32(out, cap, &n, now - l.last_feed_ms);
179 fs_put(out, cap, &n,
",\"deadline_ms\":");
180 fs_put_u32(out, cap, &n, l.deadline_ms);
181 fs_put(out, cap, &n,
"}");
183 fs_put(out, cap, &n,
"]}");
186 out[n < cap ? n : cap - 1] =
'\0';
Pluggable monotonic clock for all library timing.
uint32_t pc_millis(void)
The library's monotonic time at 1000 Hz (milliseconds).
Software watchdog: deadlock detection + fail-safe safe-state (PC_ENABLE_FAILSAFE).
uint32_t mask(uint8_t width)
Mask of width low bits (width 32 handled without a 32-bit shift, which is UB).
#define PC_FAILSAFE_MAX_LIFELINES
Max monitored lifelines in the fail-safe registry (static, zero-heap).