Loading...
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 123 124 125 | /* * Copyright (c) 2022 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/ztest.h> #include <zephyr/kernel.h> #include <zephyr/sys/arch_interface.h> #if defined(CONFIG_SMP) && CONFIG_MP_MAX_NUM_CPUS > 1 #define SMP_TEST #endif #ifdef SMP_TEST #define MAX_NUM_THREADS CONFIG_MP_MAX_NUM_CPUS #define STACK_SIZE 1024 #define PRIORITY 7 static struct k_thread threads[MAX_NUM_THREADS]; static K_THREAD_STACK_ARRAY_DEFINE(tstack, MAX_NUM_THREADS, STACK_SIZE); #endif #define WAIT_US 1000 #define WAIT_NS (WAIT_US * 1000) #define TOLERANCE 0.1 static void perform_tests(void) { timing_t start, middle, end; uint64_t diff1, diff2, diff_all, freq_hz; uint64_t diff1_ns, diff2_ns, diff_all_ns, diff_avg_ns; uint32_t freq_mhz; arch_timing_start(); start = arch_timing_counter_get(); k_busy_wait(WAIT_US); middle = arch_timing_counter_get(); k_busy_wait(WAIT_US); end = arch_timing_counter_get(); /* Time shouldn't stop or go backwards */ diff1 = arch_timing_cycles_get(&start, &middle); diff2 = arch_timing_cycles_get(&middle, &end); diff_all = arch_timing_cycles_get(&start, &end); zassert_true(diff1 > 0, NULL); zassert_true(diff2 > 0, NULL); zassert_true(diff_all > 0, NULL); /* Differences shouldn't be so different, as both are spaced by * k_busy_wait(WAIT_US). */ zassert_within(diff1, diff2, diff1 * TOLERANCE, NULL); zassert_within(diff_all, diff1 + diff2, (diff1 + diff2) * TOLERANCE, NULL); freq_hz = arch_timing_freq_get(); freq_mhz = arch_timing_freq_get_mhz(); zassert_equal(freq_mhz, (uint32_t)(freq_hz / 1000000ULL), NULL); diff1_ns = arch_timing_cycles_to_ns(diff1); diff2_ns = arch_timing_cycles_to_ns(diff2); diff_all_ns = arch_timing_cycles_to_ns(diff_all); /* Ensure the differences are close to 100us */ zassert_within(diff1_ns, WAIT_NS, WAIT_NS * TOLERANCE, NULL); zassert_within(diff2_ns, WAIT_NS, WAIT_NS * TOLERANCE, NULL); zassert_within(diff_all_ns, 2 * WAIT_NS, 2 * WAIT_NS * TOLERANCE, NULL); diff_avg_ns = arch_timing_cycles_to_ns_avg(diff1 + diff2, 2); zassert_within(diff_avg_ns, WAIT_NS, WAIT_NS * TOLERANCE, NULL); arch_timing_stop(); } void *timing_setup(void) { arch_timing_init(); return NULL; } ZTEST(arch_timing, test_arch_timing) { perform_tests(); /* Run tests again to ensure nothing breaks after arch_timing_stop */ perform_tests(); } #ifdef SMP_TEST static void thread_entry(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); perform_tests(); /* Run tests again to ensure nothing breaks after arch_timing_stop */ perform_tests(); } ZTEST(arch_timing, test_arch_timing_smp) { int i; unsigned int num_threads = arch_num_cpus(); for (i = 0; i < num_threads; i++) { k_thread_create(&threads[i], tstack[i], STACK_SIZE, thread_entry, NULL, NULL, NULL, PRIORITY, 0, K_FOREVER); k_thread_cpu_mask_enable(&threads[i], i); k_thread_start(&threads[i]); } for (i = 0; i < num_threads; i++) k_thread_join(&threads[i], K_FOREVER); } #else ZTEST(arch_timing, test_arch_timing_smp) { ztest_test_skip(); } #endif ZTEST_SUITE(arch_timing, NULL, timing_setup, NULL, NULL, NULL); |