LCOV - code coverage report
Current view: top level - app/test - test_timer_secondary.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 6 66 9.1 %
Date: 2026-04-01 20:02:27 Functions: 2 5 40.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 40 5.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2019 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdio.h>
       6                 :            : #include <string.h>
       7                 :            : 
       8                 :            : #include <rte_eal.h>
       9                 :            : #include <rte_lcore.h>
      10                 :            : #include <rte_debug.h>
      11                 :            : #include <rte_memzone.h>
      12                 :            : #include <rte_timer.h>
      13                 :            : #include <rte_cycles.h>
      14                 :            : #include <rte_mempool.h>
      15                 :            : #include <rte_pause.h>
      16                 :            : #include <rte_random.h>
      17                 :            : #include <rte_stdatomic.h>
      18                 :            : 
      19                 :            : #include "test.h"
      20                 :            : 
      21                 :            : #ifdef RTE_EXEC_ENV_WINDOWS
      22                 :            : int
      23                 :            : test_timer_secondary(void)
      24                 :            : {
      25                 :            :         printf("timer_secondary not supported on Windows, skipping test\n");
      26                 :            :         return TEST_SKIPPED;
      27                 :            : }
      28                 :            : #else
      29                 :            : 
      30                 :            : #include "process.h"
      31                 :            : 
      32                 :            : #define NUM_TIMERS_MAX          (1 << 20) /* ~1M timers */
      33                 :            : #define NUM_TIMERS_MIN          (1 << 14) /* 16K minimum */
      34                 :            : #define NUM_LCORES_NEEDED       3
      35                 :            : #define TEST_INFO_MZ_NAME       "test_timer_info_mz"
      36                 :            : #define MSECPERSEC              1E3
      37                 :            : 
      38                 :            : #define launch_proc(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__)
      39                 :            : 
      40                 :            : struct test_info {
      41                 :            :         unsigned int main_lcore;
      42                 :            :         unsigned int mgr_lcore;
      43                 :            :         unsigned int sec_lcore;
      44                 :            :         unsigned int num_timers;
      45                 :            :         uint32_t timer_data_id;
      46                 :            :         RTE_ATOMIC(unsigned int) expected_count;
      47                 :            :         RTE_ATOMIC(unsigned int) expired_count;
      48                 :            :         struct rte_mempool *tim_mempool;
      49                 :            :         struct rte_timer *expired_timers[NUM_TIMERS_MAX];
      50                 :            :         int expired_timers_idx;
      51                 :            :         RTE_ATOMIC(int) exit_flag;
      52                 :            : };
      53                 :            : 
      54                 :            : static int
      55                 :          0 : timer_secondary_spawn_wait(unsigned int lcore)
      56                 :            : {
      57                 :            :         char core_str[10];
      58                 :            :         const char *prefix;
      59                 :            : 
      60                 :          0 :         prefix = file_prefix_arg();
      61         [ #  # ]:          0 :         if (prefix == NULL)
      62                 :            :                 return -1;
      63                 :            : 
      64                 :          0 :         char const *argv[] = {
      65                 :            :                 prgname,
      66                 :            :                 "-l", core_str,
      67                 :            :                 "--proc-type=secondary",
      68                 :            :                 prefix
      69                 :            :         };
      70                 :            : 
      71                 :            :         snprintf(core_str, sizeof(core_str), "%u", lcore);
      72                 :            : 
      73                 :          0 :         return launch_proc(argv);
      74                 :            : }
      75                 :            : 
      76                 :            : static void
      77                 :          0 : handle_expired_timer(struct rte_timer *tim)
      78                 :            : {
      79                 :          0 :         struct test_info *test_info = tim->arg;
      80                 :            : 
      81                 :          0 :         rte_atomic_fetch_add_explicit(&test_info->expired_count, 1,
      82                 :            :                                       rte_memory_order_relaxed);
      83                 :          0 :         test_info->expired_timers[test_info->expired_timers_idx++] = tim;
      84                 :          0 : }
      85                 :            : 
      86                 :            : static int
      87                 :          0 : timer_manage_loop(void *arg)
      88                 :            : {
      89                 :            : #define TICK_MSECS 1
      90                 :          0 :         uint64_t tick_cycles = TICK_MSECS * rte_get_timer_hz() / MSECPERSEC;
      91                 :            :         uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
      92                 :            :         struct test_info *test_info = arg;
      93                 :            : 
      94         [ #  # ]:          0 :         while (!rte_atomic_load_explicit(&test_info->exit_flag,
      95                 :            :                                        rte_memory_order_acquire)) {
      96                 :            :                 cur_tsc = rte_rdtsc();
      97                 :          0 :                 diff_tsc = cur_tsc - prev_tsc;
      98                 :            : 
      99         [ #  # ]:          0 :                 if (diff_tsc > tick_cycles) {
     100                 :            :                         /* Scan timer list for expired timers */
     101                 :          0 :                         rte_timer_alt_manage(test_info->timer_data_id,
     102                 :            :                                              NULL,
     103                 :            :                                              0,
     104                 :            :                                              handle_expired_timer);
     105                 :            : 
     106                 :            :                         /* Return expired timer objects back to mempool */
     107                 :          0 :                         rte_mempool_put_bulk(test_info->tim_mempool,
     108                 :          0 :                                              (void **)test_info->expired_timers,
     109         [ #  # ]:          0 :                                              test_info->expired_timers_idx);
     110                 :            : 
     111                 :          0 :                         test_info->expired_timers_idx = 0;
     112                 :            : 
     113                 :            :                         prev_tsc = cur_tsc;
     114                 :            :                 }
     115                 :            : 
     116                 :            :                 rte_pause();
     117                 :            :         }
     118                 :            : 
     119                 :          0 :         return 0;
     120                 :            : }
     121                 :            : 
     122                 :            : int
     123                 :          1 : test_timer_secondary(void)
     124                 :            : {
     125                 :          1 :         int proc_type = rte_eal_process_type();
     126                 :            :         const struct rte_memzone *mz;
     127                 :            :         struct test_info *test_info;
     128                 :            :         int ret;
     129                 :            : 
     130         [ +  - ]:          1 :         if (proc_type == RTE_PROC_PRIMARY) {
     131         [ +  - ]:          1 :                 if (rte_lcore_count() < NUM_LCORES_NEEDED) {
     132                 :            :                         printf("Not enough cores for test_timer_secondary, expecting at least %u\n",
     133                 :            :                                NUM_LCORES_NEEDED);
     134                 :          1 :                         return TEST_SKIPPED;
     135                 :            :                 }
     136                 :            : 
     137                 :          0 :                 mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info),
     138                 :            :                                          SOCKET_ID_ANY, 0);
     139         [ #  # ]:          0 :                 TEST_ASSERT_NOT_NULL(mz, "Couldn't allocate memory for "
     140                 :            :                                      "test data");
     141                 :          0 :                 test_info = mz->addr;
     142                 :            : 
     143                 :          0 :                 test_info->num_timers = test_scale_iterations(NUM_TIMERS_MAX, NUM_TIMERS_MIN);
     144                 :            : 
     145                 :          0 :                 test_info->tim_mempool = rte_mempool_create("test_timer_mp",
     146                 :            :                                 test_info->num_timers, sizeof(struct rte_timer), 0, 0,
     147                 :          0 :                                 NULL, NULL, NULL, NULL, rte_socket_id(), 0);
     148                 :            : 
     149                 :          0 :                 ret = rte_timer_data_alloc(&test_info->timer_data_id);
     150         [ #  # ]:          0 :                 TEST_ASSERT_SUCCESS(ret, "Failed to allocate timer data "
     151                 :            :                                     "instance");
     152                 :            : 
     153                 :            :                 unsigned int *main_lcorep = &test_info->main_lcore;
     154                 :            :                 unsigned int *mgr_lcorep = &test_info->mgr_lcore;
     155                 :            :                 unsigned int *sec_lcorep = &test_info->sec_lcore;
     156                 :            : 
     157                 :          0 :                 *main_lcorep = rte_get_main_lcore();
     158                 :          0 :                 *mgr_lcorep = rte_get_next_lcore(*main_lcorep, 1, 1);
     159                 :          0 :                 *sec_lcorep = rte_get_next_lcore(*mgr_lcorep, 1, 1);
     160                 :            : 
     161                 :          0 :                 ret = rte_eal_remote_launch(timer_manage_loop,
     162                 :            :                                             (void *)test_info,
     163                 :            :                                             *mgr_lcorep);
     164         [ #  # ]:          0 :                 TEST_ASSERT_SUCCESS(ret, "Failed to launch timer manage loop");
     165                 :            : 
     166                 :          0 :                 ret = timer_secondary_spawn_wait(*sec_lcorep);
     167                 :            :                 /* must set exit flag even on error case, so check ret later */
     168                 :            : 
     169                 :            :                 rte_delay_ms(500);
     170                 :          0 :                 rte_atomic_store_explicit(&test_info->exit_flag, 1,
     171                 :            :                                           rte_memory_order_release);
     172                 :            : 
     173         [ #  # ]:          0 :                 TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed");
     174                 :          0 :                 rte_eal_wait_lcore(*mgr_lcorep);
     175                 :            : 
     176                 :            : #ifdef RTE_LIBRTE_TIMER_DEBUG
     177                 :            :                 rte_timer_alt_dump_stats(test_info->timer_data_id, stdout);
     178                 :            : #endif
     179                 :            : 
     180                 :          0 :                 return rte_atomic_load_explicit(&test_info->expected_count,
     181                 :            :                                                rte_memory_order_relaxed) ==
     182                 :          0 :                        rte_atomic_load_explicit(&test_info->expired_count,
     183                 :            :                                                rte_memory_order_relaxed) ?
     184         [ #  # ]:          0 :                         TEST_SUCCESS : TEST_FAILED;
     185                 :            : 
     186         [ #  # ]:          0 :         } else if (proc_type == RTE_PROC_SECONDARY) {
     187                 :            :                 uint64_t ticks, timeout_ms;
     188                 :            :                 struct rte_timer *tim;
     189                 :            :                 unsigned int i;
     190                 :            : 
     191                 :          0 :                 mz = rte_memzone_lookup(TEST_INFO_MZ_NAME);
     192         [ #  # ]:          0 :                 TEST_ASSERT_NOT_NULL(mz, "Couldn't lookup memzone for "
     193                 :            :                                      "test info");
     194                 :          0 :                 test_info = mz->addr;
     195                 :            : 
     196         [ #  # ]:          0 :                 for (i = 0; i < test_info->num_timers; i++) {
     197         [ #  # ]:          0 :                         ret = rte_mempool_get(test_info->tim_mempool, (void **)&tim);
     198         [ #  # ]:          0 :                         TEST_ASSERT_SUCCESS(ret, "Couldn't get timer from mempool");
     199                 :            : 
     200                 :          0 :                         rte_timer_init(tim);
     201                 :            : 
     202                 :            :                         /* generate timeouts between 10 and 80 ms */
     203                 :          0 :                         timeout_ms = ((rte_rand() & 0x7) + 1) * 10;
     204                 :          0 :                         ticks = timeout_ms * rte_get_timer_hz() / MSECPERSEC;
     205                 :            : 
     206                 :          0 :                         ret = rte_timer_alt_reset(test_info->timer_data_id,
     207                 :            :                                                   tim, ticks, SINGLE,
     208                 :            :                                                   test_info->mgr_lcore, NULL,
     209                 :            :                                                   test_info);
     210         [ #  # ]:          0 :                         if (ret < 0)
     211                 :            :                                 return TEST_FAILED;
     212                 :            : 
     213                 :          0 :                         rte_atomic_fetch_add_explicit(&test_info->expected_count,
     214                 :            :                                                      1, rte_memory_order_relaxed);
     215                 :            : 
     216                 :            :                         /* randomly leave timer running or stop it */
     217         [ #  # ]:          0 :                         if (rte_rand() & 1)
     218                 :          0 :                                 continue;
     219                 :            : 
     220                 :          0 :                         ret = rte_timer_alt_stop(test_info->timer_data_id,
     221                 :            :                                                  tim);
     222         [ #  # ]:          0 :                         if (ret == 0) {
     223                 :          0 :                                 rte_atomic_fetch_sub_explicit(&test_info->expected_count,
     224                 :            :                                                              1, rte_memory_order_relaxed);
     225         [ #  # ]:          0 :                                 rte_mempool_put(test_info->tim_mempool,
     226                 :            :                                                 (void *)tim);
     227                 :            :                         }
     228                 :            : 
     229                 :            :                 }
     230                 :            : 
     231                 :            :                 return TEST_SUCCESS;
     232                 :            :         }
     233                 :            : 
     234                 :            :         return TEST_FAILED;
     235                 :            : }
     236                 :            : 
     237                 :            : #endif /* !RTE_EXEC_ENV_WINDOWS */
     238                 :            : 
     239                 :        276 : REGISTER_FAST_TEST(timer_secondary_autotest, NOHUGE_SKIP, ASAN_SKIP, test_timer_secondary);

Generated by: LCOV version 1.14