Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ config RT_CPUS_NR
help
Number of CPUs in the system

config RT_SMP_THREAD_DETACH_TIMEOUT
int "SMP thread detach timeout (ms)"
depends on RT_USING_SMP
default 2000
range 100 5000
help
Timeout value for waiting thread to detach from CPU in SMP mode.
Adjust based on hardware characteristics and system load.

config RT_ALIGN_SIZE
int "Alignment size for CPU architecture data access"
default 8
Expand Down
67 changes: 61 additions & 6 deletions src/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,12 +423,15 @@ RTM_EXPORT(rt_thread_startup);
*/
rt_err_t rt_thread_close(rt_thread_t thread)
{
rt_err_t error;
rt_sched_lock_level_t slvl;
rt_uint8_t thread_status;

/* forbid scheduling on current core if closing current thread */
RT_ASSERT(thread != rt_thread_self() || rt_critical_level());

error = RT_EOK;

/* before checking status of scheduler */
rt_sched_lock(&slvl);

Expand All @@ -447,12 +450,60 @@ rt_err_t rt_thread_close(rt_thread_t thread)

/* change stat */
rt_sched_thread_close(thread);
}

#ifdef RT_USING_SMP
int cpu_id;
rt_tick_t start_tick;
rt_tick_t timeout = rt_tick_from_millisecond(RT_SMP_THREAD_DETACH_TIMEOUT);
rt_bool_t need_wait = RT_FALSE;

/**
* in SMP, the current thread and target thread may run on different CPUs.
* although we set the target thread's state to closed, it may still execute
* on another CPU until rescheduled. send IPI to force immediate rescheduling.
*/
cpu_id = RT_SCHED_CTX(thread).oncpu;
rt_sched_unlock(slvl);
if ((cpu_id != RT_CPU_DETACHED) && (cpu_id != rt_cpu_get_id()))
{
rt_hw_ipi_send(RT_SCHEDULE_IPI, RT_CPU_MASK ^ (1 << cpu_id));
need_wait = RT_TRUE;
}

start_tick = rt_tick_get();

/**
* continuously check if target thread has detached from CPU core.
* this loop ensures the thread fully stops before resource cleanup.
* a timeout prevents deadlock if thread fails to detach promptly.
*/
while (need_wait)
{
if (rt_tick_get_delta(start_tick) >= timeout)
{
LOG_D("Timeout waiting for thread %s (tid=%p) to detach from CPU%d",
thread->parent.name, thread, cpu_id);
error = -RT_ETIMEOUT;
break;
}

rt_sched_lock(&slvl);
cpu_id = RT_SCHED_CTX(thread).oncpu;
rt_sched_unlock(slvl);

if (cpu_id == RT_CPU_DETACHED)
{
break;
}
}

return error;
#endif
}
/* scheduler works are done */
rt_sched_unlock(slvl);

return RT_EOK;
return error;
}
RTM_EXPORT(rt_thread_close);

Expand Down Expand Up @@ -491,10 +542,14 @@ static rt_err_t _thread_detach(rt_thread_t thread)

error = rt_thread_close(thread);

_thread_detach_from_mutex(thread);
/* only when the current thread has successfully closed the target thread. */
if (error == RT_EOK)
{
_thread_detach_from_mutex(thread);

/* insert to defunct thread list */
rt_thread_defunct_enqueue(thread);
/* insert to defunct thread list */
rt_thread_defunct_enqueue(thread);
}

rt_exit_critical_safe(critical_level);
return error;
Expand Down Expand Up @@ -1142,4 +1197,4 @@ rt_err_t rt_thread_get_name(rt_thread_t thread, char *name, rt_uint8_t name_size
}
RTM_EXPORT(rt_thread_get_name);

/**@}*/
/**@}*/