1 /*
2 * Copyright (c) 2006-2024, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2024-08-10 RV the first version
9 */
10
11 #include <rtthread.h>
12 #include "utest.h"
13
14 /**
15 * @brief Threads are automatically balanced across cores.
16 *
17 * @note Create RT_CPUS_NR threads, thread 0 is not bound to core 0, higher priority, the priority of the other
18 * threads for the system's highest and the thread entry function does not let out the CPU control, run the
19 * specified number of times after the creation of thread 0 in thread 0, a low-priority bound to the core 0,
20 * the thread will not preempt the core 0 is running on threads
21 */
22
23 /* Number of thread runs */
24 static int run_num = 10;
25 #define THREAD_STACK_SIZE UTEST_THR_STACK_SIZE
26 #define THREAD_PRIORITY 2
27 #define LOW_PRIORITY 50
28 #define THIGH_PRIORITY 10
29 static rt_thread_t threads[RT_CPUS_NR];
30 static rt_thread_t temp_thread;
31 static struct rt_spinlock lock;
32 static int thread_inc = 0;
33 static int run_flag = 0;
34 static int num = 0;
35
thread_temp_entry(void * parameter)36 static void thread_temp_entry(void *parameter)
37 {
38 run_flag = 1;
39 rt_thread_delete(temp_thread);
40 }
41
thread_entry(void * parameter)42 static void thread_entry(void *parameter)
43 {
44 int id = 0;
45 int para = *(int *)parameter;
46 while (1)
47 {
48 thread_inc++;
49 id = rt_hw_cpu_id();
50 if (para == 0)
51 {
52 if (thread_inc == run_num)
53 {
54 uassert_int_equal(id, 0);
55 temp_thread = rt_thread_create("Tn", thread_temp_entry, RT_NULL, THREAD_STACK_SIZE, LOW_PRIORITY, 20);
56
57 if (temp_thread != RT_NULL)
58 {
59 rt_thread_control(temp_thread, RT_THREAD_CTRL_BIND_CPU, (void *)0);
60 rt_thread_startup(temp_thread);
61 uassert_int_not_equal(run_flag, 1);
62 }
63 }
64 rt_thread_delay(5);
65 }
66 else
67 {
68 uassert_int_not_equal(id, 0);
69 while (1);
70 }
71 }
72 }
73
smp_affinity_pri2_tc(void)74 static void smp_affinity_pri2_tc(void)
75 {
76 static int params[RT_CPUS_NR] = {0};
77 char thread_name[8];
78 int i;
79
80 for (i = 0; i < RT_CPUS_NR; i++)
81 {
82 params[i] = i;
83 }
84
85 threads[0] = rt_thread_create("T0", thread_entry, (int *)¶ms[0], THREAD_STACK_SIZE, THIGH_PRIORITY, 20);
86
87 if (threads[0] != RT_NULL)
88 {
89 uassert_true(1);
90 rt_thread_startup(threads[0]);
91 }
92
93 /* Create high-priority unbound threads with thread functions that don't let out CPU control */
94 for (i = 1; i < RT_CPUS_NR; i++)
95 {
96 rt_snprintf(thread_name, sizeof(thread_name), "T%d", i);
97 threads[i] = rt_thread_create(thread_name, thread_entry, (int *)¶ms[i], THREAD_STACK_SIZE, THREAD_PRIORITY, 20);
98
99 if (threads[i] != RT_NULL)
100 {
101 uassert_true(1);
102 rt_thread_control(threads[i], RT_THREAD_CTRL_BIND_CPU, (void *)i);
103 rt_thread_startup(threads[i]);
104 }
105 }
106 rt_thread_delay(50);
107 }
108
utest_tc_init(void)109 static rt_err_t utest_tc_init(void)
110 {
111 rt_spin_lock_init(&lock);
112 return RT_EOK;
113 }
114
utest_tc_cleanup(void)115 static rt_err_t utest_tc_cleanup(void)
116 {
117 for (num = 0; num < RT_CPUS_NR; num++)
118 {
119 rt_thread_delete(threads[num]);
120 }
121 return RT_EOK;
122 }
123
testcase(void)124 static void testcase(void)
125 {
126 UTEST_UNIT_RUN(smp_affinity_pri2_tc);
127 }
128 UTEST_TC_EXPORT(testcase, "testcases.smp.affinity_pri2_tc", utest_tc_init, utest_tc_cleanup, 10);
129