Skip to content
Merged
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
54 changes: 42 additions & 12 deletions src/utest/smp/smp_assigned_idle_cores_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,52 @@
* @note Create multiple threads untied core threads, run them for a while on each core to see
* if the threads are automatically distributed evenly, run for a while to output the threads
* running on each core.
*
* Test Case Name: [smp_assigned_idle_cores]
*
* Test Objectives:
* - Test whether ready threads unbound to cores can be automatically allocated
* - to idle cores under the SMP architecture.
*
* Test Scenarios:
* - Under the SMP architecture, each core spends most of its time running the
* - idle thread after the system starts. At this point, create RT_CPUS_NR-1 cyclic
* - tasks and observe whether these tasks can be evenly distributed across all
* - cores for execution. Since the thread running the utest occupies one core, it
* - is only necessary to observe whether the remaining (RT_CPUS_NR - 1) cores can
* - be allocated the newly created threads and execute them.
*
* Verification Metrics:
* - After running this test case, it is necessary to observe the printed thread
* - list, where all threads created with names from T0 to T(RT_CPUS_NR-2) must
* - be in the running state. RT_CPUS_NR must be greater than or equal to 2.
*
* Dependencies:
* - RT_USING_SMP needs to be enabled.
*
* Expected Results:
* - Print the thread list on the terminal, and observe that T0 to T(RT_CPUS_NR-2)
* - are all in the running state, with the output "[ PASSED ] [ result ] testcase
* - (core.smp_assigned_idle_cores)".
*/

#define THREAD_STACK_SIZE UTEST_THR_STACK_SIZE
#define THREAD_PRIORITY 20
static rt_thread_t threads[RT_CPUS_NR];
static int tick = 0, finsh_flag = 0;
static rt_thread_t threads[RT_CPUS_NR - 1];
static int tick = 0, finish_flag = 0;
static int num = 0;
/* thread entry function */
static void thread_entry(void *parameter)
{
int value = *(int *)parameter;
while (1)
{
tick++;
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Concurrency/并发]: Potential race condition on shared variable tick

English: Multiple threads increment the shared variable tick without synchronization (line 60). In an SMP environment, this creates a race condition where concurrent increments from different cores can lead to lost updates. While this may not affect the test's primary purpose (observing thread distribution), it could cause the tick >= 100 condition to be reached unreliably. Consider using atomic operations (rt_atomic_t and atomic increment) or protecting the increment with a lock.

中文: 多个线程在没有同步的情况下递增共享变量 tick(第60行)。在 SMP 环境中,这会产生竞态条件,来自不同核心的并发递增可能导致更新丢失。虽然这可能不影响测试的主要目的(观察线程分布),但可能导致 tick >= 100 条件不可靠地到达。建议使用原子操作(rt_atomic_t 和原子递增)或使用锁保护递增操作。

Copilot uses AI. Check for mistakes.
if (tick == 100)
if (tick >= 100 && (finish_flag & (1 << value)) == 0)
{
/* Output the current core running threads */
extern long list_thread(void);
list_thread();
finsh_flag = 0xA55A;
rt_atomic_or((volatile rt_atomic_t *)&finish_flag, (1 << value));
uassert_true(1);
}
Copy link

Copilot AI Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Performance/性能]: Busy-wait loop consuming CPU cycles

English: The thread entry function now contains a tight busy-wait loop without any delay (line 58-66). Previously, rt_thread_delay(5) was called at line 66 (old code), which yielded the CPU and allowed the scheduler to run other threads. Removing this delay causes all threads to continuously spin in busy loops, consuming 100% CPU on all cores. This could interfere with the test's ability to observe proper thread distribution, as the system is now under heavy load rather than demonstrating idle core assignment. Consider adding a small delay or yield operation to make the test more realistic.

中文: 线程入口函数现在包含一个紧密的忙等循环,没有任何延迟(第58-66行)。之前在第66行(旧代码)调用了 rt_thread_delay(5),它会让出 CPU 并允许调度器运行其他线程。移除此延迟会导致所有线程在忙循环中持续旋转,在所有核心上消耗 100% CPU。这可能会干扰测试观察正确线程分布的能力,因为系统现在处于重负载状态,而不是展示空闲核心分配。建议添加一个小的延迟或让出操作,使测试更加真实。

Suggested change
}
}
rt_thread_delay(5);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加延时会让线程处于suspend态,导致观察不到新创建的线程是否被均匀分配到了空闲hart上。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加延时会让线程处于suspend态,导致观察不到新创建的线程是否被均匀分配到了空闲hart上。

是的,你这个改动合理

rt_thread_delay(5);
}
}

Expand All @@ -54,8 +78,8 @@ static void thread_on_idle_core_tc(void)
params[i] = i;
}

/* Create RT_CPUS_NR threads and pass the entry parameters for each thread */
for (i = 0; i < RT_CPUS_NR; i++)
/* Create RT_CPUS_NR-1 threads and pass the entry parameters for each thread */
for (i = 0; i < RT_CPUS_NR - 1; i++)
{
rt_snprintf(thread_name, sizeof(thread_name), "T%d", i);
threads[i] = rt_thread_create(thread_name, thread_entry, &params[i], THREAD_STACK_SIZE, THREAD_PRIORITY, 20);
Expand All @@ -66,18 +90,23 @@ static void thread_on_idle_core_tc(void)
}
}
/* Waiting for test cases to finish */
while (finsh_flag != 0xA55A);
while (finish_flag != (1<<(RT_CPUS_NR-1))-1);
/* Output the current core running threads */
extern long list_thread(void);
list_thread();
}

static rt_err_t utest_tc_init(void)
{
finish_flag = 0;
tick = 0;
rt_kprintf("[Test case]: created threads are automatically assigned to run on idle cores\r\n");
return RT_EOK;
}

static rt_err_t utest_tc_cleanup(void)
{
for (num = 0; num < RT_CPUS_NR; num++)
for (num = 0; num < RT_CPUS_NR - 1; num++)
{
rt_thread_delete(threads[num]);
}
Expand All @@ -89,3 +118,4 @@ static void testcase(void)
UTEST_UNIT_RUN(thread_on_idle_core_tc);
}
UTEST_TC_EXPORT(testcase, "core.smp_assigned_idle_cores", utest_tc_init, utest_tc_cleanup, 10);