@@ -160,48 +160,76 @@ impl SchedulerState {
160160 }
161161 }
162162
163- #[ cfg( xtensa) ]
164- fn switch_task ( & mut self , trap_frame : & mut esp_hal:: trapframe:: TrapFrame ) {
165- task:: save_task_context ( unsafe { & mut * self . current_task } , trap_frame) ;
166-
167- if !self . to_delete . is_null ( ) {
163+ fn delete_marked_tasks ( & mut self ) {
164+ while !self . to_delete . is_null ( ) {
168165 let task_to_delete = core:: mem:: take ( & mut self . to_delete ) ;
166+ self . to_delete = unsafe { ( * task_to_delete) . next_to_delete } ;
169167 self . delete_task ( task_to_delete) ;
170168 }
169+ }
170+
171+ fn select_next_task ( & mut self ) -> Option < * mut Context > {
172+ let mut current = self . current_task ;
173+ loop {
174+ let next_task = unsafe { ( * current) . next } ;
175+
176+ if next_task == self . current_task {
177+ // We didn't find a new task to switch to.
178+ // TODO: mark the current task as Running
179+ // Once we have actual task states, yield should marked the current task as Ready,
180+ // other stuff as Waiting.
181+ return None ;
182+ }
171183
172- unsafe { self . current_task = ( * self . current_task ) . next } ;
184+ if unsafe { ( * next_task) . state } . is_ready ( ) {
185+ // TODO: mark the selected task as Running
186+ return Some ( next_task) ;
187+ }
188+ current = next_task;
189+ }
190+ }
191+
192+ #[ cfg( xtensa) ]
193+ fn switch_task ( & mut self , trap_frame : & mut esp_hal:: trapframe:: TrapFrame ) {
194+ self . delete_marked_tasks ( ) ;
195+
196+ let Some ( next_task) = self . select_next_task ( ) else {
197+ return ;
198+ } ;
199+
200+ task:: save_task_context ( unsafe { & mut * self . current_task } , trap_frame) ;
201+
202+ self . current_task = next_task;
173203
174204 task:: restore_task_context ( unsafe { & mut * self . current_task } , trap_frame) ;
175205 }
176206
177207 #[ cfg( riscv) ]
178208 fn switch_task ( & mut self ) {
179- if !self . to_delete . is_null ( ) {
180- let task_to_delete = core:: mem:: take ( & mut self . to_delete ) ;
181- self . delete_task ( task_to_delete) ;
182- }
209+ self . delete_marked_tasks ( ) ;
183210
184- let task = self . current_task ;
185- let context = unsafe { & mut ( * task ) . trap_frame } ;
186- let old_ctx = core :: ptr :: addr_of_mut! ( * context ) ;
211+ let Some ( next_task ) = self . select_next_task ( ) else {
212+ return ;
213+ } ;
187214
188- let task = unsafe { ( * self . current_task ) . next } ;
189- let context = unsafe { & mut ( * task) . trap_frame } ;
190- let new_ctx = core:: ptr:: addr_of_mut!( * context) ;
215+ let old_ctx = unsafe { & raw mut ( * self . current_task ) . trap_frame } ;
216+ let new_ctx = unsafe { & raw mut ( * next_task) . trap_frame } ;
191217
192218 if crate :: task:: arch_specific:: task_switch ( old_ctx, new_ctx) {
193219 unsafe { self . current_task = ( * self . current_task ) . next } ;
194220 }
195221 }
196222
197- fn schedule_task_deletion ( & mut self , task : * mut Context ) -> bool {
198- if task. is_null ( ) {
199- self . to_delete = self . current_task ;
200- true
201- } else {
202- self . to_delete = task;
203- core:: ptr:: eq ( task, self . current_task )
223+ fn schedule_task_deletion ( & mut self , mut task_to_delete : * mut Context ) -> bool {
224+ if task_to_delete. is_null ( ) {
225+ task_to_delete = self . current_task ;
204226 }
227+ let is_current = core:: ptr:: eq ( task_to_delete, self . current_task ) ;
228+
229+ unsafe { ( * task_to_delete) . next_to_delete = self . to_delete } ;
230+ self . to_delete = task_to_delete;
231+
232+ is_current
205233 }
206234}
207235
0 commit comments