@@ -168,20 +168,18 @@ impl SchedulerState {
168168 task_ptr
169169 }
170170
171+ #[ cold]
172+ #[ inline( never) ]
171173 fn delete_marked_tasks ( & mut self , cpu : Cpu ) {
172174 let current_cpu = cpu as usize ;
173175 let mut to_delete = core:: mem:: take ( & mut self . to_delete ) ;
174176 ' outer: while let Some ( task_ptr) = to_delete. pop ( ) {
175177 assert ! ( task_ptr. state( ) == TaskState :: Deleted ) ;
176178 for cpu in 0 ..Cpu :: COUNT {
177- if Some ( task_ptr) == self . per_cpu [ cpu] . current_task {
178- if cpu == current_cpu {
179- self . per_cpu [ cpu] . current_task = None ;
180- } else {
181- // We can't delete a task that is currently running on another CPU.
182- self . to_delete . push ( task_ptr) ;
183- continue ' outer;
184- }
179+ if cpu != current_cpu && Some ( task_ptr) == self . per_cpu [ cpu] . current_task {
180+ // We can't delete a task that is currently running on another CPU.
181+ self . to_delete . push ( task_ptr) ;
182+ continue ' outer;
185183 }
186184 }
187185
@@ -197,25 +195,22 @@ impl SchedulerState {
197195 let cpu = Cpu :: current ( ) ;
198196 let current_cpu = cpu as usize ;
199197
200- let mut priority = if let Some ( current_task) = self . per_cpu [ current_cpu] . current_task {
201- let current_task = unsafe { current_task. as_ref ( ) } ;
202- current_task. ensure_no_stack_overflow ( ) ;
203- Some ( current_task. priority )
204- } else {
205- None
206- } ;
207-
208- self . delete_marked_tasks ( cpu) ;
198+ if !self . to_delete . is_empty ( ) {
199+ self . delete_marked_tasks ( cpu) ;
200+ }
209201
210202 let current_task = self . per_cpu [ current_cpu] . current_task ;
211- if let Some ( current_task) = current_task
212- && current_task. state ( ) == TaskState :: Ready
213- {
214- // Current task is still ready, mark it as such.
215- debug ! ( "re-queueing current task: {:?}" , current_task) ;
216- self . run_queue . mark_task_ready ( & self . per_cpu , current_task) ;
217- }
203+ if let Some ( current_task) = current_task {
204+ unsafe { current_task. as_ref ( ) . ensure_no_stack_overflow ( ) } ;
218205
206+ if current_task. state ( ) == TaskState :: Ready {
207+ // Current task is still ready, mark it as such.
208+ debug ! ( "re-queueing current task: {:?}" , current_task) ;
209+ self . run_queue . mark_task_ready ( & self . per_cpu , current_task) ;
210+ }
211+ } ;
212+
213+ let mut arm_next_timeslice_tick = false ;
219214 let next_task = self . run_queue . pop ( ) ;
220215 if next_task != current_task {
221216 trace ! ( "Switching task {:?} -> {:?}" , current_task, next_task) ;
@@ -243,18 +238,19 @@ impl SchedulerState {
243238 core:: ptr:: null_mut ( )
244239 } ;
245240
246- let new_core_priority =
247- next_task. map_or ( Priority :: ZERO , |t| t. priority ( & mut self . run_queue ) ) ;
248241 let next_context = if let Some ( next) = next_task {
249- priority = Some ( new_core_priority) ;
250242 #[ cfg( feature = "rtos-trace" ) ]
251243 rtos_trace:: trace:: task_exec_begin ( next. rtos_trace_id ( ) ) ;
252244
253245 unsafe { next. as_ref ( ) . set_up_stack_watchpoint ( ) } ;
254246
247+ // If there are more tasks at this priority level, we need to schedule a timeslice
248+ // tick.
249+ let new_core_priority = next. priority ( & mut self . run_queue ) ;
250+ arm_next_timeslice_tick = !self . run_queue . is_level_empty ( new_core_priority) ;
251+
255252 unsafe { & raw mut ( * next. as_ptr ( ) ) . cpu_context }
256253 } else {
257- priority = None ;
258254 // If there is no next task, set up and return to the idle hook.
259255 // Reuse the stack frame of the main task. Note that this requires the main task to
260256 // be pinned to the current CPU. If we're switching out the main task, however, we
@@ -310,13 +306,6 @@ impl SchedulerState {
310306 self . per_cpu [ current_cpu] . current_task = next_task;
311307 }
312308
313- // The current task is not in the run queue. If the run queue on the current priority
314- // level is empty, the current task is the only one running at its priority
315- // level. In this case, we don't need time slicing.
316- let arm_next_timeslice_tick = priority
317- . map ( |p| !self . run_queue . is_level_empty ( p) )
318- . unwrap_or ( false ) ;
319-
320309 let time_driver = unwrap ! ( self . time_driver. as_mut( ) ) ;
321310 let now = crate :: now ( ) ;
322311 time_driver. set_time_slice ( cpu, now, arm_next_timeslice_tick) ;
@@ -351,6 +340,10 @@ impl SchedulerState {
351340 self . to_delete . push ( task_to_delete) ;
352341 task_to_delete. set_state ( TaskState :: Deleted ) ;
353342
343+ if is_current {
344+ self . per_cpu [ current_cpu] . current_task = None ;
345+ }
346+
354347 is_current
355348 }
356349
@@ -372,6 +365,8 @@ impl SchedulerState {
372365 }
373366
374367 fn delete_task ( & mut self , mut to_delete : TaskPtr ) {
368+ unsafe { to_delete. as_ref ( ) . ensure_no_stack_overflow ( ) } ;
369+
375370 self . remove_from_all_queues ( to_delete) ;
376371
377372 unsafe {
0 commit comments