@@ -116,6 +116,7 @@ static void _thread_detach_from_mutex(rt_thread_t thread) {}
116116
117117static void _thread_exit (void )
118118{
119+ rt_err_t error ;
119120 struct rt_thread * thread ;
120121 rt_base_t critical_level ;
121122
@@ -124,12 +125,18 @@ static void _thread_exit(void)
124125
125126 critical_level = rt_enter_critical ();
126127
127- rt_thread_close (thread );
128+ error = rt_thread_close (thread );
128129
129- _thread_detach_from_mutex (thread );
130+ /* This check prevents other threads from concurrently executing _thread_detach
131+ * and duplicating the detach operations. Only proceed if close succeeds.
132+ */
133+ if (error == RT_EOK )
134+ {
135+ _thread_detach_from_mutex (thread );
130136
131- /* insert to defunct thread list */
132- rt_thread_defunct_enqueue (thread );
137+ /* insert to defunct thread list */
138+ rt_thread_defunct_enqueue (thread );
139+ }
133140
134141 rt_exit_critical_safe (critical_level );
135142
@@ -423,12 +430,15 @@ RTM_EXPORT(rt_thread_startup);
423430 */
424431rt_err_t rt_thread_close (rt_thread_t thread )
425432{
433+ rt_err_t error ;
426434 rt_sched_lock_level_t slvl ;
427435 rt_uint8_t thread_status ;
428436
429437 /* forbid scheduling on current core if closing current thread */
430438 RT_ASSERT (thread != rt_thread_self () || rt_critical_level ());
431439
440+ error = RT_EOK ;
441+
432442 /* before checking status of scheduler */
433443 rt_sched_lock (& slvl );
434444
@@ -447,12 +457,56 @@ rt_err_t rt_thread_close(rt_thread_t thread)
447457
448458 /* change stat */
449459 rt_sched_thread_close (thread );
460+
461+ #ifdef RT_USING_SMP
462+ int cpu_id ;
463+ rt_tick_t timeout = RT_TICK_PER_SECOND ;
464+ rt_bool_t need_wait = RT_FALSE ;
465+
466+ cpu_id = RT_SCHED_CTX (thread ).oncpu ;
467+
468+ if ((cpu_id != RT_CPU_DETACHED ) && (cpu_id != rt_cpu_get_id ()))
469+ {
470+ rt_hw_ipi_send (RT_SCHEDULE_IPI , RT_CPU_MASK ^ (1 << cpu_id ));
471+ need_wait = RT_TRUE ;
472+ }
473+
474+ rt_sched_unlock (slvl );
475+
476+ while (need_wait && timeout -- )
477+ {
478+ rt_sched_lock (& slvl );
479+
480+ cpu_id = RT_SCHED_CTX (thread ).oncpu ;
481+
482+ rt_sched_unlock (slvl );
483+
484+ if (cpu_id == RT_CPU_DETACHED )
485+ {
486+ break ;
487+ }
488+ }
489+
490+ if (need_wait && timeout == 0 )
491+ {
492+ error = - RT_ETIMEOUT ;
493+ }
494+
495+ return error ;
496+ #endif
497+ }
498+ else
499+ {
500+ /* Avoid duplicate closing: If the thread is already closed, return an error.
501+ * This prevents race conditions when multiple threads call close/detach/delete concurrently.
502+ */
503+ error = - RT_ERROR ;
450504 }
451505
452506 /* scheduler works are done */
453507 rt_sched_unlock (slvl );
454508
455- return RT_EOK ;
509+ return error ;
456510}
457511RTM_EXPORT (rt_thread_close );
458512
@@ -491,10 +545,17 @@ static rt_err_t _thread_detach(rt_thread_t thread)
491545
492546 error = rt_thread_close (thread );
493547
494- _thread_detach_from_mutex (thread );
495-
496- /* insert to defunct thread list */
497- rt_thread_defunct_enqueue (thread );
548+ if (error == RT_EOK )
549+ {
550+ /* Only proceed if rt_thread_close() succeeded.
551+ * This ensures thread resources are safely released before detaching mutexes
552+ * and enqueueing to the defunct list.
553+ */
554+ _thread_detach_from_mutex (thread );
555+
556+ /* insert to defunct thread list */
557+ rt_thread_defunct_enqueue (thread );
558+ }
498559
499560 rt_exit_critical_safe (critical_level );
500561 return error ;
@@ -1142,4 +1203,4 @@ rt_err_t rt_thread_get_name(rt_thread_t thread, char *name, rt_uint8_t name_size
11421203}
11431204RTM_EXPORT (rt_thread_get_name );
11441205
1145- /**@}*/
1206+ /**@}*/
0 commit comments