summaryrefslogtreecommitdiff
path: root/src/utest/smp/smp_assigned_idle_cores_tc.c
blob: 94092959f9954ee7f33e5fad3b7fe6fbd6836fd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
 * Copyright (c) 2006-2024, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-08-10     RV           the first version
 */

#include <rtthread.h>
#include "utest.h"

/**
 * @brief   Threads are automatically balanced across cores.
 *
 * @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 - 1];
static int         tick = 0;
static rt_align(sizeof(rt_ubase_t)) int finish_flag = 0;
static int                num        = 0;
/* thread entry function */
static void thread_entry(void *parameter)
{
    int value = *(int *)parameter;
    while (1)
    {
        tick++;
        if (tick >= 100 && (finish_flag & (1 << value)) == 0)
        {
            rt_atomic_or((volatile rt_atomic_t *)&finish_flag, (1 << value));
            uassert_true(1);
        }
    }
}

static void thread_on_idle_core_tc(void)
{
    static int params[RT_CPUS_NR] = {0};
    char       thread_name[8];
    int        i;

    /* Initialise the thread entry parameters */
    for (i = 0; i < RT_CPUS_NR; i++)
    {
        params[i] = 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);
        if (threads[i] != RT_NULL)
        {
            uassert_true(1);
            rt_thread_startup(threads[i]);
        }
    }
    /* Waiting for test cases to finish */
    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 - 1; num++)
    {
        rt_thread_delete(threads[num]);
    }
    return RT_EOK;
}

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);