uc_scheduler.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
6 #include <uavcan/debug.hpp>
7 #include <cassert>
8 
9 namespace uavcan
10 {
11 /*
12  * MonotonicDeadlineHandler
13  */
15 {
16  UAVCAN_ASSERT(!deadline.isZero());
17  stop();
18  deadline_ = deadline;
20 }
21 
23 {
25 }
26 
28 {
30 }
31 
33 {
35 }
36 
37 /*
38  * MonotonicDeadlineScheduler
39  */
41 {
44  bool operator()(const DeadlineHandler* t) const
45  {
46  return t->getDeadline() > ts;
47  }
48 };
49 
51 {
52  UAVCAN_ASSERT(mdh);
53  handlers_.insertBefore(mdh, MonotonicDeadlineHandlerInsertionComparator(mdh->getDeadline()));
54 }
55 
57 {
58  UAVCAN_ASSERT(mdh);
59  handlers_.remove(mdh);
60 }
61 
63 {
64  UAVCAN_ASSERT(mdh);
65  const DeadlineHandler* p = handlers_.get();
66 #if UAVCAN_DEBUG
67  MonotonicTime prev_deadline;
68 #endif
69  while (p)
70  {
71 #if UAVCAN_DEBUG
72  if (prev_deadline > p->getDeadline()) // Self check
73  {
74  std::abort();
75  }
76  prev_deadline = p->getDeadline();
77 #endif
78  if (p == mdh)
79  {
80  return true;
81  }
82  p = p->getNextListNode();
83  }
84  return false;
85 }
86 
88 {
89  while (true)
90  {
91  DeadlineHandler* const mdh = handlers_.get();
92  if (!mdh)
93  {
94  return sysclock.getMonotonic();
95  }
96 #if UAVCAN_DEBUG
97  if (mdh->getNextListNode()) // Order check
98  {
100  }
101 #endif
102 
103  const MonotonicTime ts = sysclock.getMonotonic();
104  if (ts < mdh->getDeadline())
105  {
106  return ts;
107  }
108 
109  handlers_.remove(mdh);
110  mdh->handleDeadline(ts); // This handler can be re-registered immediately
111  }
112  UAVCAN_ASSERT(0);
113  return MonotonicTime();
114 }
115 
117 {
118  const DeadlineHandler* const mdh = handlers_.get();
119  if (mdh)
120  {
121  return mdh->getDeadline();
122  }
123  return MonotonicTime::getMax();
124 }
125 
126 /*
127  * Scheduler
128  */
130 {
131  const MonotonicTime earliest = min(deadline_scheduler_.getEarliestDeadline(), spin_deadline);
132  const MonotonicTime ts = getMonotonicTime();
133  if (earliest > ts)
134  {
135  if (earliest - ts > deadline_resolution_)
136  {
137  return ts + deadline_resolution_;
138  }
139  }
140  return earliest;
141 }
142 
143 void Scheduler::pollCleanup(MonotonicTime mono_ts, uint32_t num_frames_processed_with_last_spin)
144 {
145  // cleanup will be performed less frequently if the stack handles more frames per second
146  const MonotonicTime deadline = prev_cleanup_ts_ + cleanup_period_ * (num_frames_processed_with_last_spin + 1);
147  if (mono_ts > deadline)
148  {
149  //UAVCAN_TRACE("Scheduler", "Cleanup with %u processed frames", num_frames_processed_with_last_spin);
150  prev_cleanup_ts_ = mono_ts;
151  dispatcher_.cleanup(mono_ts);
152  }
153 }
154 
156 {
157  if (inside_spin_) // Preventing recursive calls
158  {
159  UAVCAN_ASSERT(0);
160  return -ErrRecursiveCall;
161  }
162  InsideSpinSetter iss(*this);
163  UAVCAN_ASSERT(inside_spin_);
164 
165  int retval = 0;
166  while (true)
167  {
168  const MonotonicTime dl = computeDispatcherSpinDeadline(deadline);
169  retval = dispatcher_.spin(dl);
170  if (retval < 0)
171  {
172  break;
173  }
174 
175  const MonotonicTime ts = deadline_scheduler_.pollAndGetMonotonicTime(getSystemClock());
176  pollCleanup(ts, unsigned(retval));
177  if (ts >= deadline)
178  {
179  break;
180  }
181  }
182 
183  return retval;
184 }
185 
187 {
188  if (inside_spin_) // Preventing recursive calls
189  {
190  UAVCAN_ASSERT(0);
191  return -ErrRecursiveCall;
192  }
193  InsideSpinSetter iss(*this);
194  UAVCAN_ASSERT(inside_spin_);
195 
196  const int retval = dispatcher_.spinOnce();
197  if (retval < 0)
198  {
199  return retval;
200  }
201 
202  const MonotonicTime ts = deadline_scheduler_.pollAndGetMonotonicTime(getSystemClock());
203  pollCleanup(ts, unsigned(retval));
204 
205  return retval;
206 }
207 
208 }
void startWithDeadline(MonotonicTime deadline)
void pollCleanup(MonotonicTime mono_ts, uint32_t num_frames_processed_with_last_spin)
virtual MonotonicTime getMonotonic() const =0
bool isZero() const
Definition: time.hpp:123
MonotonicTime getEarliestDeadline() const
MonotonicTime getMonotonicTime() const
Definition: scheduler.hpp:123
bool operator()(const DeadlineHandler *t) const
MonotonicTime pollAndGetMonotonicTime(ISystemClock &sysclock)
bool doesExist(const DeadlineHandler *mdh) const
Scheduler & scheduler_
Definition: scheduler.hpp:22
uavcan::ISystemClock & getSystemClock()
void startWithDelay(MonotonicDuration delay)
MonotonicDeadlineHandlerInsertionComparator(MonotonicTime arg_ts)
MonotonicTime computeDispatcherSpinDeadline(MonotonicTime spin_deadline) const
T * getNextListNode() const
Definition: linked_list.hpp:32
void add(DeadlineHandler *mdh)
std::uint32_t uint32_t
Definition: std.hpp:26
MonotonicTime getDeadline() const
Definition: scheduler.hpp:41
UAVCAN_EXPORT const T & min(const T &a, const T &b)
Definition: templates.hpp:281
void remove(DeadlineHandler *mdh)
int spin(MonotonicTime deadline)
virtual void handleDeadline(MonotonicTime current)=0
MonotonicTime deadline_
Definition: scheduler.hpp:19
DeadlineScheduler & getDeadlineScheduler()
Definition: scheduler.hpp:117


uavcan_communicator
Author(s):
autogenerated on Wed Jan 11 2023 03:59:40