eal/bsd: concatenate adjacent memory segments
authorAnatoly Burakov <anatoly.burakov@intel.com>
Thu, 28 Jun 2018 11:41:48 +0000 (12:41 +0100)
committerThomas Monjalon <thomas@monjalon.net>
Thu, 12 Jul 2018 22:58:56 +0000 (00:58 +0200)
Previously, memory allocator always left holes between mapped
contigmem segments, even if they were IOVA-contiguous. Fix this
by remembering last IOVA address and memseg index, and checking
against those when mapping new contigmem segments.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
lib/librte_eal/bsdapp/eal/eal_memory.c

index ca06de2..7bf05c7 100644 (file)
@@ -104,6 +104,8 @@ rte_eal_hugepage_init(void)
        /* map all hugepages and sort them */
        for (i = 0; i < internal_config.num_hugepage_sizes; i ++){
                struct hugepage_info *hpi;
+               rte_iova_t prev_end = 0;
+               int prev_ms_idx = -1;
                uint64_t page_sz, mem_needed;
                unsigned int n_pages, max_pages;
 
@@ -124,10 +126,27 @@ rte_eal_hugepage_init(void)
                        int error;
                        size_t sysctl_size = sizeof(physaddr);
                        char physaddr_str[64];
+                       bool is_adjacent;
+
+                       /* first, check if this segment is IOVA-adjacent to
+                        * the previous one.
+                        */
+                       snprintf(physaddr_str, sizeof(physaddr_str),
+                                       "hw.contigmem.physaddr.%d", j);
+                       error = sysctlbyname(physaddr_str, &physaddr,
+                                       &sysctl_size, NULL, 0);
+                       if (error < 0) {
+                               RTE_LOG(ERR, EAL, "Failed to get physical addr for buffer %u "
+                                               "from %s\n", j, hpi->hugedir);
+                               return -1;
+                       }
+
+                       is_adjacent = prev_end != 0 && physaddr == prev_end;
+                       prev_end = physaddr + hpi->hugepage_sz;
 
                        for (msl_idx = 0; msl_idx < RTE_MAX_MEMSEG_LISTS;
                                        msl_idx++) {
-                               bool empty;
+                               bool empty, need_hole;
                                msl = &mcfg->memsegs[msl_idx];
                                arr = &msl->memseg_arr;
 
@@ -136,20 +155,23 @@ rte_eal_hugepage_init(void)
 
                                empty = arr->count == 0;
 
-                               /* we need 1, plus hole if not empty */
+                               /* we need a hole if this isn't an empty memseg
+                                * list, and if previous segment was not
+                                * adjacent to current one.
+                                */
+                               need_hole = !empty && !is_adjacent;
+
+                               /* we need 1, plus hole if not adjacent */
                                ms_idx = rte_fbarray_find_next_n_free(arr,
-                                               0, 1 + (empty ? 1 : 0));
+                                               0, 1 + (need_hole ? 1 : 0));
 
                                /* memseg list is full? */
                                if (ms_idx < 0)
                                        continue;
 
-                               /* leave some space between memsegs, they are
-                                * not IOVA contiguous, so they shouldn't be VA
-                                * contiguous either.
-                                */
-                               if (!empty)
+                               if (need_hole && prev_ms_idx == ms_idx - 1)
                                        ms_idx++;
+                               prev_ms_idx = ms_idx;
 
                                break;
                        }
@@ -178,16 +200,6 @@ rte_eal_hugepage_init(void)
                                return -1;
                        }
 
-                       snprintf(physaddr_str, sizeof(physaddr_str), "hw.contigmem"
-                                       ".physaddr.%d", j);
-                       error = sysctlbyname(physaddr_str, &physaddr, &sysctl_size,
-                                       NULL, 0);
-                       if (error < 0) {
-                               RTE_LOG(ERR, EAL, "Failed to get physical addr for buffer %u "
-                                               "from %s\n", j, hpi->hugedir);
-                               return -1;
-                       }
-
                        seg->addr = addr;
                        seg->iova = physaddr;
                        seg->hugepage_sz = page_sz;