aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src
diff options
context:
space:
mode:
authorivmarkov <[email protected]>2022-10-24 09:17:43 +0300
committerivmarkov <[email protected]>2022-10-24 09:17:43 +0300
commit4d5550070fe5e80ff2296a71239c568c774b9ceb (patch)
tree3248eb5c70b9dd5402c5edc049cafc31a5f66ed3 /embassy-executor/src
parent53608a87ac4b6c8c60b5508551d12f5ba76ca2f6 (diff)
Change time Driver contract to never fire the alarm synchronously
Diffstat (limited to 'embassy-executor/src')
-rw-r--r--embassy-executor/src/raw/mod.rs72
1 files changed, 40 insertions, 32 deletions
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index e1258ebb5..5bcb1e6e7 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -354,46 +354,54 @@ impl Executor {
354 /// somehow schedule for `poll()` to be called later, at a time you know for sure there's 354 /// somehow schedule for `poll()` to be called later, at a time you know for sure there's
355 /// no `poll()` already running. 355 /// no `poll()` already running.
356 pub unsafe fn poll(&'static self) { 356 pub unsafe fn poll(&'static self) {
357 #[cfg(feature = "integrated-timers")] 357 loop {
358 self.timer_queue.dequeue_expired(Instant::now(), |task| wake_task(task)); 358 #[cfg(feature = "integrated-timers")]
359 self.timer_queue.dequeue_expired(Instant::now(), |task| wake_task(task));
359 360
360 self.run_queue.dequeue_all(|p| { 361 self.run_queue.dequeue_all(|p| {
361 let task = p.as_ref(); 362 let task = p.as_ref();
362 363
363 #[cfg(feature = "integrated-timers")] 364 #[cfg(feature = "integrated-timers")]
364 task.expires_at.set(Instant::MAX); 365 task.expires_at.set(Instant::MAX);
365 366
366 let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel); 367 let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel);
367 if state & STATE_SPAWNED == 0 { 368 if state & STATE_SPAWNED == 0 {
368 // If task is not running, ignore it. This can happen in the following scenario: 369 // If task is not running, ignore it. This can happen in the following scenario:
369 // - Task gets dequeued, poll starts 370 // - Task gets dequeued, poll starts
370 // - While task is being polled, it gets woken. It gets placed in the queue. 371 // - While task is being polled, it gets woken. It gets placed in the queue.
371 // - Task poll finishes, returning done=true 372 // - Task poll finishes, returning done=true
372 // - RUNNING bit is cleared, but the task is already in the queue. 373 // - RUNNING bit is cleared, but the task is already in the queue.
373 return; 374 return;
374 } 375 }
375 376
376 #[cfg(feature = "rtos-trace")] 377 #[cfg(feature = "rtos-trace")]
377 trace::task_exec_begin(p.as_ptr() as u32); 378 trace::task_exec_begin(p.as_ptr() as u32);
378 379
379 // Run the task 380 // Run the task
380 task.poll_fn.read()(p as _); 381 task.poll_fn.read()(p as _);
381 382
382 #[cfg(feature = "rtos-trace")] 383 #[cfg(feature = "rtos-trace")]
383 trace::task_exec_end(); 384 trace::task_exec_end();
385
386 // Enqueue or update into timer_queue
387 #[cfg(feature = "integrated-timers")]
388 self.timer_queue.update(p);
389 });
384 390
385 // Enqueue or update into timer_queue
386 #[cfg(feature = "integrated-timers")] 391 #[cfg(feature = "integrated-timers")]
387 self.timer_queue.update(p); 392 {
388 }); 393 // If this is already in the past, set_alarm might return false
394 // In that case do another poll loop iteration.
395 let next_expiration = self.timer_queue.next_expiration();
396 if driver::set_alarm(self.alarm, next_expiration.as_ticks()) {
397 break;
398 }
399 }
389 400
390 #[cfg(feature = "integrated-timers")] 401 #[cfg(not(feature = "integrated-timers"))]
391 { 402 {
392 // If this is already in the past, set_alarm will immediately trigger the alarm. 403 break;
393 // This will cause `signal_fn` to be called, which will cause `poll()` to be called again, 404 }
394 // so we immediately do another poll loop iteration.
395 let next_expiration = self.timer_queue.next_expiration();
396 driver::set_alarm(self.alarm, next_expiration.as_ticks());
397 } 405 }
398 406
399 #[cfg(feature = "rtos-trace")] 407 #[cfg(feature = "rtos-trace")]