Skip to content

Commit 1319de9

Browse files
committed
[fiber] Guarantee minimum for durations < 1µs
1 parent e75fae5 commit 1319de9

File tree

2 files changed

+59
-16
lines changed

2 files changed

+59
-16
lines changed

src/modm/processing/fiber/functions.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,16 @@ poll_for(std::chrono::duration<Rep, Period> sleep_duration, Function &&condition
9090
std::chrono::duration<Rep, std::milli>>,
9191
modm::chrono::milli_clock, modm::chrono::micro_clock>;
9292

93+
// Ensure the sleep duration is rounded up to the next full clock tick
94+
const auto clock_sleep_duration(
95+
std::chrono::ceil<typename Clock::duration>(sleep_duration));
96+
9397
const auto start = Clock::now();
9498
do {
9599
modm::this_fiber::yield();
96100
if (std::forward<Function>(condition)()) return true;
97101
}
98-
while((Clock::now() - start) <= sleep_duration);
102+
while((Clock::now() - start) < clock_sleep_duration);
99103
return false;
100104
}
101105

@@ -125,7 +129,7 @@ poll_until(std::chrono::time_point<Clock, Duration> sleep_time, Function &&condi
125129
modm::this_fiber::yield();
126130
if (std::forward<Function>(condition)()) return true;
127131
}
128-
while((Clock::now() - start) <= sleep_duration);
132+
while((Clock::now() - start) < sleep_duration);
129133
return false;
130134
}
131135

test/modm/processing/fiber/fiber_test.cpp

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
#include <modm-test/mock/clock.hpp>
1717

1818
using namespace std::chrono_literals;
19-
using test_clock = modm_test::chrono::milli_clock;
19+
using test_clock_ms = modm_test::chrono::milli_clock;
20+
using test_clock_us = modm_test::chrono::micro_clock;
2021

2122
void
2223
FiberTest::setUp()
@@ -103,7 +104,7 @@ FiberTest::testYieldFromSubroutine()
103104
void
104105
FiberTest::testPollFor()
105106
{
106-
test_clock::setTime(1251);
107+
test_clock_ms::setTime(1251);
107108
TEST_ASSERT_TRUE(modm::this_fiber::poll_for(20ms, []{ return true; }));
108109
// timeout is tested in the SleepFor() test
109110
}
@@ -112,7 +113,7 @@ FiberTest::testPollFor()
112113
void
113114
FiberTest::testPollUntil()
114115
{
115-
test_clock::setTime(451250);
116+
test_clock_ms::setTime(451250);
116117
TEST_ASSERT_TRUE(modm::this_fiber::poll_until(modm::Clock::now() + 20ms, []{ return true; }));
117118
TEST_ASSERT_TRUE(modm::this_fiber::poll_until(modm::Clock::now() - 20ms, []{ return true; }));
118119
// timeout is tested in the SleepUntil() tests
@@ -123,33 +124,52 @@ static void
123124
f4()
124125
{
125126
TEST_ASSERT_EQUALS(state++, 0u);
126-
modm::this_fiber::sleep_for(50ms); // goto 1
127+
// yields only once
128+
modm::this_fiber::sleep_for(0s); // goto 1
129+
130+
TEST_ASSERT_EQUALS(state++, 2u);
131+
// rounds up to 1us, not 0us!
132+
modm::this_fiber::sleep_for(100ns); // goto 3
133+
127134
TEST_ASSERT_EQUALS(state++, 5u);
135+
modm::this_fiber::sleep_for(50ms); // goto 6
136+
TEST_ASSERT_EQUALS(state++, 10u);
128137
}
129138

130139
static void
131140
f5()
132141
{
133142
TEST_ASSERT_EQUALS(state++, 1u);
134-
test_clock::increment(10);
135-
TEST_ASSERT_EQUALS(state++, 2u);
136-
modm::this_fiber::yield();
143+
modm::this_fiber::yield(); // goto 2
137144

138-
test_clock::increment(20);
139145
TEST_ASSERT_EQUALS(state++, 3u);
140146
modm::this_fiber::yield();
141147

142-
test_clock::increment(30);
143148
TEST_ASSERT_EQUALS(state++, 4u);
149+
test_clock_us::increment(1);
144150
modm::this_fiber::yield(); // goto 5
145151

146152
TEST_ASSERT_EQUALS(state++, 6u);
153+
test_clock_ms::increment(10);
154+
TEST_ASSERT_EQUALS(state++, 7u);
155+
modm::this_fiber::yield();
156+
157+
test_clock_ms::increment(20);
158+
TEST_ASSERT_EQUALS(state++, 8u);
159+
modm::this_fiber::yield();
160+
161+
test_clock_ms::increment(30);
162+
TEST_ASSERT_EQUALS(state++, 9u);
163+
modm::this_fiber::yield(); // goto 10
164+
165+
TEST_ASSERT_EQUALS(state++, 11u);
147166
}
148167

149168
static void
150169
runSleepFor(uint32_t startTime)
151170
{
152-
test_clock::setTime(startTime);
171+
test_clock_ms::setTime(startTime);
172+
test_clock_us::setTime(startTime);
153173
modm::fiber::Task fiber1(stack1, f4), fiber2(stack2, f5);
154174
modm::fiber::Scheduler::run();
155175
}
@@ -165,6 +185,25 @@ FiberTest::testSleepFor()
165185

166186
static void
167187
f6()
188+
{
189+
TEST_ASSERT_EQUALS(state++, 1u);
190+
test_clock_ms::increment(10);
191+
TEST_ASSERT_EQUALS(state++, 2u);
192+
modm::this_fiber::yield();
193+
194+
test_clock_ms::increment(20);
195+
TEST_ASSERT_EQUALS(state++, 3u);
196+
modm::this_fiber::yield();
197+
198+
test_clock_ms::increment(30);
199+
TEST_ASSERT_EQUALS(state++, 4u);
200+
modm::this_fiber::yield(); // goto 5
201+
202+
TEST_ASSERT_EQUALS(state++, 6u);
203+
}
204+
205+
static void
206+
f7()
168207
{
169208
TEST_ASSERT_EQUALS(state++, 0u); // goto 1
170209
modm::this_fiber::sleep_until(modm::Clock::now() + 50ms);
@@ -177,8 +216,8 @@ f6()
177216
static void
178217
runSleepUntil(uint32_t startTime)
179218
{
180-
test_clock::setTime(startTime);
181-
modm::fiber::Task fiber1(stack1, f6), fiber2(stack2, f5);
219+
test_clock_ms::setTime(startTime);
220+
modm::fiber::Task fiber1(stack1, f7), fiber2(stack2, f6);
182221
modm::fiber::Scheduler::run();
183222
}
184223

@@ -191,7 +230,7 @@ FiberTest::testSleepUntil()
191230
}
192231

193232
static void
194-
f7(modm::fiber::stop_token stoken)
233+
f8(modm::fiber::stop_token stoken)
195234
{
196235
TEST_ASSERT_EQUALS(state++, 0u);
197236
TEST_ASSERT_TRUE(stoken.stop_possible());
@@ -208,7 +247,7 @@ f7(modm::fiber::stop_token stoken)
208247
void
209248
FiberTest::testStopToken()
210249
{
211-
modm::fiber::Task fiber1(stack1, f7);
250+
modm::fiber::Task fiber1(stack1, f8);
212251
modm::fiber::Task fiber2(stack2, [&](modm::fiber::stop_token stoken)
213252
{
214253
TEST_ASSERT_EQUALS(state++, 1u);

0 commit comments

Comments
 (0)