LCOV - code coverage report
Current view: top level - app/test - test_timer_racecond.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 2 49 4.1 %
Date: 2025-03-01 20:23:48 Functions: 2 6 33.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 26 3.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2015 Akamai Technologies.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "test.h"
       7                 :            : 
       8                 :            : #include <stdio.h>
       9                 :            : #include <unistd.h>
      10                 :            : #include <inttypes.h>
      11                 :            : #include <rte_cycles.h>
      12                 :            : #include <rte_timer.h>
      13                 :            : #include <rte_common.h>
      14                 :            : #include <rte_lcore.h>
      15                 :            : #include <rte_random.h>
      16                 :            : #include <rte_malloc.h>
      17                 :            : #include <rte_pause.h>
      18                 :            : 
      19                 :            : #ifdef RTE_EXEC_ENV_LINUX
      20                 :            : #define usec_delay(us) usleep(us)
      21                 :            : #else
      22                 :            : #define usec_delay(us) rte_delay_us(us)
      23                 :            : #endif
      24                 :            : 
      25                 :            : #define BILLION (1UL << 30)
      26                 :            : 
      27                 :            : #define TEST_DURATION_S 4 /* in seconds */
      28                 :            : #define N_TIMERS    50
      29                 :            : 
      30                 :            : static struct rte_timer timer[N_TIMERS];
      31                 :            : static unsigned int timer_lcore_id[N_TIMERS];
      32                 :            : 
      33                 :            : static unsigned int main_lcore;
      34                 :            : static volatile unsigned int stop_workers;
      35                 :            : 
      36                 :            : static int reload_timer(struct rte_timer *tim);
      37                 :            : 
      38         [ -  + ]:        252 : RTE_LOG_REGISTER(timer_logtype_test, test.timer, INFO);
      39                 :            : 
      40                 :            : static void
      41                 :          0 : timer_cb(struct rte_timer *tim, void *arg __rte_unused)
      42                 :            : {
      43                 :            :         /* Simulate slow callback function, 100 us. */
      44                 :          0 :         rte_delay_us(100);
      45         [ #  # ]:          0 :         if (tim == &timer[0])
      46                 :          0 :                 rte_log(RTE_LOG_DEBUG, timer_logtype_test,
      47                 :            :                         "------------------------------------------------\n");
      48                 :          0 :         rte_log(RTE_LOG_DEBUG, timer_logtype_test, "%s: core %u timer %"
      49                 :          0 :                 PRIuPTR "\n", __func__, rte_lcore_id(), tim - timer);
      50                 :          0 :         (void)reload_timer(tim);
      51                 :          0 : }
      52                 :            : 
      53                 :            : RTE_DEFINE_PER_LCORE(unsigned, n_reset_collisions);
      54                 :            : 
      55                 :            : static int
      56                 :          0 : reload_timer(struct rte_timer *tim)
      57                 :            : {
      58                 :            :         /* Make timer expire roughly when the TSC hits the next BILLION
      59                 :            :          * multiple. Add in timer's index to make them expire in nearly
      60                 :            :          * sorted order. This makes all timers somewhat synchronized,
      61                 :            :          * firing ~2-3 times per second, assuming 2-3 GHz TSCs.
      62                 :            :          */
      63                 :          0 :         uint64_t ticks = BILLION - (rte_get_timer_cycles() % BILLION) +
      64                 :          0 :             (tim - timer);
      65                 :            :         int ret;
      66                 :            : 
      67                 :          0 :         ret = rte_timer_reset(tim, ticks, PERIODICAL, main_lcore, timer_cb, NULL);
      68         [ #  # ]:          0 :         if (ret != 0) {
      69                 :          0 :                 rte_log(RTE_LOG_DEBUG, timer_logtype_test,
      70                 :            :                         "- core %u failed to reset timer %" PRIuPTR " (OK)\n",
      71                 :            :                         rte_lcore_id(), tim - timer);
      72                 :          0 :                 RTE_PER_LCORE(n_reset_collisions) += 1;
      73                 :            :         }
      74                 :          0 :         return ret;
      75                 :            : }
      76                 :            : 
      77                 :            : static int
      78                 :          0 : worker_main_loop(__rte_unused void *arg)
      79                 :            : {
      80                 :            :         unsigned lcore_id = rte_lcore_id();
      81                 :            :         unsigned i;
      82                 :            : 
      83                 :          0 :         RTE_PER_LCORE(n_reset_collisions) = 0;
      84                 :            : 
      85                 :            :         printf("Starting main loop on core %u\n", lcore_id);
      86                 :            : 
      87         [ #  # ]:          0 :         while (!stop_workers) {
      88                 :            :                 /* Wait until the timer manager is running.
      89                 :            :                  * We know it's running when we see timer[0] NOT pending.
      90                 :            :                  */
      91         [ #  # ]:          0 :                 if (rte_timer_pending(&timer[0])) {
      92                 :            :                         rte_pause();
      93                 :          0 :                         continue;
      94                 :            :                 }
      95                 :            : 
      96                 :            :                 /* Now, go cause some havoc!
      97                 :            :                  * Reload our timers.
      98                 :            :                  */
      99         [ #  # ]:          0 :                 for (i = 0; i < N_TIMERS; i++) {
     100         [ #  # ]:          0 :                         if (timer_lcore_id[i] == lcore_id)
     101                 :          0 :                                 (void)reload_timer(&timer[i]);
     102                 :            :                 }
     103                 :          0 :                 usec_delay(100*1000); /* sleep 100 ms */
     104                 :            :         }
     105                 :            : 
     106         [ #  # ]:          0 :         if (RTE_PER_LCORE(n_reset_collisions) != 0) {
     107                 :            :                 printf("- core %u, %u reset collisions (OK)\n",
     108                 :            :                         lcore_id, RTE_PER_LCORE(n_reset_collisions));
     109                 :            :         }
     110                 :          0 :         return 0;
     111                 :            : }
     112                 :            : 
     113                 :            : static int
     114                 :          0 : test_timer_racecond(void)
     115                 :            : {
     116                 :            :         int ret;
     117                 :            :         uint64_t hz;
     118                 :            :         uint64_t cur_time;
     119                 :            :         uint64_t end_time;
     120                 :            :         int64_t diff = 0;
     121                 :            :         unsigned lcore_id;
     122                 :            :         unsigned i;
     123                 :            : 
     124                 :          0 :         main_lcore = lcore_id = rte_lcore_id();
     125                 :            :         hz = rte_get_timer_hz();
     126                 :            : 
     127                 :            :         /* init and start timers */
     128         [ #  # ]:          0 :         for (i = 0; i < N_TIMERS; i++) {
     129                 :          0 :                 rte_timer_init(&timer[i]);
     130                 :          0 :                 ret = reload_timer(&timer[i]);
     131         [ #  # ]:          0 :                 TEST_ASSERT(ret == 0, "reload_timer failed");
     132                 :            : 
     133                 :            :                 /* Distribute timers to workers.
     134                 :            :                  * Note that we assign timer[0] to the main.
     135                 :            :                  */
     136                 :          0 :                 timer_lcore_id[i] = lcore_id;
     137                 :          0 :                 lcore_id = rte_get_next_lcore(lcore_id, 1, 1);
     138                 :            :         }
     139                 :            : 
     140                 :            :         /* calculate the "end of test" time */
     141                 :            :         cur_time = rte_get_timer_cycles();
     142                 :          0 :         end_time = cur_time + (hz * TEST_DURATION_S);
     143                 :            : 
     144                 :            :         /* start worker cores */
     145                 :          0 :         stop_workers = 0;
     146                 :            :         printf("Start timer manage race condition test (%u seconds)\n",
     147                 :            :                         TEST_DURATION_S);
     148                 :          0 :         rte_eal_mp_remote_launch(worker_main_loop, NULL, SKIP_MAIN);
     149                 :            : 
     150         [ #  # ]:          0 :         while (diff >= 0) {
     151                 :            :                 /* run the timers */
     152                 :          0 :                 rte_timer_manage();
     153                 :            : 
     154                 :            :                 /* wait 100 ms */
     155                 :          0 :                 usec_delay(100*1000);
     156                 :            : 
     157                 :            :                 cur_time = rte_get_timer_cycles();
     158                 :          0 :                 diff = end_time - cur_time;
     159                 :            :         }
     160                 :            : 
     161                 :            :         /* stop worker cores */
     162                 :            :         printf("Stopping timer manage race condition test\n");
     163                 :          0 :         stop_workers = 1;
     164                 :          0 :         rte_eal_mp_wait_lcore();
     165                 :            : 
     166                 :            :         /* stop timers */
     167         [ #  # ]:          0 :         for (i = 0; i < N_TIMERS; i++) {
     168                 :          0 :                 ret = rte_timer_stop(&timer[i]);
     169         [ #  # ]:          0 :                 TEST_ASSERT(ret == 0, "rte_timer_stop failed");
     170                 :            :         }
     171                 :            : 
     172                 :            :         return TEST_SUCCESS;
     173                 :            : }
     174                 :            : 
     175                 :        252 : REGISTER_PERF_TEST(timer_racecond_autotest, test_timer_racecond);

Generated by: LCOV version 1.14