From 3d8930c0ff4fff63a557ad3e916990092a448639 Mon Sep 17 00:00:00 2001 From: Elena Frank Date: Fri, 12 Apr 2024 14:05:02 +0200 Subject: [PATCH] fixup! threads: PoC multicore support for rp2040 Only schedule a context switch if thread allocation (to a core) changed. TODO: Schedule the context switch on the core that is affected. In most cases, this is the currently running cores, but not always (e.g. when on another core a low priority thread is running that should be preempted). --- src/riot-rs-threads/src/lib.rs | 46 ++++++++++++++----------- src/riot-rs-threads/src/thread_flags.rs | 29 +++++++++++----- src/riot-rs-threads/src/threadlist.rs | 11 +++--- 3 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/riot-rs-threads/src/lib.rs b/src/riot-rs-threads/src/lib.rs index 77f708121..85c91c33e 100644 --- a/src/riot-rs-threads/src/lib.rs +++ b/src/riot-rs-threads/src/lib.rs @@ -149,17 +149,22 @@ impl Threads { /// /// This function handles adding/ removing the thread to the Runqueue depending /// on its previous or new state. - pub(crate) fn set_state(&mut self, pid: ThreadId, state: ThreadState) -> ThreadState { + pub(crate) fn set_state( + &mut self, + pid: ThreadId, + state: ThreadState, + ) -> (ThreadState, Option) { let thread = &mut self.threads[pid as usize]; let old_state = thread.state; thread.state = state; - if old_state != ThreadState::Running && state == ThreadState::Running { - self.runqueue.add(thread.pid, thread.prio); - } else if old_state == ThreadState::Running && state != ThreadState::Running { - self.runqueue.del(thread.pid, thread.prio); - } - old_state + let changed_id = match (old_state, state) { + (ThreadState::Running, ThreadState::Running) => None, + (_, ThreadState::Running) => self.runqueue.add(thread.pid, thread.prio), + (ThreadState::Running, _) => self.runqueue.del(thread.pid, thread.prio), + _ => None, + }; + (old_state, changed_id) } pub fn get_state(&self, thread_id: ThreadId) -> Option { @@ -298,8 +303,9 @@ fn cleanup() -> ! { pub fn yield_same() { THREADS.with_mut(|mut threads| { let runqueue = threads.current().unwrap().prio; - threads.runqueue.advance(runqueue); - schedule(); + if let Some(_cpuid) = threads.runqueue.advance(runqueue) { + schedule(); + } }) } @@ -307,8 +313,9 @@ pub fn yield_same() { pub fn sleep() { THREADS.with_mut(|mut threads| { let pid = threads.current_pid().unwrap(); - threads.set_state(pid, ThreadState::Paused); - schedule(); + if let Some(_cpuid) = threads.set_state(pid, ThreadState::Paused).1 { + schedule(); + } }); } @@ -317,17 +324,14 @@ pub fn sleep() { /// Returns `false` if no paused thread exists for `thread_id`. pub fn wakeup(thread_id: ThreadId) -> bool { THREADS.with_mut(|mut threads| { - if let Some(state) = threads.get_state(thread_id) { - if state == ThreadState::Paused { - threads.set_state(thread_id, ThreadState::Running); - schedule(); - true - } else { - false - } - } else { - false + match threads.get_state(thread_id) { + Some(ThreadState::Paused) => {} + _ => return false, + } + if let (_, Some(_cpuid)) = threads.set_state(thread_id, ThreadState::Running) { + schedule(); } + true }) } diff --git a/src/riot-rs-threads/src/thread_flags.rs b/src/riot-rs-threads/src/thread_flags.rs index ec3475abf..e84efa729 100644 --- a/src/riot-rs-threads/src/thread_flags.rs +++ b/src/riot-rs-threads/src/thread_flags.rs @@ -105,8 +105,9 @@ impl Threads { }, _ => false, } { - self.set_state(thread_id, ThreadState::Running); - crate::schedule(); + if let Some(_cpuid) = self.set_state(thread_id, ThreadState::Running).1 { + crate::schedule(); + } } } @@ -117,8 +118,12 @@ impl Threads { Some(mask) } else { let thread_id = thread.pid; - self.set_state(thread_id, ThreadState::FlagBlocked(WaitMode::All(mask))); - crate::schedule(); + if let Some(_cpuid) = self + .set_state(thread_id, ThreadState::FlagBlocked(WaitMode::All(mask))) + .1 + { + crate::schedule(); + } None } } @@ -131,8 +136,12 @@ impl Threads { Some(res) } else { let thread_id = thread.pid; - self.set_state(thread_id, ThreadState::FlagBlocked(WaitMode::Any(mask))); - crate::schedule(); + if let Some(_cpuid) = self + .set_state(thread_id, ThreadState::FlagBlocked(WaitMode::Any(mask))) + .1 + { + crate::schedule(); + } None } } @@ -147,8 +156,12 @@ impl Threads { Some(res) } else { let thread_id = thread.pid; - self.set_state(thread_id, ThreadState::FlagBlocked(WaitMode::Any(mask))); - crate::schedule(); + if let Some(_cpuid) = self + .set_state(thread_id, ThreadState::FlagBlocked(WaitMode::Any(mask))) + .1 + { + crate::schedule(); + } None } } diff --git a/src/riot-rs-threads/src/threadlist.rs b/src/riot-rs-threads/src/threadlist.rs index 8a9589840..1b34032e4 100644 --- a/src/riot-rs-threads/src/threadlist.rs +++ b/src/riot-rs-threads/src/threadlist.rs @@ -21,8 +21,9 @@ impl ThreadList { let thread_id = threads.current_pid().unwrap(); threads.thread_blocklist[thread_id as usize] = self.head; self.head = Some(thread_id); - threads.set_state(thread_id, state); - crate::schedule(); + if let Some(_cpuid) = threads.set_state(thread_id, state).1 { + crate::schedule(); + } }); } @@ -36,8 +37,10 @@ impl ThreadList { if let Some(head) = self.head { let old_state = THREADS.with_mut_cs(cs, |mut threads| { self.head = threads.thread_blocklist[head as usize].take(); - let old_state = threads.set_state(head, ThreadState::Running); - crate::schedule(); + let (old_state, cpuid) = threads.set_state(head, ThreadState::Running); + if let Some(_cpuid) = cpuid { + crate::schedule(); + } old_state }); Some((head, old_state))