Skip to content

Commit c85b6b4

Browse files
committed
zephyr: Make time.sleep() and friends thread safe.
Currently the delay function is using a single static k_poll_event object which means that multiple threads sleeping at similar times will try to use the same event variable leading to a eventual crash. Signed-off-by: Daniel Campora <[email protected]>
1 parent 593ae04 commit c85b6b4

File tree

2 files changed

+17
-35
lines changed

2 files changed

+17
-35
lines changed

ports/zephyr/mphalport.c

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,6 @@
2929
#include "extmod/modmachine.h"
3030

3131
static struct k_poll_signal wait_signal;
32-
static struct k_poll_event wait_events[2] = {
33-
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
34-
K_POLL_MODE_NOTIFY_ONLY,
35-
&wait_signal),
36-
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
37-
K_POLL_MODE_NOTIFY_ONLY,
38-
NULL, 0),
39-
};
4032

4133
void mp_hal_init(void) {
4234
k_poll_signal_init(&wait_signal);
@@ -46,35 +38,29 @@ void mp_hal_signal_event(void) {
4638
k_poll_signal_raise(&wait_signal, 0);
4739
}
4840

49-
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms) {
50-
mp_uint_t t0 = mp_hal_ticks_ms();
51-
if (sem) {
52-
k_poll_event_init(&wait_events[1], K_POLL_TYPE_SEM_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, sem);
53-
}
41+
void mp_hal_delay_ms(uint32_t ms) {
42+
uint64_t dt;
43+
uint32_t t0 = mp_hal_ticks_ms();
5444
for (;;) {
5545
mp_handle_pending(true);
5646
MP_THREAD_GIL_EXIT();
57-
k_timeout_t wait;
58-
uint32_t dt = mp_hal_ticks_ms() - t0;
59-
if (timeout_ms == (uint32_t)-1) {
60-
wait = K_FOREVER;
61-
} else {
62-
wait = K_MSEC((timeout_ms > dt) ? (timeout_ms - dt) : 0);
63-
}
64-
k_poll(wait_events, sem ? 2 : 1, wait);
65-
if (wait_events[0].state == K_POLL_STATE_SIGNALED) {
66-
wait_events[0].signal->signaled = 0;
67-
wait_events[0].state = K_POLL_STATE_NOT_READY;
68-
} else if (sem && wait_events[1].state == K_POLL_STATE_SEM_AVAILABLE) {
69-
wait_events[1].state = K_POLL_STATE_NOT_READY;
47+
uint32_t t1 = mp_hal_ticks_ms();
48+
dt = t1 - t0;
49+
if (dt + 1 >= ms) {
50+
// doing a k_msleep would take us beyond requested delay time
51+
k_yield();
7052
MP_THREAD_GIL_ENTER();
71-
return;
72-
}
73-
if (dt >= timeout_ms) {
53+
t1 = mp_hal_ticks_ms();
54+
dt = t1 - t0;
55+
break;
56+
} else {
57+
k_msleep(1);
7458
MP_THREAD_GIL_ENTER();
75-
return;
7659
}
7760
}
61+
if (dt < ms) {
62+
mp_hal_delay_us(500);
63+
}
7864
}
7965

8066
mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t pin_in) {

ports/zephyr/mphalport.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#define MICROPY_END_ATOMIC_SECTION irq_unlock
77

88
void mp_hal_init(void);
9-
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms);
9+
void mp_hal_delay_ms(mp_uint_t delay);
1010

1111
static inline mp_uint_t mp_hal_ticks_us(void) {
1212
return k_cyc_to_ns_floor64(k_cycle_get_32()) / 1000;
@@ -27,10 +27,6 @@ static inline void mp_hal_delay_us(mp_uint_t delay) {
2727
k_busy_wait(delay);
2828
}
2929

30-
static inline void mp_hal_delay_ms(mp_uint_t delay) {
31-
mp_hal_wait_sem(NULL, delay);
32-
}
33-
3430
static inline uint64_t mp_hal_time_ns(void) {
3531
return k_ticks_to_ns_near64(k_uptime_ticks());
3632
}

0 commit comments

Comments
 (0)