1 /*
2 * Copyright (c) 2018 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/tc_util.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/kernel.h>
10 #include <ksched.h>
11 #include <zephyr/kernel_structs.h>
12
13 #if CONFIG_MP_MAX_NUM_CPUS < 2
14 #error SMP test requires at least two CPUs!
15 #endif
16
17 /*
18 * The test is designed to work with no more than 12 CPUs.
19 * If attempting to run on a platform with more than that,
20 * create a custom board overlay file to reduce the number
21 * of CPUs to 12.
22 */
23 #if CONFIG_MP_MAX_NUM_CPUS > 12
24 #error "Test only supports up to 12 CPUs\nReduce CONFIG_MP_MAX_NUM_CPUS\n"
25 #endif
26
27 #define RUN_FACTOR (CONFIG_SMP_TEST_RUN_FACTOR / 100.0)
28
29 #define T2_STACK_SIZE (2048 + CONFIG_TEST_EXTRA_STACK_SIZE)
30 #define STACK_SIZE (384 + CONFIG_TEST_EXTRA_STACK_SIZE)
31 #define DELAY_US 50000
32 #define TIMEOUT 5000
33 #define EQUAL_PRIORITY 1
34 #define TIME_SLICE_MS 500
35 #define THREAD_DELAY 1
36 #define SLEEP_MS_LONG ((int)(15000 * RUN_FACTOR))
37
38 struct k_thread t2;
39 K_THREAD_STACK_DEFINE(t2_stack, T2_STACK_SIZE);
40
41 volatile int t2_count;
42 volatile int sync_count = -1;
43
44 static int main_thread_id;
45 static int child_thread_id;
46 volatile int rv;
47
48 K_SEM_DEFINE(cpuid_sema, 0, 1);
49 K_SEM_DEFINE(sema, 0, 1);
50 static struct k_mutex smutex;
51 static struct k_sem smp_sem;
52
53 #define MAX_NUM_THREADS CONFIG_MP_MAX_NUM_CPUS
54
55 struct thread_info {
56 k_tid_t tid;
57 int executed;
58 int priority;
59 int cpu_id;
60 };
61 static ZTEST_BMEM volatile struct thread_info tinfo[MAX_NUM_THREADS];
62 static struct k_thread tthread[MAX_NUM_THREADS];
63 static K_THREAD_STACK_ARRAY_DEFINE(tstack, MAX_NUM_THREADS, STACK_SIZE);
64
65 static volatile int thread_started[MAX_NUM_THREADS - 1];
66
67 static struct k_poll_signal tsignal[MAX_NUM_THREADS];
68 static struct k_poll_event tevent[MAX_NUM_THREADS];
69
curr_cpu(void)70 static int curr_cpu(void)
71 {
72 unsigned int k = arch_irq_lock();
73 int ret = arch_curr_cpu()->id;
74
75 arch_irq_unlock(k);
76 return ret;
77 }
78
79 /**
80 * @brief SMP
81 * @defgroup kernel_smp_tests SMP Tests
82 * @ingroup all_tests
83 * @{
84 * @}
85 */
86
87 /**
88 * @defgroup kernel_smp_integration_tests SMP Integration Tests
89 * @ingroup kernel_smp_tests
90 * @{
91 * @}
92 */
93
94 /**
95 * @defgroup kernel_smp_module_tests SMP Module Tests
96 * @ingroup kernel_smp_tests
97 * @{
98 * @}
99 */
100
t2_fn(void * a,void * b,void * c)101 static void t2_fn(void *a, void *b, void *c)
102 {
103 ARG_UNUSED(a);
104 ARG_UNUSED(b);
105 ARG_UNUSED(c);
106
107 t2_count = 0;
108
109 /* This thread simply increments a counter while spinning on
110 * the CPU. The idea is that it will always be iterating
111 * faster than the other thread so long as it is fairly
112 * scheduled (and it's designed to NOT be fairly schedulable
113 * without a separate CPU!), so the main thread can always
114 * check its progress.
115 */
116 while (1) {
117 k_busy_wait(DELAY_US);
118 t2_count++;
119 }
120 }
121
122 /**
123 * @brief Verify SMP with 2 cooperative threads
124 *
125 * @ingroup kernel_smp_tests
126 *
127 * @details Multi processing is verified by checking whether
128 * 2 cooperative threads run simultaneously at different cores
129 */
ZTEST(smp,test_smp_coop_threads)130 ZTEST(smp, test_smp_coop_threads)
131 {
132 int i, ok = 1;
133
134 if (!IS_ENABLED(CONFIG_SCHED_IPI_SUPPORTED)) {
135 /* The spawned thread enters an infinite loop, so it can't be
136 * successfully aborted via an IPI. Just skip in that
137 * configuration.
138 */
139 ztest_test_skip();
140 }
141
142 k_tid_t tid = k_thread_create(&t2, t2_stack, T2_STACK_SIZE, t2_fn,
143 NULL, NULL, NULL,
144 K_PRIO_COOP(2), 0, K_NO_WAIT);
145
146 /* Wait for the other thread (on a separate CPU) to actually
147 * start running. We want synchrony to be as perfect as
148 * possible.
149 */
150 t2_count = -1;
151 while (t2_count == -1) {
152 }
153
154 for (i = 0; i < 10; i++) {
155 /* Wait slightly longer than the other thread so our
156 * count will always be lower
157 */
158 k_busy_wait(DELAY_US + (DELAY_US / 8));
159
160 if (t2_count <= i) {
161 ok = 0;
162 break;
163 }
164 }
165
166 k_thread_abort(tid);
167 k_thread_join(tid, K_FOREVER);
168 zassert_true(ok, "SMP test failed");
169 }
170
child_fn(void * p1,void * p2,void * p3)171 static void child_fn(void *p1, void *p2, void *p3)
172 {
173 ARG_UNUSED(p2);
174 ARG_UNUSED(p3);
175 int parent_cpu_id = POINTER_TO_INT(p1);
176
177 zassert_true(parent_cpu_id != curr_cpu(),
178 "Parent isn't on other core");
179
180 sync_count++;
181 k_sem_give(&cpuid_sema);
182 }
183
184 /**
185 * @brief Verify CPU IDs of threads in SMP
186 *
187 * @ingroup kernel_smp_tests
188 *
189 * @details Verify whether thread running on other core is
190 * parent thread from child thread
191 */
ZTEST(smp,test_cpu_id_threads)192 ZTEST(smp, test_cpu_id_threads)
193 {
194 /* Make sure idle thread runs on each core */
195 k_sleep(K_MSEC(1000));
196
197 int parent_cpu_id = curr_cpu();
198
199 k_tid_t tid = k_thread_create(&t2, t2_stack, T2_STACK_SIZE, child_fn,
200 INT_TO_POINTER(parent_cpu_id), NULL,
201 NULL, K_PRIO_PREEMPT(2), 0, K_NO_WAIT);
202
203 while (sync_count == -1) {
204 }
205 k_sem_take(&cpuid_sema, K_FOREVER);
206
207 k_thread_abort(tid);
208 k_thread_join(tid, K_FOREVER);
209 }
210
thread_entry_fn(void * p1,void * p2,void * p3)211 static void thread_entry_fn(void *p1, void *p2, void *p3)
212 {
213 ARG_UNUSED(p2);
214 ARG_UNUSED(p3);
215 int thread_num = POINTER_TO_INT(p1);
216 int count = 0;
217
218 tinfo[thread_num].executed = 1;
219 tinfo[thread_num].cpu_id = curr_cpu();
220
221 while (count++ < 5) {
222 k_busy_wait(DELAY_US);
223 }
224 }
225
spin_for_threads_exit(void)226 static void spin_for_threads_exit(void)
227 {
228 unsigned int num_threads = arch_num_cpus();
229
230 for (int i = 0; i < num_threads - 1; i++) {
231 volatile uint8_t *p = &tinfo[i].tid->base.thread_state;
232
233 while (!(*p & _THREAD_DEAD)) {
234 }
235 }
236 k_busy_wait(DELAY_US);
237 }
238
spawn_threads(int prio,int thread_num,int equal_prio,k_thread_entry_t thread_entry,int delay)239 static void spawn_threads(int prio, int thread_num, int equal_prio,
240 k_thread_entry_t thread_entry, int delay)
241 {
242 int i;
243
244 /* Spawn threads of priority higher than
245 * the previously created thread
246 */
247 for (i = 0; i < thread_num; i++) {
248 if (equal_prio) {
249 tinfo[i].priority = prio;
250 } else {
251 /* Increase priority for each thread */
252 tinfo[i].priority = prio - 1;
253 prio = tinfo[i].priority;
254 }
255 tinfo[i].tid = k_thread_create(&tthread[i], tstack[i],
256 STACK_SIZE, thread_entry,
257 INT_TO_POINTER(i), NULL, NULL,
258 tinfo[i].priority, 0,
259 K_MSEC(delay));
260 if (delay) {
261 /* Increase delay for each thread */
262 delay = delay + 10;
263 }
264 }
265 }
266
abort_threads(int num)267 static void abort_threads(int num)
268 {
269 for (int i = 0; i < num; i++) {
270 k_thread_abort(tinfo[i].tid);
271 }
272
273 for (int i = 0; i < num; i++) {
274 k_thread_join(tinfo[i].tid, K_FOREVER);
275 }
276 }
277
cleanup_resources(void)278 static void cleanup_resources(void)
279 {
280 unsigned int num_threads = arch_num_cpus();
281
282 for (int i = 0; i < num_threads; i++) {
283 tinfo[i].tid = 0;
284 tinfo[i].executed = 0;
285 tinfo[i].priority = 0;
286 }
287 }
288
thread_ab_entry(void * p1,void * p2,void * p3)289 static void __no_optimization thread_ab_entry(void *p1, void *p2, void *p3)
290 {
291 ARG_UNUSED(p1);
292 ARG_UNUSED(p2);
293 ARG_UNUSED(p3);
294
295 while (true) {
296 }
297 }
298
299 #define SPAWN_AB_PRIO K_PRIO_COOP(10)
300
301 /**
302 * @brief Verify the code path when we do context switch in k_thread_abort on SMP system
303 *
304 * @ingroup kernel_smp_tests
305 *
306 * @details test logic:
307 * - The ztest thread has cooperative priority.
308 * - From ztest thread we spawn N number of cooperative threads, where N = number of CPUs.
309 * - The spawned cooperative are executing infinite loop (so they occupy CPU core until they are
310 * aborted).
311 * - We have (number of CPUs - 1) spawned threads run and executing infinite loop, as current CPU
312 * is occupied by ztest cooperative thread. Due to that the last of spawned threads is ready but
313 * not executing.
314 * - We abort spawned threads one-by-one from the ztest thread.
315 * - At the first k_thread_abort call the ztest thread will be preempted by the remaining spawned
316 * thread which has higher priority than ztest thread.
317 * But... k_thread_abort call should has destroyed one of the spawned threads, so ztest thread
318 * should have a CPU available to run on.
319 * - We expect that all spawned threads will be aborted successfully.
320 *
321 * This was the test case for zephyrproject-rtos/zephyr#58040 issue where this test caused system
322 * hang.
323 */
324
ZTEST(smp,test_coop_switch_in_abort)325 ZTEST(smp, test_coop_switch_in_abort)
326 {
327 k_tid_t tid[MAX_NUM_THREADS];
328 unsigned int num_threads = arch_num_cpus();
329 unsigned int i;
330
331 zassert_true(_current->base.prio < 0, "test case relies on ztest thread be cooperative");
332 zassert_true(_current->base.prio > SPAWN_AB_PRIO,
333 "spawn test need to have higher priority than ztest thread");
334
335 /* Spawn N number of cooperative threads, where N = number of CPUs */
336 for (i = 0; i < num_threads; i++) {
337 tid[i] = k_thread_create(&tthread[i], tstack[i],
338 STACK_SIZE, thread_ab_entry,
339 NULL, NULL, NULL,
340 SPAWN_AB_PRIO, 0, K_NO_WAIT);
341 }
342
343 /* Wait for some time to let spawned threads on other cores run and start executing infinite
344 * loop.
345 */
346 k_busy_wait(DELAY_US * 4);
347
348 /* At this time we have (number of CPUs - 1) spawned threads run and executing infinite loop
349 * on other CPU cores, as current CPU is occupied by this ztest cooperative thread.
350 * Due to that the last of spawned threads is ready but not executing.
351 */
352
353 /* Abort all spawned threads one-by-one. At the first k_thread_abort call the context
354 * switch will happen and the last 'spawned' thread will start.
355 * We should successfully abort all threads.
356 */
357 for (i = 0; i < num_threads; i++) {
358 k_thread_abort(tid[i]);
359 }
360
361 /* Cleanup */
362 for (i = 0; i < num_threads; i++) {
363 zassert_equal(k_thread_join(tid[i], K_FOREVER), 0);
364 }
365 }
366
367 /**
368 * @brief Test cooperative threads non-preemption
369 *
370 * @ingroup kernel_smp_tests
371 *
372 * @details Spawn cooperative threads equal to number of cores
373 * supported. Main thread will already be running on 1 core.
374 * Check if the last thread created preempts any threads
375 * already running.
376 */
ZTEST(smp,test_coop_resched_threads)377 ZTEST(smp, test_coop_resched_threads)
378 {
379 unsigned int num_threads = arch_num_cpus();
380
381 /* Spawn threads equal to number of cores,
382 * since we don't give up current CPU, last thread
383 * will not get scheduled
384 */
385 spawn_threads(K_PRIO_COOP(12), num_threads, !EQUAL_PRIORITY,
386 &thread_entry_fn, THREAD_DELAY);
387
388 /* Wait for some time to let other core's thread run */
389 k_busy_wait(DELAY_US * 5);
390
391
392 /* Reassure that cooperative thread's are not preempted
393 * by checking last thread's execution
394 * status. We know that all threads got rescheduled on
395 * other cores except the last one
396 */
397 for (int i = 0; i < num_threads - 1; i++) {
398 zassert_true(tinfo[i].executed == 1,
399 "cooperative thread %d didn't run", i);
400 }
401 zassert_true(tinfo[num_threads - 1].executed == 0,
402 "cooperative thread is preempted");
403
404 /* Abort threads created */
405 abort_threads(num_threads);
406 cleanup_resources();
407 }
408
409 /**
410 * @brief Test preemptness of preemptive thread
411 *
412 * @ingroup kernel_smp_tests
413 *
414 * @details Create preemptive thread and let it run
415 * on another core and verify if it gets preempted
416 * if another thread of higher priority is spawned
417 */
ZTEST(smp,test_preempt_resched_threads)418 ZTEST(smp, test_preempt_resched_threads)
419 {
420 unsigned int num_threads = arch_num_cpus();
421
422 /* Spawn threads equal to number of cores,
423 * lower priority thread should
424 * be preempted by higher ones
425 */
426 spawn_threads(K_PRIO_PREEMPT(12), num_threads, !EQUAL_PRIORITY,
427 &thread_entry_fn, THREAD_DELAY);
428
429 spin_for_threads_exit();
430
431 for (int i = 0; i < num_threads; i++) {
432 zassert_true(tinfo[i].executed == 1,
433 "preemptive thread %d didn't run", i);
434 }
435
436 /* Abort threads created */
437 abort_threads(num_threads);
438 cleanup_resources();
439 }
440
441 /**
442 * @brief Validate behavior of thread when it yields
443 *
444 * @ingroup kernel_smp_tests
445 *
446 * @details Spawn cooperative threads equal to number
447 * of cores, so last thread would be pending, call
448 * yield() from main thread. Now, all threads must be
449 * executed
450 */
ZTEST(smp,test_yield_threads)451 ZTEST(smp, test_yield_threads)
452 {
453 unsigned int num_threads = arch_num_cpus();
454
455 /* Spawn threads equal to the number
456 * of cores, so the last thread would be
457 * pending.
458 */
459 spawn_threads(K_PRIO_COOP(12), num_threads, !EQUAL_PRIORITY,
460 &thread_entry_fn, !THREAD_DELAY);
461
462 k_yield();
463 k_busy_wait(DELAY_US * 5);
464
465 for (int i = 0; i < num_threads; i++) {
466 zassert_true(tinfo[i].executed == 1,
467 "thread %d did not execute", i);
468
469 }
470
471 abort_threads(num_threads);
472 cleanup_resources();
473 }
474
475 /**
476 * @brief Test behavior of thread when it sleeps
477 *
478 * @ingroup kernel_smp_tests
479 *
480 * @details Spawn cooperative thread and call
481 * sleep() from main thread. After timeout, all
482 * threads has to be scheduled.
483 */
ZTEST(smp,test_sleep_threads)484 ZTEST(smp, test_sleep_threads)
485 {
486 unsigned int num_threads = arch_num_cpus();
487
488 spawn_threads(K_PRIO_COOP(12), num_threads, !EQUAL_PRIORITY,
489 &thread_entry_fn, !THREAD_DELAY);
490
491 k_msleep(TIMEOUT);
492
493 for (int i = 0; i < num_threads; i++) {
494 zassert_true(tinfo[i].executed == 1,
495 "thread %d did not execute", i);
496 }
497
498 abort_threads(num_threads);
499 cleanup_resources();
500 }
501
thread_wakeup_entry(void * p1,void * p2,void * p3)502 static void thread_wakeup_entry(void *p1, void *p2, void *p3)
503 {
504 ARG_UNUSED(p2);
505 ARG_UNUSED(p3);
506 int thread_num = POINTER_TO_INT(p1);
507
508 thread_started[thread_num] = 1;
509
510 k_msleep(DELAY_US * 1000);
511
512 tinfo[thread_num].executed = 1;
513 }
514
wakeup_on_start_thread(int tnum)515 static void wakeup_on_start_thread(int tnum)
516 {
517 int threads_started = 0, i;
518
519 /* For each thread, spin waiting for it to first flag that
520 * it's going to sleep, and then that it's actually blocked
521 */
522 for (i = 0; i < tnum; i++) {
523 while (thread_started[i] == 0) {
524 }
525 while (!z_is_thread_prevented_from_running(tinfo[i].tid)) {
526 }
527 }
528
529 for (i = 0; i < tnum; i++) {
530 if (thread_started[i] == 1 && threads_started <= tnum) {
531 threads_started++;
532 k_wakeup(tinfo[i].tid);
533 }
534 }
535 zassert_equal(threads_started, tnum,
536 "All threads haven't started");
537 }
538
check_wokeup_threads(int tnum)539 static void check_wokeup_threads(int tnum)
540 {
541 int threads_woke_up = 0, i;
542
543 /* k_wakeup() isn't synchronous, give the other CPU time to
544 * schedule them
545 */
546 k_busy_wait(300000);
547
548 for (i = 0; i < tnum; i++) {
549 if (tinfo[i].executed == 1 && threads_woke_up <= tnum) {
550 threads_woke_up++;
551 }
552 }
553 zassert_equal(threads_woke_up, tnum, "Threads did not wakeup");
554 }
555
556 /**
557 * @brief Test behavior of wakeup() in SMP case
558 *
559 * @ingroup kernel_smp_tests
560 *
561 * @details Spawn number of threads equal to number of
562 * remaining cores and let them sleep for a while. Call
563 * wakeup() of those threads from parent thread and check
564 * if they are all running
565 */
ZTEST(smp,test_wakeup_threads)566 ZTEST(smp, test_wakeup_threads)
567 {
568 unsigned int num_threads = arch_num_cpus();
569
570 /* Spawn threads to run on all remaining cores */
571 spawn_threads(K_PRIO_COOP(12), num_threads - 1, !EQUAL_PRIORITY,
572 &thread_wakeup_entry, !THREAD_DELAY);
573
574 /* Check if all the threads have started, then call wakeup */
575 wakeup_on_start_thread(num_threads - 1);
576
577 /* Count threads which are woken up */
578 check_wokeup_threads(num_threads - 1);
579
580 /* Abort all threads and cleanup */
581 abort_threads(num_threads - 1);
582 cleanup_resources();
583 }
584
585 /* a thread for testing get current cpu */
thread_get_cpu_entry(void * p1,void * p2,void * p3)586 static void thread_get_cpu_entry(void *p1, void *p2, void *p3)
587 {
588 ARG_UNUSED(p1);
589 ARG_UNUSED(p2);
590 ARG_UNUSED(p3);
591
592 int bsp_id = *(int *)p1;
593 int cpu_id = -1;
594
595 /* get current cpu number for running thread */
596 _cpu_t *curr_cpu = arch_curr_cpu();
597
598 /**TESTPOINT: call arch_curr_cpu() to get cpu struct */
599 zassert_true(curr_cpu != NULL,
600 "test failed to get current cpu.");
601
602 cpu_id = curr_cpu->id;
603
604 zassert_true(bsp_id != cpu_id,
605 "should not be the same with our BSP");
606
607 /* loop forever to ensure running on this CPU */
608 while (1) {
609 k_busy_wait(DELAY_US);
610 }
611 }
612
613 /**
614 * @brief Test get a pointer of CPU
615 *
616 * @ingroup kernel_smp_module_tests
617 *
618 * @details
619 * Test Objective:
620 * - To verify architecture layer provides a mechanism to return a pointer to the
621 * current kernel CPU record of the running CPU.
622 * We call arch_curr_cpu() and get its member, both in main and spawned thread
623 * separately, and compare them. They shall be different in SMP environment.
624 *
625 * Testing techniques:
626 * - Interface testing, function and block box testing,
627 * dynamic analysis and testing,
628 *
629 * Prerequisite Conditions:
630 * - CONFIG_SMP=y, and the HW platform must support SMP.
631 *
632 * Input Specifications:
633 * - N/A
634 *
635 * Test Procedure:
636 * -# In main thread, call arch_curr_cpu() to get it's member "id",then store it
637 * into a variable thread_id.
638 * -# Spawn a thread t2, and pass the stored thread_id to it, then call
639 * k_busy_wait() 50us to wait for thread run and won't be swapped out.
640 * -# In thread t2, call arch_curr_cpu() to get pointer of current cpu data. Then
641 * check if it not NULL.
642 * -# Store the member id via accessing pointer of current cpu data to var cpu_id.
643 * -# Check if cpu_id is not equaled to bsp_id that we pass into thread.
644 * -# Call k_busy_wait() and loop forever.
645 * -# In main thread, terminate the thread t2 before exit.
646 *
647 * Expected Test Result:
648 * - The pointer of current cpu data that we got from function call is correct.
649 *
650 * Pass/Fail Criteria:
651 * - Successful if the check of step 3,5 are all passed.
652 * - Failure if one of the check of step 3,5 is failed.
653 *
654 * Assumptions and Constraints:
655 * - This test using for the platform that support SMP, in our current scenario
656 * , only x86_64, arc and xtensa supported.
657 *
658 * @see arch_curr_cpu()
659 */
660 static int _cpu_id;
ZTEST(smp,test_get_cpu)661 ZTEST(smp, test_get_cpu)
662 {
663 k_tid_t thread_id;
664
665 if (!IS_ENABLED(CONFIG_SCHED_IPI_SUPPORTED)) {
666 /* The spawned thread enters an infinite loop, so it can't be
667 * successfully aborted via an IPI. Just skip in that
668 * configuration.
669 */
670 ztest_test_skip();
671 }
672
673 /* get current cpu number */
674 _cpu_id = arch_curr_cpu()->id;
675
676 thread_id = k_thread_create(&t2, t2_stack, T2_STACK_SIZE,
677 thread_get_cpu_entry,
678 &_cpu_id, NULL, NULL,
679 K_PRIO_COOP(2),
680 K_INHERIT_PERMS, K_NO_WAIT);
681
682 k_busy_wait(DELAY_US);
683
684 k_thread_abort(thread_id);
685 k_thread_join(thread_id, K_FOREVER);
686 }
687
688 #ifdef CONFIG_TRACE_SCHED_IPI
689 /* global variable for testing send IPI */
690 static volatile int sched_ipi_has_called;
691
z_trace_sched_ipi(void)692 void z_trace_sched_ipi(void)
693 {
694 sched_ipi_has_called++;
695 }
696 #endif
697
698 /**
699 * @brief Test interprocessor interrupt
700 *
701 * @ingroup kernel_smp_integration_tests
702 *
703 * @details
704 * Test Objective:
705 * - To verify architecture layer provides a mechanism to issue an interprocessor
706 * interrupt to all other CPUs in the system that calls the scheduler IPI.
707 * We simply add a hook in z_sched_ipi(), in order to check if it has been
708 * called once in another CPU except the caller, when arch_sched_broadcast_ipi()
709 * is called.
710 *
711 * Testing techniques:
712 * - Interface testing, function and block box testing,
713 * dynamic analysis and testing
714 *
715 * Prerequisite Conditions:
716 * - CONFIG_SMP=y, and the HW platform must support SMP.
717 * - CONFIG_TRACE_SCHED_IPI=y was set.
718 *
719 * Input Specifications:
720 * - N/A
721 *
722 * Test Procedure:
723 * -# In main thread, given a global variable sched_ipi_has_called equaled zero.
724 * -# Call arch_sched_broadcast_ipi() then sleep for 100ms.
725 * -# In z_sched_ipi() handler, increment the sched_ipi_has_called.
726 * -# In main thread, check the sched_ipi_has_called is not equaled to zero.
727 * -# Repeat step 1 to 4 for 3 times.
728 *
729 * Expected Test Result:
730 * - The pointer of current cpu data that we got from function call is correct.
731 *
732 * Pass/Fail Criteria:
733 * - Successful if the check of step 4 are all passed.
734 * - Failure if one of the check of step 4 is failed.
735 *
736 * Assumptions and Constraints:
737 * - This test using for the platform that support SMP, in our current scenario
738 * , only x86_64 and arc supported.
739 *
740 * @see arch_sched_broadcast_ipi()
741 */
742 #ifdef CONFIG_SCHED_IPI_SUPPORTED
ZTEST(smp,test_smp_ipi)743 ZTEST(smp, test_smp_ipi)
744 {
745 #ifndef CONFIG_TRACE_SCHED_IPI
746 ztest_test_skip();
747 #else
748 TC_PRINT("There are %u CPUs.\n", arch_num_cpus());
749
750 for (int i = 0; i < CONFIG_SMP_IPI_NUM_ITERS; i++) {
751 int retries = CONFIG_SMP_IPI_WAIT_RETRIES;
752 /* issue a sched ipi to tell other CPU to run thread */
753 sched_ipi_has_called = 0;
754 arch_sched_broadcast_ipi();
755
756 /* Need to wait longer than we think, loaded CI
757 * systems need to wait for host scheduling to run the
758 * other CPU's thread.
759 */
760 while (retries > 0) {
761 k_msleep(CONFIG_SMP_IPI_WAIT_MS);
762
763 /* Bail out early if test is deemed a success. */
764 if (sched_ipi_has_called > 0) {
765 break;
766 }
767
768 retries--;
769 }
770
771 /**TESTPOINT: check if enter our IPI interrupt handler */
772 zassert_true(sched_ipi_has_called != 0,
773 "did not receive IPI.(%d,%d)", i,
774 sched_ipi_has_called);
775 }
776 #endif
777 }
778 #endif
779
k_sys_fatal_error_handler(unsigned int reason,const struct arch_esf * esf)780 void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf)
781 {
782 static int trigger;
783
784 if (reason != K_ERR_KERNEL_OOPS) {
785 printk("wrong error reason\n");
786 TC_END_REPORT(TC_FAIL);
787 k_fatal_halt(reason);
788 }
789
790 if (trigger == 0) {
791 child_thread_id = curr_cpu();
792 trigger++;
793 } else {
794 main_thread_id = curr_cpu();
795
796 /* Verify the fatal was happened on different core */
797 zassert_true(main_thread_id != child_thread_id,
798 "fatal on the same core");
799 }
800 }
801
entry_oops(void * p1,void * p2,void * p3)802 void entry_oops(void *p1, void *p2, void *p3)
803 {
804 k_oops();
805 TC_ERROR("SHOULD NEVER SEE THIS\n");
806 }
807
808 /**
809 * @brief Test fatal error can be triggered on different core
810
811 * @details When CONFIG_SMP is enabled, on some multiprocessor
812 * platforms, exception can be triggered on different core at
813 * the same time.
814 *
815 * @ingroup kernel_common_tests
816 */
ZTEST(smp,test_fatal_on_smp)817 ZTEST(smp, test_fatal_on_smp)
818 {
819 /* Creat a child thread and trigger a crash */
820 k_thread_create(&t2, t2_stack, T2_STACK_SIZE, entry_oops,
821 NULL, NULL, NULL,
822 K_PRIO_PREEMPT(2), 0, K_NO_WAIT);
823
824 /* hold cpu and wait for thread trigger exception and being terminated */
825 k_busy_wait(5 * DELAY_US);
826
827 /* Verify that child thread is no longer running. We can't simply use k_thread_join here
828 * as we don't want to introduce reschedule point here.
829 */
830 zassert_true(z_is_thread_state_set(&t2, _THREAD_DEAD));
831
832 /* Manually trigger the crash in mainthread */
833 entry_oops(NULL, NULL, NULL);
834
835 /* should not be here */
836 ztest_test_fail();
837 }
838
workq_handler(struct k_work * work)839 static void workq_handler(struct k_work *work)
840 {
841 child_thread_id = curr_cpu();
842 }
843
844 /**
845 * @brief Test system workq run on different core
846
847 * @details When macro CONFIG_SMP is enabled, workq can be run
848 * on different core.
849 *
850 * @ingroup kernel_common_tests
851 */
ZTEST(smp,test_workq_on_smp)852 ZTEST(smp, test_workq_on_smp)
853 {
854 static struct k_work work;
855
856 k_work_init(&work, workq_handler);
857
858 /* submit work item on system workq */
859 k_work_submit(&work);
860
861 /* Wait for some time to let other core's thread run */
862 k_busy_wait(DELAY_US);
863
864 /* check work have finished */
865 zassert_equal(k_work_busy_get(&work), 0);
866
867 main_thread_id = curr_cpu();
868
869 /* Verify the ztest thread and system workq run on different core */
870 zassert_true(main_thread_id != child_thread_id,
871 "system workq run on the same core");
872 }
873
t1_mutex_lock(void * p1,void * p2,void * p3)874 static void t1_mutex_lock(void *p1, void *p2, void *p3)
875 {
876 ARG_UNUSED(p2);
877 ARG_UNUSED(p3);
878
879 /* t1 will get mutex first */
880 k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
881
882 k_msleep(2);
883
884 k_mutex_unlock((struct k_mutex *)p1);
885 }
886
t2_mutex_lock(void * p1,void * p2,void * p3)887 static void t2_mutex_lock(void *p1, void *p2, void *p3)
888 {
889 ARG_UNUSED(p2);
890 ARG_UNUSED(p3);
891
892 zassert_equal(_current->base.global_lock_count, 0,
893 "thread global lock cnt %d is incorrect",
894 _current->base.global_lock_count);
895
896 k_mutex_lock((struct k_mutex *)p1, K_FOREVER);
897
898 zassert_equal(_current->base.global_lock_count, 0,
899 "thread global lock cnt %d is incorrect",
900 _current->base.global_lock_count);
901
902 k_mutex_unlock((struct k_mutex *)p1);
903
904 /**TESTPOINT: z_smp_release_global_lock() has been call during
905 * context switch but global_lock_cnt has not been decrease
906 * because no irq_lock() was called.
907 */
908 zassert_equal(_current->base.global_lock_count, 0,
909 "thread global lock cnt %d is incorrect",
910 _current->base.global_lock_count);
911 }
912
913 /**
914 * @brief Test scenario that a thread release the global lock
915 *
916 * @ingroup kernel_smp_tests
917 *
918 * @details Validate the scenario that make the internal APIs of SMP
919 * z_smp_release_global_lock() to be called.
920 */
ZTEST(smp,test_smp_release_global_lock)921 ZTEST(smp, test_smp_release_global_lock)
922 {
923 k_mutex_init(&smutex);
924
925 tinfo[0].tid =
926 k_thread_create(&tthread[0], tstack[0], STACK_SIZE,
927 t1_mutex_lock,
928 &smutex, NULL, NULL,
929 K_PRIO_PREEMPT(5),
930 K_INHERIT_PERMS, K_NO_WAIT);
931
932 tinfo[1].tid =
933 k_thread_create(&tthread[1], tstack[1], STACK_SIZE,
934 t2_mutex_lock,
935 &smutex, NULL, NULL,
936 K_PRIO_PREEMPT(3),
937 K_INHERIT_PERMS, K_MSEC(1));
938
939 /* Hold one of the cpu to ensure context switch as we wanted
940 * can happen in another cpu.
941 */
942 k_busy_wait(20000);
943
944 k_thread_join(tinfo[1].tid, K_FOREVER);
945 k_thread_join(tinfo[0].tid, K_FOREVER);
946 cleanup_resources();
947 }
948
949 #define LOOP_COUNT ((int)(20000 * RUN_FACTOR))
950
951 enum sync_t {
952 LOCK_IRQ,
953 LOCK_SEM,
954 LOCK_MUTEX
955 };
956
957 static int global_cnt;
958 static struct k_mutex smp_mutex;
959
960 static void (*sync_lock)(void *);
961 static void (*sync_unlock)(void *);
962
sync_lock_dummy(void * k)963 static void sync_lock_dummy(void *k)
964 {
965 /* no sync lock used */
966 }
967
sync_lock_irq(void * k)968 static void sync_lock_irq(void *k)
969 {
970 *((unsigned int *)k) = irq_lock();
971 }
972
sync_unlock_irq(void * k)973 static void sync_unlock_irq(void *k)
974 {
975 irq_unlock(*(unsigned int *)k);
976 }
977
sync_lock_sem(void * k)978 static void sync_lock_sem(void *k)
979 {
980 k_sem_take(&smp_sem, K_FOREVER);
981 }
982
sync_unlock_sem(void * k)983 static void sync_unlock_sem(void *k)
984 {
985 k_sem_give(&smp_sem);
986 }
987
sync_lock_mutex(void * k)988 static void sync_lock_mutex(void *k)
989 {
990 k_mutex_lock(&smp_mutex, K_FOREVER);
991 }
992
sync_unlock_mutex(void * k)993 static void sync_unlock_mutex(void *k)
994 {
995 k_mutex_unlock(&smp_mutex);
996 }
997
sync_init(int lock_type)998 static void sync_init(int lock_type)
999 {
1000 switch (lock_type) {
1001 case LOCK_IRQ:
1002 sync_lock = sync_lock_irq;
1003 sync_unlock = sync_unlock_irq;
1004 break;
1005 case LOCK_SEM:
1006 sync_lock = sync_lock_sem;
1007 sync_unlock = sync_unlock_sem;
1008 k_sem_init(&smp_sem, 1, 3);
1009 break;
1010 case LOCK_MUTEX:
1011 sync_lock = sync_lock_mutex;
1012 sync_unlock = sync_unlock_mutex;
1013 k_mutex_init(&smp_mutex);
1014 break;
1015
1016 default:
1017 sync_lock = sync_unlock = sync_lock_dummy;
1018 }
1019 }
1020
inc_global_cnt(void * a,void * b,void * c)1021 static void inc_global_cnt(void *a, void *b, void *c)
1022 {
1023 int key;
1024
1025 for (int i = 0; i < LOOP_COUNT; i++) {
1026
1027 sync_lock(&key);
1028
1029 global_cnt++;
1030 global_cnt--;
1031 global_cnt++;
1032
1033 sync_unlock(&key);
1034 }
1035 }
1036
run_concurrency(void * p1,void * p2,void * p3)1037 static int run_concurrency(void *p1, void *p2, void *p3)
1038 {
1039 ARG_UNUSED(p3);
1040
1041 int type = POINTER_TO_INT(p1);
1042 k_thread_entry_t func = p2;
1043 uint32_t start_t, end_t;
1044
1045 sync_init(type);
1046 global_cnt = 0;
1047 start_t = k_cycle_get_32();
1048
1049 tinfo[0].tid =
1050 k_thread_create(&tthread[0], tstack[0], STACK_SIZE,
1051 func,
1052 NULL, NULL, NULL,
1053 K_PRIO_PREEMPT(1),
1054 K_INHERIT_PERMS, K_NO_WAIT);
1055
1056 tinfo[1].tid =
1057 k_thread_create(&tthread[1], tstack[1], STACK_SIZE,
1058 func,
1059 NULL, NULL, NULL,
1060 K_PRIO_PREEMPT(1),
1061 K_INHERIT_PERMS, K_NO_WAIT);
1062
1063 k_tid_t tid =
1064 k_thread_create(&t2, t2_stack, T2_STACK_SIZE,
1065 func,
1066 NULL, NULL, NULL,
1067 K_PRIO_PREEMPT(1),
1068 K_INHERIT_PERMS, K_NO_WAIT);
1069
1070 k_thread_join(tinfo[0].tid, K_FOREVER);
1071 k_thread_join(tinfo[1].tid, K_FOREVER);
1072 k_thread_join(tid, K_FOREVER);
1073 cleanup_resources();
1074
1075 end_t = k_cycle_get_32();
1076
1077 printk("type %d: cnt %d, spend %u ms\n", type, global_cnt,
1078 k_cyc_to_ms_ceil32(end_t - start_t));
1079
1080 return global_cnt == (LOOP_COUNT * 3);
1081 }
1082
1083 /**
1084 * @brief Test if the concurrency of SMP works or not
1085 *
1086 * @ingroup kernel_smp_tests
1087 *
1088 * @details Validate the global lock and unlock API of SMP are thread-safe.
1089 * We make 3 thread to increase the global count in different cpu and
1090 * they both do locking then unlocking for LOOP_COUNT times. It shall be no
1091 * deadlock happened and total global count shall be 3 * LOOP COUNT.
1092 *
1093 * We show the 4 kinds of scenario:
1094 * - No any lock used
1095 * - Use global irq lock
1096 * - Use semaphore
1097 * - Use mutex
1098 */
ZTEST(smp,test_inc_concurrency)1099 ZTEST(smp, test_inc_concurrency)
1100 {
1101 /* increasing global var with irq lock */
1102 zassert_true(run_concurrency(INT_TO_POINTER(LOCK_IRQ), inc_global_cnt, NULL),
1103 "total count %d is wrong(i)", global_cnt);
1104
1105 /* increasing global var with irq lock */
1106 zassert_true(run_concurrency(INT_TO_POINTER(LOCK_SEM), inc_global_cnt, NULL),
1107 "total count %d is wrong(s)", global_cnt);
1108
1109 /* increasing global var with irq lock */
1110 zassert_true(run_concurrency(INT_TO_POINTER(LOCK_MUTEX), inc_global_cnt, NULL),
1111 "total count %d is wrong(M)", global_cnt);
1112 }
1113
1114 /** Keep track of how many signals raised. */
1115 static unsigned int t_signal_raised;
1116
1117 /** Keep track of how many signals received per thread. */
1118 static unsigned int t_signals_rcvd[MAX_NUM_THREADS];
1119
1120 /**
1121 * @brief Stress test for context switching code
1122 *
1123 * @ingroup kernel_smp_tests
1124 *
1125 * @details Leverage the polling API to stress test the context switching code.
1126 * This test will hammer all the CPUs with thread swapping requests.
1127 */
process_events(void * arg0,void * arg1,void * arg2)1128 static void process_events(void *arg0, void *arg1, void *arg2)
1129 {
1130 ARG_UNUSED(arg1);
1131 ARG_UNUSED(arg2);
1132
1133 uintptr_t id = (uintptr_t) arg0;
1134 unsigned int signaled;
1135 int result;
1136
1137 while (1) {
1138 /* Retry if no event(s) are ready.
1139 * For example, -EINTR where polling is interrupted.
1140 */
1141 if (k_poll(&tevent[id], 1, K_FOREVER) != 0) {
1142 continue;
1143 }
1144
1145 /* Grab the raised signal. */
1146 k_poll_signal_check(tevent[id].signal, &signaled, &result);
1147
1148 /* Check correct result. */
1149 if (result != 0x55) {
1150 ztest_test_fail();
1151 }
1152
1153 t_signals_rcvd[id]++;
1154
1155 /* Reset both event and signal. */
1156 tevent[id].state = K_POLL_STATE_NOT_READY;
1157 tevent[id].signal->result = 0;
1158 k_poll_signal_reset(tevent[id].signal);
1159 }
1160 }
1161
signal_raise(void * arg0,void * arg1,void * arg2)1162 static void signal_raise(void *arg0, void *arg1, void *arg2)
1163 {
1164 unsigned int num_threads = arch_num_cpus();
1165 unsigned int signaled;
1166 int result;
1167
1168 t_signal_raised = 0U;
1169
1170 while (1) {
1171 for (uintptr_t i = 0; i < num_threads; i++) {
1172 /* Only raise signal when it is okay to do so.
1173 * We don't want to raise a signal while the signal
1174 * and the associated event are still in the process
1175 * of being reset (see above).
1176 */
1177 k_poll_signal_check(tevent[i].signal, &signaled, &result);
1178
1179 if (signaled != 0U) {
1180 continue;
1181 }
1182
1183 t_signal_raised++;
1184 k_poll_signal_raise(&tsignal[i], 0x55);
1185 }
1186 }
1187 }
1188
ZTEST(smp_stress,test_smp_switch_stress)1189 ZTEST(smp_stress, test_smp_switch_stress)
1190 {
1191 unsigned int num_threads = arch_num_cpus();
1192
1193 if (CONFIG_SMP_TEST_RUN_FACTOR == 0) {
1194 /* If CONFIG_SMP_TEST_RUN_FACTOR is zero,
1195 * the switch stress test is effectively
1196 * not doing anything as the k_sleep()
1197 * below is not going to sleep at all,
1198 * and all created threads are being
1199 * terminated (almost) immediately after
1200 * creation. So if run factor is zero,
1201 * mark the test as skipped.
1202 */
1203 ztest_test_skip();
1204 }
1205
1206 for (uintptr_t i = 0; i < num_threads; i++) {
1207 t_signals_rcvd[i] = 0;
1208
1209 k_poll_signal_init(&tsignal[i]);
1210 k_poll_event_init(&tevent[i], K_POLL_TYPE_SIGNAL,
1211 K_POLL_MODE_NOTIFY_ONLY, &tsignal[i]);
1212
1213 k_thread_create(&tthread[i], tstack[i], STACK_SIZE,
1214 process_events,
1215 (void *) i, NULL, NULL, K_PRIO_PREEMPT(i + 1),
1216 K_INHERIT_PERMS, K_NO_WAIT);
1217 }
1218
1219 k_thread_create(&t2, t2_stack, T2_STACK_SIZE, signal_raise,
1220 NULL, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT);
1221
1222 k_sleep(K_MSEC(SLEEP_MS_LONG));
1223
1224 k_thread_abort(&t2);
1225 k_thread_join(&t2, K_FOREVER);
1226 for (uintptr_t i = 0; i < num_threads; i++) {
1227 k_thread_abort(&tthread[i]);
1228 k_thread_join(&tthread[i], K_FOREVER);
1229 }
1230
1231 TC_PRINT("Total signals raised %u\n", t_signal_raised);
1232
1233 for (unsigned int i = 0; i < num_threads; i++) {
1234 TC_PRINT("Thread #%d received %u signals\n", i, t_signals_rcvd[i]);
1235 }
1236
1237 /* Check if we at least have done some switching. */
1238 for (unsigned int i = 0; i < num_threads; i++) {
1239 zassert_not_equal(0, t_signals_rcvd[i],
1240 "Thread #%d has not received any signals", i);
1241 }
1242 }
1243
1244 /**
1245 * @brief Stress test for cpu affinity code
1246 *
1247 * @ingroup kernel_smp_tests
1248 *
1249 * @details Pin thread to a specific cpu. Once thread gets cpu, check
1250 * the cpu id is correct and then thread will give up cpu.
1251 */
1252 #ifdef CONFIG_SCHED_CPU_MASK
check_affinity(void * arg0,void * arg1,void * arg2)1253 static void check_affinity(void *arg0, void *arg1, void *arg2)
1254 {
1255 ARG_UNUSED(arg1);
1256 ARG_UNUSED(arg2);
1257
1258 int affinity = POINTER_TO_INT(arg0);
1259 int counter = 30;
1260
1261 while (counter != 0) {
1262 zassert_equal(affinity, curr_cpu(), "Affinity test failed.");
1263 counter--;
1264 k_yield();
1265 }
1266 }
1267
ZTEST(smp,test_smp_affinity)1268 ZTEST(smp, test_smp_affinity)
1269 {
1270 int num_threads = arch_num_cpus();
1271
1272 for (int i = 0; i < num_threads; ++i) {
1273 k_thread_create(&tthread[i], tstack[i],
1274 STACK_SIZE, check_affinity,
1275 INT_TO_POINTER(i), NULL, NULL,
1276 0, 0, K_FOREVER);
1277
1278 k_thread_cpu_pin(&tthread[i], i);
1279 k_thread_start(&tthread[i]);
1280 }
1281
1282 for (int i = 0; i < num_threads; i++) {
1283 k_thread_join(&tthread[i], K_FOREVER);
1284 }
1285 }
1286 #endif
1287
smp_tests_setup(void)1288 static void *smp_tests_setup(void)
1289 {
1290 /* Sleep a bit to guarantee that both CPUs enter an idle
1291 * thread from which they can exit correctly to run the main
1292 * test.
1293 */
1294 k_sleep(K_MSEC(10));
1295
1296 return NULL;
1297 }
1298
1299 ZTEST_SUITE(smp, NULL, smp_tests_setup, NULL, NULL, NULL);
1300 ZTEST_SUITE(smp_stress, NULL, smp_tests_setup, NULL, NULL, NULL);
1301