blob: 87281119faa685fb0e28b8775a421ce73a8d70ff [file] [log] [blame]
Austin Schuh54cf95f2019-11-29 13:14:18 -08001#include "aos/events/event_loop.h"
2
3#include "aos/configuration.h"
4#include "aos/configuration_generated.h"
Tyler Chatow67ddb032020-01-12 14:30:04 -08005#include "aos/logging/implementations.h"
Austin Schuh54cf95f2019-11-29 13:14:18 -08006#include "glog/logging.h"
7
Austin Schuh39788ff2019-12-01 18:22:57 -08008DEFINE_bool(timing_reports, true, "Publish timing reports.");
9DEFINE_int32(timing_report_ms, 1000,
10 "Period in milliseconds to publish timing reports at.");
11
Austin Schuh54cf95f2019-11-29 13:14:18 -080012namespace aos {
Austin Schuhd54780b2020-10-03 16:26:02 -070013namespace {
14void CheckAlignment(const Channel *channel) {
15 if (channel->max_size() % alignof(flatbuffers::largest_scalar_t) != 0) {
16 LOG(FATAL) << "max_size() (" << channel->max_size()
17 << ") is not a multiple of alignment ("
18 << alignof(flatbuffers::largest_scalar_t) << ") for channel "
19 << configuration::CleanedChannelToString(channel) << ".";
20 }
21}
22} // namespace
Austin Schuh54cf95f2019-11-29 13:14:18 -080023
Austin Schuh39788ff2019-12-01 18:22:57 -080024RawSender::RawSender(EventLoop *event_loop, const Channel *channel)
25 : event_loop_(event_loop),
26 channel_(channel),
Brian Silverman79ec7fc2020-06-08 20:11:22 -050027 ftrace_prefix_(configuration::StrippedChannelToString(channel)),
Austin Schuh39788ff2019-12-01 18:22:57 -080028 timing_(event_loop_->ChannelIndex(channel)) {
29 event_loop_->NewSender(this);
30}
31
32RawSender::~RawSender() { event_loop_->DeleteSender(this); }
33
34RawFetcher::RawFetcher(EventLoop *event_loop, const Channel *channel)
35 : event_loop_(event_loop),
36 channel_(channel),
Brian Silverman79ec7fc2020-06-08 20:11:22 -050037 ftrace_prefix_(configuration::StrippedChannelToString(channel)),
Austin Schuh39788ff2019-12-01 18:22:57 -080038 timing_(event_loop_->ChannelIndex(channel)) {
Austin Schuhad154822019-12-27 15:45:13 -080039 context_.monotonic_event_time = monotonic_clock::min_time;
40 context_.monotonic_remote_time = monotonic_clock::min_time;
41 context_.realtime_event_time = realtime_clock::min_time;
42 context_.realtime_remote_time = realtime_clock::min_time;
Austin Schuh39788ff2019-12-01 18:22:57 -080043 context_.queue_index = 0xffffffff;
44 context_.size = 0;
45 context_.data = nullptr;
Brian Silverman4f4e0612020-08-12 19:54:41 -070046 context_.buffer_index = -1;
Austin Schuh39788ff2019-12-01 18:22:57 -080047 event_loop_->NewFetcher(this);
48}
49
50RawFetcher::~RawFetcher() { event_loop_->DeleteFetcher(this); }
51
52TimerHandler::TimerHandler(EventLoop *event_loop, std::function<void()> fn)
53 : event_loop_(event_loop), fn_(std::move(fn)) {}
54
55TimerHandler::~TimerHandler() {}
56
57PhasedLoopHandler::PhasedLoopHandler(EventLoop *event_loop,
58 std::function<void(int)> fn,
59 const monotonic_clock::duration interval,
60 const monotonic_clock::duration offset)
61 : event_loop_(event_loop),
62 fn_(std::move(fn)),
63 phased_loop_(interval, event_loop_->monotonic_now(), offset) {
64 event_loop_->OnRun([this]() {
65 const monotonic_clock::time_point monotonic_now =
66 event_loop_->monotonic_now();
67 phased_loop_.Reset(monotonic_now);
68 Reschedule(
69 [this](monotonic_clock::time_point sleep_time) {
70 Schedule(sleep_time);
71 },
72 monotonic_now);
Milind Upadhyay42589bb2021-05-19 20:05:16 -070073 // Reschedule here will count cycles elapsed before now, and then the
74 // reschedule before running the handler will count the time that elapsed
75 // then. So clear the count here.
Austin Schuh39788ff2019-12-01 18:22:57 -080076 cycles_elapsed_ = 0;
77 });
78}
79
80PhasedLoopHandler::~PhasedLoopHandler() {}
81
Austin Schuh83c7f702021-01-19 22:36:29 -080082EventLoop::EventLoop(const Configuration *configuration)
83 : timing_report_(flatbuffers::DetachedBuffer()),
Austin Schuh56196432020-10-24 20:15:21 -070084 configuration_(configuration) {}
Tyler Chatow67ddb032020-01-12 14:30:04 -080085
Austin Schuh39788ff2019-12-01 18:22:57 -080086EventLoop::~EventLoop() {
Austin Schuh58646e22021-08-23 23:51:46 -070087 if(!senders_.empty()) {
88 for (const RawSender *sender : senders_) {
89 LOG(ERROR) << " Sender "
90 << configuration::StrippedChannelToString(sender->channel())
91 << " still open";
92 }
93 }
Austin Schuh39788ff2019-12-01 18:22:57 -080094 CHECK_EQ(senders_.size(), 0u) << ": Not all senders destroyed";
Austin Schuh7d87b672019-12-01 20:23:49 -080095 CHECK_EQ(events_.size(), 0u) << ": Not all events unregistered";
Austin Schuh39788ff2019-12-01 18:22:57 -080096}
97
98int EventLoop::ChannelIndex(const Channel *channel) {
Austin Schuhc9e10ec2020-01-26 16:08:28 -080099 return configuration::ChannelIndex(configuration_, channel);
Austin Schuh39788ff2019-12-01 18:22:57 -0800100}
101
Brian Silverman5120afb2020-01-31 17:44:35 -0800102WatcherState *EventLoop::GetWatcherState(const Channel *channel) {
103 const int channel_index = ChannelIndex(channel);
104 for (const std::unique_ptr<WatcherState> &watcher : watchers_) {
105 if (watcher->channel_index() == channel_index) {
106 return watcher.get();
107 }
108 }
109 LOG(FATAL) << "No watcher found for channel";
110}
111
Austin Schuh39788ff2019-12-01 18:22:57 -0800112void EventLoop::NewSender(RawSender *sender) {
113 senders_.emplace_back(sender);
114 UpdateTimingReport();
115}
116void EventLoop::DeleteSender(RawSender *sender) {
117 CHECK(!is_running());
118 auto s = std::find(senders_.begin(), senders_.end(), sender);
119 CHECK(s != senders_.end()) << ": Sender not in senders list";
120 senders_.erase(s);
121 UpdateTimingReport();
122}
123
124TimerHandler *EventLoop::NewTimer(std::unique_ptr<TimerHandler> timer) {
125 timers_.emplace_back(std::move(timer));
126 UpdateTimingReport();
127 return timers_.back().get();
128}
129
130PhasedLoopHandler *EventLoop::NewPhasedLoop(
131 std::unique_ptr<PhasedLoopHandler> phased_loop) {
132 phased_loops_.emplace_back(std::move(phased_loop));
133 UpdateTimingReport();
134 return phased_loops_.back().get();
135}
136
137void EventLoop::NewFetcher(RawFetcher *fetcher) {
Austin Schuhd54780b2020-10-03 16:26:02 -0700138 CheckAlignment(fetcher->channel());
139
Austin Schuh39788ff2019-12-01 18:22:57 -0800140 fetchers_.emplace_back(fetcher);
141 UpdateTimingReport();
142}
143
144void EventLoop::DeleteFetcher(RawFetcher *fetcher) {
145 CHECK(!is_running());
146 auto f = std::find(fetchers_.begin(), fetchers_.end(), fetcher);
147 CHECK(f != fetchers_.end()) << ": Fetcher not in fetchers list";
148 fetchers_.erase(f);
149 UpdateTimingReport();
150}
151
152WatcherState *EventLoop::NewWatcher(std::unique_ptr<WatcherState> watcher) {
153 watchers_.emplace_back(std::move(watcher));
154
155 UpdateTimingReport();
156
157 return watchers_.back().get();
158}
159
Brian Silverman0fc69932020-01-24 21:54:02 -0800160void EventLoop::TakeWatcher(const Channel *channel) {
161 CHECK(!is_running()) << ": Cannot add new objects while running.";
162 ChannelIndex(channel);
163
Austin Schuhd54780b2020-10-03 16:26:02 -0700164 CheckAlignment(channel);
165
Brian Silverman0fc69932020-01-24 21:54:02 -0800166 CHECK(taken_senders_.find(channel) == taken_senders_.end())
Austin Schuh8072f922020-02-16 21:51:47 -0800167 << ": " << configuration::CleanedChannelToString(channel)
168 << " is already being used.";
Brian Silverman0fc69932020-01-24 21:54:02 -0800169
170 auto result = taken_watchers_.insert(channel);
Austin Schuh8072f922020-02-16 21:51:47 -0800171 CHECK(result.second) << ": " << configuration::CleanedChannelToString(channel)
Brian Silverman0fc69932020-01-24 21:54:02 -0800172 << " is already being used.";
173
174 if (!configuration::ChannelIsReadableOnNode(channel, node())) {
Austin Schuh8072f922020-02-16 21:51:47 -0800175 LOG(FATAL) << ": " << configuration::CleanedChannelToString(channel)
Brian Silverman0fc69932020-01-24 21:54:02 -0800176 << " is not able to be watched on this node. Check your "
177 "configuration.";
178 }
179}
180
181void EventLoop::TakeSender(const Channel *channel) {
182 CHECK(!is_running()) << ": Cannot add new objects while running.";
183 ChannelIndex(channel);
184
Austin Schuhd54780b2020-10-03 16:26:02 -0700185 CheckAlignment(channel);
186
Brian Silverman0fc69932020-01-24 21:54:02 -0800187 CHECK(taken_watchers_.find(channel) == taken_watchers_.end())
Austin Schuh8072f922020-02-16 21:51:47 -0800188 << ": Channel " << configuration::CleanedChannelToString(channel)
189 << " is already being used.";
Brian Silverman0fc69932020-01-24 21:54:02 -0800190
191 // We don't care if this is a duplicate.
192 taken_senders_.insert(channel);
193}
194
Austin Schuh39788ff2019-12-01 18:22:57 -0800195void EventLoop::SendTimingReport() {
196 // We need to do a fancy dance here to get all the accounting to work right.
197 // We want to copy the memory here, but then send after resetting. Otherwise
198 // the send for the timing report won't be counted in the timing report.
199 //
200 // Also, flatbuffers build from the back end. So place this at the back end
201 // of the buffer. We only have to care because we are using this in a very
202 // raw fashion.
Austin Schuhadd6eb32020-11-09 21:24:26 -0800203 CHECK_LE(timing_report_.span().size(), timing_report_sender_->size())
Austin Schuh39788ff2019-12-01 18:22:57 -0800204 << ": Timing report bigger than the sender size.";
Austin Schuhadd6eb32020-11-09 21:24:26 -0800205 std::copy(timing_report_.span().data(),
206 timing_report_.span().data() + timing_report_.span().size(),
Austin Schuh39788ff2019-12-01 18:22:57 -0800207 reinterpret_cast<uint8_t *>(timing_report_sender_->data()) +
Austin Schuhadd6eb32020-11-09 21:24:26 -0800208 timing_report_sender_->size() - timing_report_.span().size());
Austin Schuh39788ff2019-12-01 18:22:57 -0800209
210 for (const std::unique_ptr<TimerHandler> &timer : timers_) {
211 timer->timing_.ResetTimingReport();
212 }
213 for (const std::unique_ptr<WatcherState> &watcher : watchers_) {
214 watcher->ResetReport();
215 }
216 for (const std::unique_ptr<PhasedLoopHandler> &phased_loop : phased_loops_) {
217 phased_loop->timing_.ResetTimingReport();
218 }
219 for (RawSender *sender : senders_) {
220 sender->timing_.ResetTimingReport();
221 }
222 for (RawFetcher *fetcher : fetchers_) {
223 fetcher->timing_.ResetTimingReport();
224 }
Austin Schuhadd6eb32020-11-09 21:24:26 -0800225 timing_report_sender_->Send(timing_report_.span().size());
Austin Schuh39788ff2019-12-01 18:22:57 -0800226}
227
228void EventLoop::UpdateTimingReport() {
229 // We need to support senders and fetchers changing while we are setting up
230 // the event loop. Otherwise we can't fetch or send until the loop runs. This
231 // means that on each change, we need to redo all this work. This makes setup
232 // more expensive, but not by all that much on a modern processor.
233
234 // Now, build up a report with everything pre-filled out.
235 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -0800236 fbb.ForceDefaults(true);
Austin Schuh39788ff2019-12-01 18:22:57 -0800237
238 // Pre-fill in the defaults for timers.
239 std::vector<flatbuffers::Offset<timing::Timer>> timer_offsets;
240 for (const std::unique_ptr<TimerHandler> &timer : timers_) {
241 flatbuffers::Offset<timing::Statistic> wakeup_latency_offset =
242 timing::CreateStatistic(fbb);
243 flatbuffers::Offset<timing::Statistic> handler_time_offset =
244 timing::CreateStatistic(fbb);
245 flatbuffers::Offset<flatbuffers::String> name_offset;
246 if (timer->name().size() != 0) {
247 name_offset = fbb.CreateString(timer->name());
248 }
249
250 timing::Timer::Builder timer_builder(fbb);
251
252 if (timer->name().size() != 0) {
253 timer_builder.add_name(name_offset);
254 }
255 timer_builder.add_wakeup_latency(wakeup_latency_offset);
256 timer_builder.add_handler_time(handler_time_offset);
257 timer_builder.add_count(0);
258 timer_offsets.emplace_back(timer_builder.Finish());
259 }
260
261 // Pre-fill in the defaults for phased_loops.
262 std::vector<flatbuffers::Offset<timing::Timer>> phased_loop_offsets;
263 for (const std::unique_ptr<PhasedLoopHandler> &phased_loop : phased_loops_) {
264 flatbuffers::Offset<timing::Statistic> wakeup_latency_offset =
265 timing::CreateStatistic(fbb);
266 flatbuffers::Offset<timing::Statistic> handler_time_offset =
267 timing::CreateStatistic(fbb);
268 flatbuffers::Offset<flatbuffers::String> name_offset;
269 if (phased_loop->name().size() != 0) {
270 name_offset = fbb.CreateString(phased_loop->name());
271 }
272
273 timing::Timer::Builder timer_builder(fbb);
274
275 if (phased_loop->name().size() != 0) {
276 timer_builder.add_name(name_offset);
277 }
278 timer_builder.add_wakeup_latency(wakeup_latency_offset);
279 timer_builder.add_handler_time(handler_time_offset);
280 timer_builder.add_count(0);
281 phased_loop_offsets.emplace_back(timer_builder.Finish());
282 }
283
284 // Pre-fill in the defaults for watchers.
285 std::vector<flatbuffers::Offset<timing::Watcher>> watcher_offsets;
286 for (const std::unique_ptr<WatcherState> &watcher : watchers_) {
287 flatbuffers::Offset<timing::Statistic> wakeup_latency_offset =
288 timing::CreateStatistic(fbb);
289 flatbuffers::Offset<timing::Statistic> handler_time_offset =
290 timing::CreateStatistic(fbb);
291
292 timing::Watcher::Builder watcher_builder(fbb);
293
294 watcher_builder.add_channel_index(watcher->channel_index());
295 watcher_builder.add_wakeup_latency(wakeup_latency_offset);
296 watcher_builder.add_handler_time(handler_time_offset);
297 watcher_builder.add_count(0);
298 watcher_offsets.emplace_back(watcher_builder.Finish());
299 }
300
301 // Pre-fill in the defaults for senders.
302 std::vector<flatbuffers::Offset<timing::Sender>> sender_offsets;
303 for (const RawSender *sender : senders_) {
304 flatbuffers::Offset<timing::Statistic> size_offset =
305 timing::CreateStatistic(fbb);
306
307 timing::Sender::Builder sender_builder(fbb);
308
309 sender_builder.add_channel_index(sender->timing_.channel_index);
310 sender_builder.add_size(size_offset);
311 sender_builder.add_count(0);
312 sender_offsets.emplace_back(sender_builder.Finish());
313 }
314
315 // Pre-fill in the defaults for fetchers.
316 std::vector<flatbuffers::Offset<timing::Fetcher>> fetcher_offsets;
317 for (RawFetcher *fetcher : fetchers_) {
318 flatbuffers::Offset<timing::Statistic> latency_offset =
319 timing::CreateStatistic(fbb);
320
321 timing::Fetcher::Builder fetcher_builder(fbb);
322
323 fetcher_builder.add_channel_index(fetcher->timing_.channel_index);
324 fetcher_builder.add_count(0);
325 fetcher_builder.add_latency(latency_offset);
326 fetcher_offsets.emplace_back(fetcher_builder.Finish());
327 }
328
329 // Then build the final report.
330 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<timing::Timer>>>
331 timers_offset;
332 if (timer_offsets.size() > 0) {
333 timers_offset = fbb.CreateVector(timer_offsets);
334 }
335
336 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<timing::Timer>>>
337 phased_loops_offset;
338 if (phased_loop_offsets.size() > 0) {
339 phased_loops_offset = fbb.CreateVector(phased_loop_offsets);
340 }
341
342 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<timing::Watcher>>>
343 watchers_offset;
344 if (watcher_offsets.size() > 0) {
345 watchers_offset = fbb.CreateVector(watcher_offsets);
346 }
347
348 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<timing::Sender>>>
349 senders_offset;
350 if (sender_offsets.size() > 0) {
351 senders_offset = fbb.CreateVector(sender_offsets);
352 }
353
354 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<timing::Fetcher>>>
355 fetchers_offset;
356 if (fetcher_offsets.size() > 0) {
357 fetchers_offset = fbb.CreateVector(fetcher_offsets);
358 }
359
360 flatbuffers::Offset<flatbuffers::String> name_offset =
361 fbb.CreateString(name());
362
363 timing::Report::Builder report_builder(fbb);
364 report_builder.add_name(name_offset);
365 report_builder.add_pid(GetTid());
366 if (timer_offsets.size() > 0) {
367 report_builder.add_timers(timers_offset);
368 }
369 if (phased_loop_offsets.size() > 0) {
370 report_builder.add_phased_loops(phased_loops_offset);
371 }
372 if (watcher_offsets.size() > 0) {
373 report_builder.add_watchers(watchers_offset);
374 }
375 if (sender_offsets.size() > 0) {
376 report_builder.add_senders(senders_offset);
377 }
378 if (fetcher_offsets.size() > 0) {
379 report_builder.add_fetchers(fetchers_offset);
380 }
381 fbb.Finish(report_builder.Finish());
382
383 timing_report_ = FlatbufferDetachedBuffer<timing::Report>(fbb.Release());
384
385 // Now that the pointers are stable, pass them to the timers and watchers to
386 // be updated.
387 for (size_t i = 0; i < timers_.size(); ++i) {
388 timers_[i]->timing_.set_timing_report(
389 timing_report_.mutable_message()->mutable_timers()->GetMutableObject(
390 i));
391 }
392
393 for (size_t i = 0; i < phased_loops_.size(); ++i) {
394 phased_loops_[i]->timing_.set_timing_report(
395 timing_report_.mutable_message()
396 ->mutable_phased_loops()
397 ->GetMutableObject(i));
398 }
399
400 for (size_t i = 0; i < watchers_.size(); ++i) {
401 watchers_[i]->set_timing_report(
402 timing_report_.mutable_message()->mutable_watchers()->GetMutableObject(
403 i));
404 }
405
406 for (size_t i = 0; i < senders_.size(); ++i) {
407 senders_[i]->timing_.set_timing_report(
408 timing_report_.mutable_message()->mutable_senders()->GetMutableObject(
409 i));
410 }
411
412 for (size_t i = 0; i < fetchers_.size(); ++i) {
413 fetchers_[i]->timing_.set_timing_report(
414 timing_report_.mutable_message()->mutable_fetchers()->GetMutableObject(
415 i));
416 }
417}
418
419void EventLoop::MaybeScheduleTimingReports() {
420 if (FLAGS_timing_reports && !skip_timing_report_) {
421 CHECK(!timing_report_sender_) << ": Timing reports already scheduled.";
422 // Make a raw sender for the report.
423 const Channel *channel = configuration::GetChannel(
424 configuration(), "/aos", timing::Report::GetFullyQualifiedName(),
Austin Schuhbca6cf02019-12-22 17:28:34 -0800425 name(), node());
Austin Schuh196a4452020-03-15 23:12:03 -0700426 CHECK(channel != nullptr) << ": Failed to look up {\"name\": \"/aos\", "
427 "\"type\": \"aos.timing.Report\"} on node "
428 << FlatbufferToJson(node());
Austin Schuhbca6cf02019-12-22 17:28:34 -0800429
430 // Since we are using a RawSender, validity isn't checked. So check it
431 // ourselves.
Austin Schuhca4828c2019-12-28 14:21:35 -0800432 if (!configuration::ChannelIsSendableOnNode(channel, node())) {
433 LOG(FATAL) << "Channel { \"name\": \"/aos"
434 << channel->name()->string_view() << "\", \"type\": \""
435 << channel->type()->string_view()
436 << "\" } is not able to be sent on this node. Check your "
437 "configuration.";
Austin Schuhbca6cf02019-12-22 17:28:34 -0800438 }
Austin Schuh39788ff2019-12-01 18:22:57 -0800439 CHECK(channel != nullptr) << ": Channel { \"name\": \"/aos\", \"type\": \""
440 << timing::Report::GetFullyQualifiedName()
441 << "\" } not found in config.";
442 timing_report_sender_ = MakeRawSender(channel);
443
444 // Register a handler which sends the report out by copying the raw data
445 // from the prebuilt and subsequently modified report.
446 TimerHandler *timing_reports_timer =
447 AddTimer([this]() { SendTimingReport(); });
448
449 // Set it up to send once per second.
450 timing_reports_timer->set_name("timing_reports");
451 OnRun([this, timing_reports_timer]() {
452 timing_reports_timer->Setup(
453 monotonic_now() + std::chrono::milliseconds(FLAGS_timing_report_ms),
454 std::chrono::milliseconds(FLAGS_timing_report_ms));
455 });
456
457 UpdateTimingReport();
458 }
459}
460
Austin Schuh7d87b672019-12-01 20:23:49 -0800461void EventLoop::ReserveEvents() {
462 events_.reserve(timers_.size() + phased_loops_.size() + watchers_.size());
463}
464
465namespace {
466bool CompareEvents(const EventLoopEvent *first, const EventLoopEvent *second) {
Brian Silvermanbd405c02020-06-23 16:25:23 -0700467 if (first->event_time() > second->event_time()) {
468 return true;
469 }
470 if (first->event_time() < second->event_time()) {
471 return false;
472 }
473 return first->generation() > second->generation();
Austin Schuh7d87b672019-12-01 20:23:49 -0800474}
475} // namespace
476
477void EventLoop::AddEvent(EventLoopEvent *event) {
478 DCHECK(std::find(events_.begin(), events_.end(), event) == events_.end());
Brian Silvermanbd405c02020-06-23 16:25:23 -0700479 DCHECK(event->generation() == 0);
480 event->set_generation(++event_generation_);
Austin Schuh7d87b672019-12-01 20:23:49 -0800481 events_.push_back(event);
482 std::push_heap(events_.begin(), events_.end(), CompareEvents);
483}
484
485void EventLoop::RemoveEvent(EventLoopEvent *event) {
486 auto e = std::find(events_.begin(), events_.end(), event);
487 if (e != events_.end()) {
Brian Silvermanbd405c02020-06-23 16:25:23 -0700488 DCHECK(event->generation() != 0);
Austin Schuh7d87b672019-12-01 20:23:49 -0800489 events_.erase(e);
490 std::make_heap(events_.begin(), events_.end(), CompareEvents);
491 event->Invalidate();
492 }
493}
494
495EventLoopEvent *EventLoop::PopEvent() {
496 EventLoopEvent *result = events_.front();
497 std::pop_heap(events_.begin(), events_.end(), CompareEvents);
498 events_.pop_back();
499 result->Invalidate();
500 return result;
501}
502
Austin Schuha9012be2021-07-21 15:19:11 -0700503void EventLoop::SetTimerContext(
504 monotonic_clock::time_point monotonic_event_time) {
505 context_.monotonic_event_time = monotonic_event_time;
506 context_.monotonic_remote_time = monotonic_clock::min_time;
507 context_.realtime_event_time = realtime_clock::min_time;
508 context_.realtime_remote_time = realtime_clock::min_time;
509 context_.queue_index = 0xffffffffu;
510 context_.size = 0u;
511 context_.data = nullptr;
512 context_.buffer_index = -1;
513 context_.source_boot_uuid = boot_uuid();
514}
515
Austin Schuh39788ff2019-12-01 18:22:57 -0800516void WatcherState::set_timing_report(timing::Watcher *watcher) {
517 CHECK_NOTNULL(watcher);
518 watcher_ = watcher;
519 wakeup_latency_.set_statistic(watcher->mutable_wakeup_latency());
520 handler_time_.set_statistic(watcher->mutable_handler_time());
521}
522
523void WatcherState::ResetReport() {
524 wakeup_latency_.Reset();
525 handler_time_.Reset();
526 watcher_->mutate_count(0);
Austin Schuh54cf95f2019-11-29 13:14:18 -0800527}
528
529} // namespace aos