@@ -392,6 +392,48 @@ void sched_wakeup_task(tcb_t *task)
392392 }
393393}
394394
395+ /* Helper to clean up zombie task resources from safe context */
396+ static void cleanup_zombie_task (tcb_t * zombie )
397+ {
398+ if (!zombie || !(zombie -> flags & TASK_FLAG_ZOMBIE ))
399+ return ;
400+
401+ /* Find and remove task node from list */
402+ CRITICAL_ENTER ();
403+
404+ list_node_t * node = NULL ;
405+ list_node_t * iter = kcb -> tasks -> head ;
406+ while (iter ) {
407+ if (iter -> data == zombie ) {
408+ node = iter ;
409+ break ;
410+ }
411+ iter = iter -> next ;
412+ }
413+
414+ if (node ) {
415+ list_remove (kcb -> tasks , node );
416+ kcb -> task_count -- ;
417+
418+ /* Clear from cache */
419+ for (int i = 0 ; i < TASK_CACHE_SIZE ; i ++ ) {
420+ if (task_cache [i ].task == zombie ) {
421+ task_cache [i ].id = 0 ;
422+ task_cache [i ].task = NULL ;
423+ }
424+ }
425+ }
426+
427+ CRITICAL_LEAVE ();
428+
429+ /* Free resources outside critical section */
430+ if (zombie -> mspace )
431+ mo_memspace_destroy (zombie -> mspace );
432+
433+ free (zombie -> stack );
434+ free (zombie );
435+ }
436+
395437/* Efficient Round-Robin Task Selection with O(n) Complexity
396438 *
397439 * Selects the next ready task using circular traversal of the master task list.
@@ -414,6 +456,16 @@ uint16_t sched_select_next_task(void)
414456
415457 tcb_t * current_task = kcb -> task_current -> data ;
416458
459+ /* Clean up current task if it's a zombie before proceeding */
460+ if (current_task -> flags & TASK_FLAG_ZOMBIE ) {
461+ cleanup_zombie_task (current_task );
462+ /* After cleanup, move to first real task to start fresh search */
463+ kcb -> task_current = kcb -> tasks -> head -> next ;
464+ if (!kcb -> task_current || !kcb -> task_current -> data )
465+ panic (ERR_NO_TASKS );
466+ current_task = kcb -> task_current -> data ;
467+ }
468+
417469 /* Mark current task as ready if it was running */
418470 if (current_task -> state == TASK_RUNNING )
419471 current_task -> state = TASK_READY ;
@@ -431,6 +483,16 @@ uint16_t sched_select_next_task(void)
431483
432484 tcb_t * task = node -> data ;
433485
486+ /* Clean up zombie tasks during scheduling */
487+ if (task -> flags & TASK_FLAG_ZOMBIE ) {
488+ list_node_t * next_node = list_cnext (kcb -> tasks , node );
489+ cleanup_zombie_task (task );
490+ node = next_node ? next_node : kcb -> tasks -> head ;
491+ if (!node || !node -> data )
492+ continue ;
493+ task = node -> data ;
494+ }
495+
434496 /* Skip non-ready tasks */
435497 if (task -> state != TASK_READY )
436498 continue ;
@@ -455,6 +517,7 @@ static int32_t noop_rtsched(void)
455517 return -1 ;
456518}
457519
520+
458521/* The main entry point from the system tick interrupt. */
459522void dispatcher (void )
460523{
@@ -493,8 +556,9 @@ void dispatch(void)
493556 uint32_t ready_count = 0 ;
494557 list_foreach (kcb -> tasks , delay_update_batch , & ready_count );
495558
496- /* Save old task before scheduler modifies task_current */
497- memspace_t * old_mspace = ((tcb_t * ) kcb -> task_current -> data )-> mspace ;
559+ /* Save old task's memory space for PMP context switching */
560+ tcb_t * old_task = (tcb_t * )kcb -> task_current -> data ;
561+ memspace_t * old_mspace = old_task -> mspace ;
498562
499563 /* Hook for real-time scheduler - if it selects a task, use it */
500564 if (kcb -> rt_sched () < 0 )
@@ -531,8 +595,9 @@ void yield(void)
531595 if (!kcb -> preemptive )
532596 list_foreach (kcb -> tasks , delay_update , NULL );
533597
534- /* Save old task before scheduler modifies task_current */
535- memspace_t * old_mspace = ((tcb_t * ) kcb -> task_current -> data )-> mspace ;
598+ /* Save old task's memory space for PMP context switching */
599+ tcb_t * old_task = (tcb_t * )kcb -> task_current -> data ;
600+ memspace_t * old_mspace = old_task -> mspace ;
536601
537602 sched_select_next_task (); /* Use O(1) priority scheduler */
538603
@@ -716,6 +781,33 @@ int32_t mo_task_cancel(uint16_t id)
716781 return ERR_OK ;
717782}
718783
784+ void task_terminate_current (void )
785+ {
786+ NOSCHED_ENTER ();
787+
788+ /* Verify we have a current task */
789+ if (unlikely (!kcb || !kcb -> task_current || !kcb -> task_current -> data )) {
790+ NOSCHED_LEAVE ();
791+ panic (ERR_NO_TASKS );
792+ }
793+
794+ tcb_t * self = kcb -> task_current -> data ;
795+
796+ /* Mark as suspended to prevent re-scheduling */
797+ self -> state = TASK_SUSPENDED ;
798+
799+ /* Set zombie flag for deferred cleanup */
800+ self -> flags |= TASK_FLAG_ZOMBIE ;
801+
802+ NOSCHED_LEAVE ();
803+
804+ /* Force immediate context switch - never returns */
805+ _dispatch ();
806+
807+ /* Unreachable */
808+ __builtin_unreachable ();
809+ }
810+
719811void mo_task_yield (void )
720812{
721813 _yield ();
0 commit comments