Skip to content

Commit 0223d92

Browse files
committed
Add Chrono support to ThisThread
1 parent fdc697e commit 0223d92

File tree

2 files changed

+148
-32
lines changed

2 files changed

+148
-32
lines changed

rtos/ThisThread.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#define THIS_THREAD_H
2525

2626
#include <stdint.h>
27+
#include "platform/mbed_toolchain.h"
28+
#include "rtos/Kernel.h"
2729
#include "rtos/mbed_rtos_types.h"
2830

2931
namespace rtos {
@@ -105,9 +107,21 @@ uint32_t flags_wait_any(uint32_t flags, bool clear = true);
105107
@return actual thread flags before clearing, which may not satisfy the wait
106108
@note You cannot call this function from ISR context.
107109
@see Thread::flags_set
110+
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
108111
*/
112+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
109113
uint32_t flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear = true);
110114

115+
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
116+
@param flags specifies the flags to wait for
117+
@param rel_time timeout value.
118+
@param clear whether to clear the specified flags after waiting for them. (default: true)
119+
@return actual thread flags before clearing, which may not satisfy the wait
120+
@note You cannot call this function from ISR context.
121+
@see Thread::flags_set
122+
*/
123+
uint32_t flags_wait_all_for(uint32_t flags, Kernel::Clock::duration_u32 rel_time, bool clear = true);
124+
111125
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
112126
@param flags specifies the flags to wait for
113127
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@@ -119,19 +133,48 @@ uint32_t flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear = true
119133
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
120134
the wait will time out earlier than specified.
121135
@see Thread::flags_set
136+
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s`
137+
rather than `Kernel::get_ms_count() + 5000`.
122138
*/
139+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
123140
uint32_t flags_wait_all_until(uint32_t flags, uint64_t millisec, bool clear = true);
124141

142+
/** Wait for all of the specified Thread Flags to become signaled for the current thread.
143+
@param flags specifies the flags to wait for
144+
@param abs_time absolute timeout time, referenced to Kernel::Clock
145+
@param clear whether to clear the specified flags after waiting for them. (default: true)
146+
@return actual thread flags before clearing, which may not satisfy the wait
147+
@note You cannot call this function from ISR context.
148+
@note the underlying RTOS may have a limit to the maximum wait time
149+
due to internal 32-bit computations, but this is guaranteed to work if the
150+
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
151+
the wait will time out earlier than specified.
152+
@see Thread::flags_set
153+
*/
154+
uint32_t flags_wait_all_until(uint32_t flags, Kernel::Clock::time_point abs_time, bool clear = true);
155+
125156
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
126157
@param flags specifies the flags to wait for
127158
@param millisec timeout value.
128159
@param clear whether to clear the specified flags after waiting for them. (default: true)
129160
@return actual thread flags before clearing, which may not satisfy the wait
130161
@note You cannot call this function from ISR context.
131162
@see Thread::flags_set
163+
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
132164
*/
165+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
133166
uint32_t flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear = true);
134167

168+
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
169+
@param flags specifies the flags to wait for
170+
@param rel_time timeout value.
171+
@param clear whether to clear the specified flags after waiting for them. (default: true)
172+
@return actual thread flags before clearing, which may not satisfy the wait
173+
@note You cannot call this function from ISR context.
174+
@see Thread::flags_set
175+
*/
176+
uint32_t flags_wait_any_for(uint32_t flags, Kernel::Clock::duration_u32 rel_time, bool clear = true);
177+
135178
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
136179
@param flags specifies the flags to wait for
137180
@param millisec absolute timeout time, referenced to Kernel::get_ms_count()
@@ -143,26 +186,66 @@ uint32_t flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear = true
143186
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
144187
the wait will time out earlier than specified.
145188
@see Thread::flags_set
189+
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s`
190+
rather than `Kernel::get_ms_count() + 5000`.
146191
*/
192+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
147193
uint32_t flags_wait_any_until(uint32_t flags, uint64_t millisec, bool clear = true);
148194

195+
/** Wait for any of the specified Thread Flags to become signaled for the current thread.
196+
@param flags specifies the flags to wait for
197+
@param abs_time absolute timeout time, referenced to Kernel::Clock
198+
@param clear whether to clear the specified flags after waiting for them. (default: true)
199+
@return actual thread flags before clearing, which may not satisfy the wait
200+
@note You cannot call this function from ISR context.
201+
@note the underlying RTOS may have a limit to the maximum wait time
202+
due to internal 32-bit computations, but this is guaranteed to work if the
203+
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
204+
the wait will time out earlier than specified.
205+
@see Thread::flags_set
206+
*/
207+
uint32_t flags_wait_any_until(uint32_t flags, Kernel::Clock::time_point abs_time, bool clear = true);
208+
149209
/** Sleep for a specified time period in millisec:
150210
@param millisec time delay value
151211
@note You cannot call this function from ISR context.
152212
@note The equivalent functionality is accessible in C via thread_sleep_for.
213+
@deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.
153214
*/
215+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
154216
void sleep_for(uint32_t millisec);
155217

218+
/** Sleep for a specified time period:
219+
@param rel_time time delay value
220+
@note You cannot call this function from ISR context.
221+
@note The equivalent functionality is accessible in C via thread_sleep_for.
222+
*/
223+
void sleep_for(Kernel::Clock::duration_u32 rel_time);
224+
225+
156226
/** Sleep until a specified time in millisec
157227
The specified time is according to Kernel::get_ms_count().
158228
@param millisec absolute time in millisec
159229
@note You cannot call this function from ISR context.
160230
@note if millisec is equal to or lower than the current tick count, this
161231
returns immediately.
162232
@note The equivalent functionality is accessible in C via thread_sleep_until.
233+
@deprecated Pass a chrono time_point, not an integer millisecond count. For example use
234+
`Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.
163235
*/
236+
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
164237
void sleep_until(uint64_t millisec);
165238

239+
/** Sleep until a specified time in millisec
240+
The specified time is according to Kernel::Clock.
241+
@param abs_time absolute time
242+
@note You cannot call this function from ISR context.
243+
@note if abs_time is equal to or lower than Kernel::Clock::now(), this
244+
returns immediately.
245+
@note The equivalent functionality is accessible in C via thread_sleep_until.
246+
*/
247+
void sleep_until(Kernel::Clock::time_point abs_time);
248+
166249
/** Pass control to next equal-priority thread that is in state READY.
167250
(Higher-priority READY threads would prevent us from running; this
168251
will not enable lower-priority threads to run, as we remain READY).

rtos/source/ThisThread.cpp

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
#include "platform/mbed_critical.h"
3232
#include "platform/source/mbed_os_timer.h"
3333

34+
using std::milli;
35+
using std::chrono::duration;
36+
using rtos::Kernel::Clock;
37+
using rtos::Kernel::wait_for_u32_max;
38+
using rtos::Kernel::wait_for_u32_forever;
39+
3440
#if !MBED_CONF_RTOS_PRESENT
3541
/* If the RTOS is not present, we call mbed_thread.cpp to do the work */
3642
/* If the RTOS is present, mbed_thread.cpp calls us to do the work */
@@ -95,16 +101,16 @@ bool non_rtos_check_flags(void *handle)
95101
}
96102
#endif
97103

98-
static uint32_t flags_wait_for(uint32_t flags, uint32_t millisec, bool clear, uint32_t options)
104+
static uint32_t flags_wait_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear, uint32_t options)
99105
{
100106
if (!clear) {
101107
options |= osFlagsNoClear;
102108
}
103109
#if MBED_CONF_RTOS_PRESENT
104-
flags = osThreadFlagsWait(flags, options, millisec);
110+
flags = osThreadFlagsWait(flags, options, rel_time.count());
105111
if (flags & osFlagsError) {
106-
MBED_ASSERT((flags == osFlagsErrorTimeout && millisec != osWaitForever) ||
107-
(flags == osFlagsErrorResource && millisec == 0));
112+
MBED_ASSERT((flags == osFlagsErrorTimeout && rel_time != wait_for_u32_forever) ||
113+
(flags == osFlagsErrorResource && rel_time == rel_time.zero()));
108114
flags = ThisThread::flags_get();
109115
}
110116
#else
@@ -113,7 +119,7 @@ static uint32_t flags_wait_for(uint32_t flags, uint32_t millisec, bool clear, ui
113119
check.options = options;
114120
check.flags_wanted = flags;
115121
check.result = 0;
116-
mbed::internal::do_timed_sleep_relative_or_forever(millisec, rtos::internal::non_rtos_check_flags, &check);
122+
mbed::internal::do_timed_sleep_relative_or_forever(rel_time, rtos::internal::non_rtos_check_flags, &check);
117123
flags = check.result;
118124
#endif
119125

@@ -123,7 +129,7 @@ static uint32_t flags_wait_for(uint32_t flags, uint32_t millisec, bool clear, ui
123129
static uint32_t flags_wait(uint32_t flags, bool clear, uint32_t options)
124130
{
125131
#if MBED_CONF_RTOS_PRESENT
126-
return flags_wait_for(flags, osWaitForever, clear, options);
132+
return flags_wait_for(flags, wait_for_u32_forever, clear, options);
127133
#else
128134
/* Avoids pulling in timer if not used */
129135
if (!clear) {
@@ -141,20 +147,20 @@ static uint32_t flags_wait(uint32_t flags, bool clear, uint32_t options)
141147
#endif
142148
}
143149

144-
static uint32_t flags_wait_until(uint32_t flags, uint64_t millisec, bool clear, uint32_t options)
150+
static uint32_t flags_wait_until(uint32_t flags, Clock::time_point abs_time, bool clear, uint32_t options)
145151
{
146-
uint64_t now = Kernel::get_ms_count();
152+
Clock::time_point now = Clock::now();
147153

148-
uint32_t delay;
149-
if (now >= millisec) {
150-
delay = 0;
151-
} else if (millisec - now >= osWaitForever) {
154+
Clock::duration_u32 rel_time;
155+
if (now >= abs_time) {
156+
rel_time = rel_time.zero();
157+
} else if (abs_time - now > wait_for_u32_max) {
152158
// Documentation permits early return for big offsets
153-
delay = osWaitForever - 1;
159+
rel_time = wait_for_u32_max;
154160
} else {
155-
delay = millisec - now;
161+
rel_time = abs_time - now;
156162
}
157-
return flags_wait_for(flags, delay, clear, options);
163+
return flags_wait_for(flags, rel_time, clear, options);
158164
}
159165

160166
uint32_t ThisThread::flags_wait_all(uint32_t flags, bool clear)
@@ -164,12 +170,22 @@ uint32_t ThisThread::flags_wait_all(uint32_t flags, bool clear)
164170

165171
uint32_t ThisThread::flags_wait_all_for(uint32_t flags, uint32_t millisec, bool clear)
166172
{
167-
return flags_wait_for(flags, millisec, clear, osFlagsWaitAll);
173+
return flags_wait_all_for(flags, duration<uint32_t, milli>(millisec), clear);
174+
}
175+
176+
uint32_t ThisThread::flags_wait_all_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear)
177+
{
178+
return flags_wait_for(flags, rel_time, clear, osFlagsWaitAll);
168179
}
169180

170181
uint32_t ThisThread::flags_wait_all_until(uint32_t flags, uint64_t millisec, bool clear)
171182
{
172-
return flags_wait_until(flags, millisec, clear, osFlagsWaitAll);
183+
return flags_wait_all_until(flags, Clock::time_point(duration<uint64_t, milli>(millisec)), clear);
184+
}
185+
186+
uint32_t ThisThread::flags_wait_all_until(uint32_t flags, Clock::time_point abs_time, bool clear)
187+
{
188+
return flags_wait_until(flags, abs_time, clear, osFlagsWaitAll);
173189
}
174190

175191
uint32_t ThisThread::flags_wait_any(uint32_t flags, bool clear)
@@ -179,45 +195,62 @@ uint32_t ThisThread::flags_wait_any(uint32_t flags, bool clear)
179195

180196
uint32_t ThisThread::flags_wait_any_for(uint32_t flags, uint32_t millisec, bool clear)
181197
{
182-
return flags_wait_for(flags, millisec, clear, osFlagsWaitAny);
198+
return flags_wait_any_for(flags, duration<uint32_t, milli>(millisec), clear);
199+
}
200+
201+
uint32_t ThisThread::flags_wait_any_for(uint32_t flags, Clock::duration_u32 rel_time, bool clear)
202+
{
203+
return flags_wait_for(flags, rel_time, clear, osFlagsWaitAll);
183204
}
184205

185206
uint32_t ThisThread::flags_wait_any_until(uint32_t flags, uint64_t millisec, bool clear)
186207
{
187-
return flags_wait_until(flags, millisec, clear, osFlagsWaitAny);
208+
return flags_wait_any_until(flags, Clock::time_point(duration<uint64_t, milli>(millisec)), clear);
209+
}
210+
211+
uint32_t ThisThread::flags_wait_any_until(uint32_t flags, Clock::time_point abs_time, bool clear)
212+
{
213+
return flags_wait_until(flags, abs_time, clear, osFlagsWaitAny);
188214
}
189215

190216
void ThisThread::sleep_for(uint32_t millisec)
217+
{
218+
ThisThread::sleep_for(duration<uint32_t, std::milli>(millisec));
219+
}
220+
221+
void ThisThread::sleep_for(Clock::duration_u32 rel_time)
191222
{
192223
#if MBED_CONF_RTOS_PRESENT
193-
osStatus_t status = osDelay(millisec);
224+
osStatus_t status = osDelay(rel_time.count());
194225
MBED_ASSERT(status == osOK);
195226
#else
196-
thread_sleep_for(millisec);
227+
thread_sleep_for(rel_time.count());
197228
#endif
198229
}
199230

200231
void ThisThread::sleep_until(uint64_t millisec)
201232
{
202-
#if MBED_CONF_RTOS_PRESENT
203-
// CMSIS-RTOS 2.1.0 had 64-bit time and osDelayUntil, but that's been revoked.
204-
// Limit ourselves to manual implementation assuming a >=32-bit osDelay.
233+
ThisThread::sleep_until(Clock::time_point(duration<uint64_t, milli>(millisec)));
234+
}
205235

206-
// 64-bit time doesn't wrap (for half a billion years, at last)
207-
// make the effort to loop for unlimited sleep, as it doesn't cost much
208-
uint64_t now;
236+
void ThisThread::sleep_until(Clock::time_point abs_time)
237+
{
238+
#if MBED_CONF_RTOS_PRESENT
239+
Clock::time_point now;
209240

210-
while ((now = Kernel::get_ms_count()) < millisec) {
211-
if (millisec - now > UINT32_MAX) {
212-
sleep_for(UINT32_MAX);
241+
while ((now = Clock::now()) < abs_time) {
242+
if (abs_time - now > wait_for_u32_max) {
243+
osStatus_t status = osDelay(wait_for_u32_max.count());
244+
MBED_ASSERT(status == osOK);
213245
continue;
214246
} else {
215-
sleep_for(millisec - now);
247+
osStatus_t status = osDelay((abs_time - now).count());
248+
MBED_ASSERT(status == osOK);
216249
break;
217250
}
218251
}
219252
#else
220-
thread_sleep_until(millisec);
253+
thread_sleep_until(abs_time.time_since_epoch().count());
221254
#endif
222255
}
223256

0 commit comments

Comments
 (0)