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,9 +430,12 @@ 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 ;
428-
436+
437+ error = RT_EOK ;
438+
429439 /* forbid scheduling on current core if closing current thread */
430440 RT_ASSERT (thread != rt_thread_self () || rt_critical_level ());
431441
@@ -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,12 +545,20 @@ 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 );
561+
500562 return error ;
501563}
502564
@@ -1143,3 +1205,4 @@ rt_err_t rt_thread_get_name(rt_thread_t thread, char *name, rt_uint8_t name_size
11431205RTM_EXPORT (rt_thread_get_name );
11441206
11451207/**@}*/
1208+
0 commit comments