11/*
2- * Copyright (c) 2006-2022 , RT-Thread Development Team
2+ * Copyright (c) 2006-2025 , RT-Thread Development Team
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 *
@@ -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,6 +430,7 @@ 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
@@ -447,12 +455,56 @@ rt_err_t rt_thread_close(rt_thread_t thread)
447455
448456 /* change stat */
449457 rt_sched_thread_close (thread );
458+
459+ #ifdef RT_USING_SMP
460+ int cpu_id ;
461+ rt_tick_t timeout = RT_TICK_PER_SECOND ;
462+ rt_bool_t need_wait = RT_FALSE ;
463+
464+ cpu_id = RT_SCHED_CTX (thread ).oncpu ;
465+
466+ if ((cpu_id != RT_CPU_DETACHED ) && (cpu_id != rt_cpu_get_id ()))
467+ {
468+ rt_hw_ipi_send (RT_SCHEDULE_IPI , RT_CPU_MASK ^ (1 << cpu_id ));
469+ need_wait = RT_TRUE ;
470+ }
471+
472+ rt_sched_unlock (slvl );
473+
474+ while (need_wait && timeout -- )
475+ {
476+ rt_sched_lock (& slvl );
477+
478+ cpu_id = RT_SCHED_CTX (thread ).oncpu ;
479+
480+ rt_sched_unlock (slvl );
481+
482+ if (cpu_id == RT_CPU_DETACHED )
483+ {
484+ break ;
485+ }
486+ }
487+
488+ if (need_wait && timeout == 0 )
489+ {
490+ error = - RT_ETIMEOUT ;
491+ }
492+
493+ return error ;
494+ #endif
495+ }
496+ else
497+ {
498+ /* Avoid duplicate closing: If the thread is already closed, return an error.
499+ * This prevents race conditions when multiple threads call close/detach/delete concurrently.
500+ */
501+ error == - RT_ERROR ;
450502 }
451503
452504 /* scheduler works are done */
453505 rt_sched_unlock (slvl );
454506
455- return RT_EOK ;
507+ return error ;
456508}
457509RTM_EXPORT (rt_thread_close );
458510
@@ -491,12 +543,20 @@ static rt_err_t _thread_detach(rt_thread_t thread)
491543
492544 error = rt_thread_close (thread );
493545
494- _thread_detach_from_mutex (thread );
495-
496- /* insert to defunct thread list */
497- rt_thread_defunct_enqueue (thread );
546+ if (error == RT_EOK )
547+ {
548+ /* Only proceed if rt_thread_close() succeeded.
549+ * This ensures thread resources are safely released before detaching mutexes
550+ * and enqueueing to the defunct list.
551+ */
552+ _thread_detach_from_mutex (thread );
553+
554+ /* insert to defunct thread list */
555+ rt_thread_defunct_enqueue (thread );
556+ }
498557
499558 rt_exit_critical_safe (critical_level );
559+
500560 return error ;
501561}
502562
@@ -1143,3 +1203,4 @@ rt_err_t rt_thread_get_name(rt_thread_t thread, char *name, rt_uint8_t name_size
11431203RTM_EXPORT (rt_thread_get_name );
11441204
11451205/**@}*/
1206+
0 commit comments