@@ -395,6 +395,48 @@ void sched_wakeup_task(tcb_t *task)
395395 }
396396}
397397
398+ /* Helper to clean up zombie task resources from safe context */
399+ static void cleanup_zombie_task (tcb_t * zombie )
400+ {
401+ if (!zombie || !(zombie -> flags & TASK_FLAG_ZOMBIE ))
402+ return ;
403+
404+ /* Find and remove task node from list */
405+ CRITICAL_ENTER ();
406+
407+ list_node_t * node = NULL ;
408+ list_node_t * iter = kcb -> tasks -> head ;
409+ while (iter ) {
410+ if (iter -> data == zombie ) {
411+ node = iter ;
412+ break ;
413+ }
414+ iter = iter -> next ;
415+ }
416+
417+ if (node ) {
418+ list_remove (kcb -> tasks , node );
419+ kcb -> task_count -- ;
420+
421+ /* Clear from cache */
422+ for (int i = 0 ; i < TASK_CACHE_SIZE ; i ++ ) {
423+ if (task_cache [i ].task == zombie ) {
424+ task_cache [i ].id = 0 ;
425+ task_cache [i ].task = NULL ;
426+ }
427+ }
428+ }
429+
430+ CRITICAL_LEAVE ();
431+
432+ /* Free resources outside critical section */
433+ if (zombie -> mspace )
434+ mo_memspace_destroy (zombie -> mspace );
435+
436+ free (zombie -> stack );
437+ free (zombie );
438+ }
439+
398440/* Efficient Round-Robin Task Selection with O(n) Complexity
399441 *
400442 * Selects the next ready task using circular traversal of the master task list.
@@ -417,6 +459,16 @@ uint16_t sched_select_next_task(void)
417459
418460 tcb_t * current_task = kcb -> task_current -> data ;
419461
462+ /* Clean up current task if it's a zombie before proceeding */
463+ if (current_task -> flags & TASK_FLAG_ZOMBIE ) {
464+ cleanup_zombie_task (current_task );
465+ /* After cleanup, move to first real task to start fresh search */
466+ kcb -> task_current = kcb -> tasks -> head -> next ;
467+ if (!kcb -> task_current || !kcb -> task_current -> data )
468+ panic (ERR_NO_TASKS );
469+ current_task = kcb -> task_current -> data ;
470+ }
471+
420472 /* Mark current task as ready if it was running */
421473 if (current_task -> state == TASK_RUNNING )
422474 current_task -> state = TASK_READY ;
@@ -434,6 +486,16 @@ uint16_t sched_select_next_task(void)
434486
435487 tcb_t * task = node -> data ;
436488
489+ /* Clean up zombie tasks during scheduling */
490+ if (task -> flags & TASK_FLAG_ZOMBIE ) {
491+ list_node_t * next_node = list_cnext (kcb -> tasks , node );
492+ cleanup_zombie_task (task );
493+ node = next_node ? next_node : kcb -> tasks -> head ;
494+ if (!node || !node -> data )
495+ continue ;
496+ task = node -> data ;
497+ }
498+
437499 /* Skip non-ready tasks */
438500 if (task -> state != TASK_READY )
439501 continue ;
@@ -458,6 +520,7 @@ static int32_t noop_rtsched(void)
458520 return -1 ;
459521}
460522
523+
461524/* The main entry point from the system tick interrupt. */
462525void dispatcher (void )
463526{
@@ -496,8 +559,9 @@ void dispatch(void)
496559 uint32_t ready_count = 0 ;
497560 list_foreach (kcb -> tasks , delay_update_batch , & ready_count );
498561
499- /* Save old task before scheduler modifies task_current */
500- memspace_t * old_mspace = ((tcb_t * ) kcb -> task_current -> data )-> mspace ;
562+ /* Save old task's memory space for PMP context switching */
563+ tcb_t * old_task = (tcb_t * )kcb -> task_current -> data ;
564+ memspace_t * old_mspace = old_task -> mspace ;
501565
502566 /* Hook for real-time scheduler - if it selects a task, use it */
503567 if (kcb -> rt_sched () < 0 )
@@ -534,8 +598,9 @@ void yield(void)
534598 if (!kcb -> preemptive )
535599 list_foreach (kcb -> tasks , delay_update , NULL );
536600
537- /* Save old task before scheduler modifies task_current */
538- memspace_t * old_mspace = ((tcb_t * ) kcb -> task_current -> data )-> mspace ;
601+ /* Save old task's memory space for PMP context switching */
602+ tcb_t * old_task = (tcb_t * )kcb -> task_current -> data ;
603+ memspace_t * old_mspace = old_task -> mspace ;
539604
540605 sched_select_next_task (); /* Use O(1) priority scheduler */
541606
@@ -714,6 +779,33 @@ int32_t mo_task_cancel(uint16_t id)
714779 return ERR_OK ;
715780}
716781
782+ void task_terminate_current (void )
783+ {
784+ NOSCHED_ENTER ();
785+
786+ /* Verify we have a current task */
787+ if (unlikely (!kcb || !kcb -> task_current || !kcb -> task_current -> data )) {
788+ NOSCHED_LEAVE ();
789+ panic (ERR_NO_TASKS );
790+ }
791+
792+ tcb_t * self = kcb -> task_current -> data ;
793+
794+ /* Mark as suspended to prevent re-scheduling */
795+ self -> state = TASK_SUSPENDED ;
796+
797+ /* Set zombie flag for deferred cleanup */
798+ self -> flags |= TASK_FLAG_ZOMBIE ;
799+
800+ NOSCHED_LEAVE ();
801+
802+ /* Force immediate context switch - never returns */
803+ _dispatch ();
804+
805+ /* Unreachable */
806+ __builtin_unreachable ();
807+ }
808+
717809void mo_task_yield (void )
718810{
719811 _yield ();
0 commit comments