LCOV - code coverage report
Current view: top level - spdk/test/env/mem_callbacks - mem_callbacks.c (source / functions) Hit Total Coverage
Test: Combined Lines: 78 85 91.8 %
Date: 2024-07-16 01:31:00 Functions: 5 5 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 37 66 56.1 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2018 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "spdk/util.h"
       9                 :            : #include "spdk/queue.h"
      10                 :            : #include "spdk_internal/cunit.h"
      11                 :            : 
      12                 :            : #include <rte_config.h>
      13                 :            : #include <rte_version.h>
      14                 :            : #include <rte_malloc.h>
      15                 :            : #include <rte_eal_memconfig.h>
      16                 :            : #include <rte_eal.h>
      17                 :            : 
      18                 :            : struct mem_allocation {
      19                 :            :         uintptr_t                       vaddr;
      20                 :            :         size_t                          len;
      21                 :            :         TAILQ_ENTRY(mem_allocation)     link;
      22                 :            : };
      23                 :            : 
      24                 :            : static TAILQ_HEAD(, mem_allocation) g_mem_allocations = TAILQ_HEAD_INITIALIZER(g_mem_allocations);
      25                 :            : 
      26                 :            : static void
      27                 :        114 : memory_hotplug_cb(enum rte_mem_event event_type, const void *addr, size_t len, void *arg)
      28                 :            : {
      29                 :            :         struct mem_allocation *allocation;
      30                 :            : 
      31         [ +  + ]:        114 :         if (event_type == RTE_MEM_EVENT_ALLOC) {
      32                 :         57 :                 allocation = calloc(1, sizeof(*allocation));
      33         [ -  + ]:         57 :                 SPDK_CU_ASSERT_FATAL(allocation != NULL);
      34                 :            : 
      35         [ -  + ]:         57 :                 printf("register %p %ju\n", addr, len);
      36                 :         57 :                 allocation->vaddr = (uintptr_t)addr;
      37                 :         57 :                 allocation->len = len;
      38                 :         57 :                 TAILQ_INSERT_TAIL(&g_mem_allocations, allocation, link);
      39         [ +  - ]:         57 :         } else if (event_type == RTE_MEM_EVENT_FREE) {
      40         [ +  - ]:        117 :                 TAILQ_FOREACH(allocation, &g_mem_allocations, link) {
      41   [ +  +  +  - ]:        117 :                         if (allocation->vaddr == (uintptr_t)addr && allocation->len == len) {
      42                 :         57 :                                 break;
      43                 :            :                         }
      44                 :            :                 }
      45   [ -  +  -  + ]:         57 :                 printf("unregister %p %ju %s\n", addr, len, allocation == NULL ? "FAILED" : "PASSED");
      46         [ -  + ]:         57 :                 SPDK_CU_ASSERT_FATAL(allocation != NULL);
      47         [ +  + ]:         57 :                 TAILQ_REMOVE(&g_mem_allocations, allocation, link);
      48                 :         57 :                 free(allocation);
      49                 :            :         }
      50                 :        114 : }
      51                 :            : 
      52                 :            : static int
      53                 :         20 : memory_iter_cb(const struct rte_memseg_list *msl,
      54                 :            :                const struct rte_memseg *ms, size_t len, void *arg)
      55                 :            : {
      56                 :            :         struct mem_allocation *allocation;
      57                 :            : 
      58                 :         20 :         allocation = calloc(1, sizeof(*allocation));
      59         [ -  + ]:         20 :         SPDK_CU_ASSERT_FATAL(allocation != NULL);
      60                 :            : 
      61         [ -  + ]:         20 :         printf("register %p %ju\n", ms->addr, len);
      62                 :         20 :         allocation->vaddr = (uintptr_t)ms->addr;
      63                 :         20 :         allocation->len = len;
      64                 :         20 :         TAILQ_INSERT_TAIL(&g_mem_allocations, allocation, link);
      65                 :            : 
      66                 :         20 :         return 0;
      67                 :            : }
      68                 :            : 
      69                 :            : static void
      70                 :         76 : verify_buffer(void *_buf, size_t len)
      71                 :            : {
      72                 :         76 :         uintptr_t buf = (uintptr_t)_buf;
      73                 :            :         struct mem_allocation *allocation;
      74                 :            : 
      75         [ -  + ]:         76 :         SPDK_CU_ASSERT_FATAL(_buf != NULL);
      76         [ -  + ]:         76 :         printf("buf %p len %ju ", _buf, len);
      77         [ +  - ]:        175 :         TAILQ_FOREACH(allocation, &g_mem_allocations, link) {
      78         [ +  + ]:        175 :                 if (buf >= allocation->vaddr &&
      79         [ +  + ]:        171 :                     buf + len <= allocation->vaddr + allocation->len) {
      80                 :         76 :                         break;
      81                 :            :                 }
      82                 :            :         }
      83   [ -  +  -  + ]:         76 :         printf("%s\n", allocation == NULL ? "FAILED" : "PASSED");
      84                 :         76 :         CU_ASSERT(allocation != NULL);
      85                 :         76 : }
      86                 :            : 
      87                 :            : static void
      88                 :         19 : test(void)
      89                 :            : {
      90                 :            :         void *buf1, *buf2, *buf3, *buf4;
      91                 :            :         size_t len1, len2, len3, len4;
      92                 :            : 
      93                 :         19 :         printf("\n");
      94                 :            : 
      95                 :         19 :         rte_mem_event_callback_register("test", memory_hotplug_cb, NULL);
      96                 :         19 :         rte_memseg_contig_walk(memory_iter_cb, NULL);
      97                 :            : 
      98                 :            :         /* First allocate a 3MB buffer.  This will allocate a 4MB hugepage
      99                 :            :          *  region, with the 3MB buffer allocated from the end of it.
     100                 :            :          */
     101                 :         19 :         len1 = 3 * 1024 * 1024;
     102         [ -  + ]:         19 :         printf("malloc %ju\n", len1);
     103                 :         19 :         buf1 = rte_malloc(NULL, len1, 0);
     104                 :         19 :         verify_buffer(buf1, len1);
     105                 :            : 
     106                 :            :         /* Now allocate a very small buffer.  This will get allocated from
     107                 :            :          *  the previous 4MB hugepage allocation, just before the 3MB buffer
     108                 :            :          *  allocated just above.
     109                 :            :          */
     110                 :         19 :         len2 = 64;
     111         [ -  + ]:         19 :         printf("malloc %ju\n", len2);
     112                 :         19 :         buf2 = rte_malloc(NULL, len2, 0);
     113                 :         19 :         verify_buffer(buf2, len2);
     114                 :            : 
     115                 :            :         /* Allocate a 4MB buffer.  This should trigger a new hugepage allocation
     116                 :            :          * just for this 4MB buffer.
     117                 :            :          */
     118                 :         19 :         len3 = 4 * 1024 * 1024;
     119         [ -  + ]:         19 :         printf("malloc %ju\n", len3);
     120                 :         19 :         buf3 = rte_malloc(NULL, len3, 0);
     121                 :         19 :         verify_buffer(buf3, len3);
     122                 :            : 
     123                 :            :         /* Free the three buffers.  Specifically free buf1 first.  buf2 was
     124                 :            :          * allocated from the same huge page allocation as buf1 - so we want
     125                 :            :          * to make sure that DPDK doesn't try to free part of the first huge
     126                 :            :          * page allocation - it needs to wait until buf2 is also freed so it
     127                 :            :          * can free all of it.
     128                 :            :          */
     129         [ -  + ]:         19 :         printf("free %p %ju\n", buf1, len1);
     130                 :         19 :         rte_free(buf1);
     131         [ -  + ]:         19 :         printf("free %p %ju\n", buf2, len2);
     132                 :         19 :         rte_free(buf2);
     133         [ -  + ]:         19 :         printf("free %p %ju\n", buf3, len3);
     134                 :         19 :         rte_free(buf3);
     135                 :            : 
     136                 :            :         /* Do a single 8MB hugepage allocation and then free it.  This covers
     137                 :            :          * the more simple case.
     138                 :            :          */
     139                 :         19 :         len4 = 8 * 1024 * 1024;
     140         [ -  + ]:         19 :         printf("malloc %ju\n", len4);
     141                 :         19 :         buf4 = rte_malloc(NULL, len4, 0);
     142                 :         19 :         verify_buffer(buf4, len4);
     143                 :            : 
     144         [ -  + ]:         19 :         printf("free %p %ju\n", buf4, len4);
     145                 :         19 :         rte_free(buf4);
     146                 :         19 : }
     147                 :            : 
     148                 :            : int
     149                 :         19 : main(int argc, char **argv)
     150                 :            : {
     151                 :         19 :         CU_pSuite               suite = NULL;
     152                 :            :         unsigned int            num_failures;
     153                 :         19 :         char                    *dpdk_arg[] = {
     154                 :            :                 "mem_callbacks", "-c 0x1",
     155                 :            :                 "--base-virtaddr=0x200000000000",
     156                 :            :                 "--match-allocations",
     157                 :            :         };
     158                 :            :         int                     rc;
     159                 :            : 
     160                 :         19 :         rc = rte_eal_init(SPDK_COUNTOF(dpdk_arg), dpdk_arg);
     161         [ -  + ]:         19 :         if (rc < 0) {
     162         [ #  # ]:          0 :                 printf("Err: Unable to initialize DPDK\n");
     163                 :          0 :                 return 1;
     164                 :            :         }
     165                 :            : 
     166         [ -  + ]:         19 :         if (CU_initialize_registry() != CUE_SUCCESS) {
     167                 :          0 :                 return CU_get_error();
     168                 :            :         }
     169                 :            : 
     170                 :         19 :         suite = CU_add_suite("memory", NULL, NULL);
     171         [ -  + ]:         19 :         if (suite == NULL) {
     172                 :          0 :                 CU_cleanup_registry();
     173                 :          0 :                 return CU_get_error();
     174                 :            :         }
     175                 :            : 
     176         [ -  + ]:         19 :         if (
     177                 :         19 :                 CU_add_test(suite, "test", test) == NULL
     178                 :            :         ) {
     179                 :          0 :                 CU_cleanup_registry();
     180                 :          0 :                 return CU_get_error();
     181                 :            :         }
     182                 :            : 
     183                 :         19 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     184                 :         19 :         CU_cleanup_registry();
     185                 :            : 
     186                 :         19 :         return num_failures;
     187                 :            : }

Generated by: LCOV version 1.14