get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/35735/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 35735,
    "url": "https://patches.dpdk.org/api/patches/35735/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/9d334086e27d07951c381e96b3daa9ea5fb73f28.1520428025.git.anatoly.burakov@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<9d334086e27d07951c381e96b3daa9ea5fb73f28.1520428025.git.anatoly.burakov@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/9d334086e27d07951c381e96b3daa9ea5fb73f28.1520428025.git.anatoly.burakov@intel.com",
    "date": "2018-03-07T16:56:45",
    "name": "[dpdk-dev,v2,17/41] eal: enable memory hotplug support in rte_malloc",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "e577d1909a2b40b7f9ddd867cb39f4b1982e9c5c",
    "submitter": {
        "id": 4,
        "url": "https://patches.dpdk.org/api/people/4/?format=api",
        "name": "Burakov, Anatoly",
        "email": "anatoly.burakov@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/9d334086e27d07951c381e96b3daa9ea5fb73f28.1520428025.git.anatoly.burakov@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/35735/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/35735/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 8CD52AAC8;\n\tWed,  7 Mar 2018 17:57:32 +0100 (CET)",
            "from mga04.intel.com (mga04.intel.com [192.55.52.120])\n\tby dpdk.org (Postfix) with ESMTP id 30C385F69\n\tfor <dev@dpdk.org>; Wed,  7 Mar 2018 17:57:17 +0100 (CET)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n\tby fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t07 Mar 2018 08:57:16 -0800",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby orsmga008.jf.intel.com with ESMTP; 07 Mar 2018 08:57:12 -0800",
            "from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com\n\t[10.237.217.45])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\tw27GvC9Q032395; Wed, 7 Mar 2018 16:57:12 GMT",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id w27GvBYQ006735;\n\tWed, 7 Mar 2018 16:57:11 GMT",
            "(from aburakov@localhost)\n\tby sivswdev01.ir.intel.com with LOCAL id w27GvBQS006731;\n\tWed, 7 Mar 2018 16:57:11 GMT"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.47,436,1515484800\"; d=\"scan'208\";a=\"23283420\"",
        "From": "Anatoly Burakov <anatoly.burakov@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "keith.wiles@intel.com, jianfeng.tan@intel.com, andras.kovacs@ericsson.com,\n\tlaszlo.vadkeri@ericsson.com, benjamin.walker@intel.com,\n\tbruce.richardson@intel.com, thomas@monjalon.net,\n\tkonstantin.ananyev@intel.com, kuralamudhan.ramakrishnan@intel.com,\n\tlouise.m.daly@intel.com, nelio.laranjeiro@6wind.com,\n\tyskoh@mellanox.com, pepperjo@japf.ch, jerin.jacob@caviumnetworks.com, \n\themant.agrawal@nxp.com, olivier.matz@6wind.com",
        "Date": "Wed,  7 Mar 2018 16:56:45 +0000",
        "Message-Id": "<9d334086e27d07951c381e96b3daa9ea5fb73f28.1520428025.git.anatoly.burakov@intel.com>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "In-Reply-To": [
            "<cover.1520428025.git.anatoly.burakov@intel.com>",
            "<cover.1520428025.git.anatoly.burakov@intel.com>"
        ],
        "References": [
            "<cover.1520428025.git.anatoly.burakov@intel.com>",
            "<cover.1520083504.git.anatoly.burakov@intel.com>\n\t<cover.1520428025.git.anatoly.burakov@intel.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH v2 17/41] eal: enable memory hotplug support in\n\trte_malloc",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This set of changes enables rte_malloc to allocate and free memory\nas needed. The way it works is, first malloc checks if there is\nenough memory already allocated to satisfy user's request. If there\nisn't, we try and allocate more memory. The reverse happens with\nfree - we free an element, check its size (including free element\nmerging due to adjacency) and see if it's bigger than hugepage\nsize and that its start and end span a hugepage or more. Then we\nremove the area from malloc heap (adjusting element lengths where\nappropriate), and deallocate the page.\n\nFor legacy mode, runtime alloc/free of pages is disabled.\n\nIt is worth noting that memseg lists are being sorted by page size,\nand that we try our best to satisfy user's request. That is, if\nthe user requests an element from a 2MB page memory, we will check\nif we can satisfy that request from existing memory, if not we try\nand allocate more 2MB pages. If that fails and user also specified\na \"size is hint\" flag, we then check other page sizes and try to\nallocate from there. If that fails too, then, depending on flags,\nwe may try allocating from other sockets. In other words, we try\nour best to give the user what they asked for, but going to other\nsockets is last resort - first we try to allocate more memory on\nthe same socket.\n\nSigned-off-by: Anatoly Burakov <anatoly.burakov@intel.com>\n---\n lib/librte_eal/common/eal_common_memzone.c |  23 +-\n lib/librte_eal/common/malloc_elem.c        |  85 ++++++++\n lib/librte_eal/common/malloc_elem.h        |   3 +\n lib/librte_eal/common/malloc_heap.c        | 332 ++++++++++++++++++++++++++++-\n lib/librte_eal/common/malloc_heap.h        |   4 +-\n lib/librte_eal/common/rte_malloc.c         |  31 +--\n 6 files changed, 416 insertions(+), 62 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c\nindex ed36174..718dee8 100644\n--- a/lib/librte_eal/common/eal_common_memzone.c\n+++ b/lib/librte_eal/common/eal_common_memzone.c\n@@ -103,7 +103,6 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,\n \tstruct rte_memzone *mz;\n \tstruct rte_mem_config *mcfg;\n \tsize_t requested_len;\n-\tint socket, i;\n \n \t/* get pointer to global configuration */\n \tmcfg = rte_eal_get_configuration()->mem_config;\n@@ -181,27 +180,9 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,\n \t\t}\n \t}\n \n-\tif (socket_id == SOCKET_ID_ANY)\n-\t\tsocket = malloc_get_numa_socket();\n-\telse\n-\t\tsocket = socket_id;\n-\n \t/* allocate memory on heap */\n-\tvoid *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket], NULL,\n-\t\t\trequested_len, flags, align, bound);\n-\n-\tif ((mz_addr == NULL) && (socket_id == SOCKET_ID_ANY)) {\n-\t\t/* try other heaps */\n-\t\tfor (i = 0; i < RTE_MAX_NUMA_NODES; i++) {\n-\t\t\tif (socket == i)\n-\t\t\t\tcontinue;\n-\n-\t\t\tmz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[i],\n-\t\t\t\t\tNULL, requested_len, flags, align, bound);\n-\t\t\tif (mz_addr != NULL)\n-\t\t\t\tbreak;\n-\t\t}\n-\t}\n+\tvoid *mz_addr = malloc_heap_alloc(NULL, requested_len, socket_id, flags,\n+\t\t\talign, bound);\n \n \tif (mz_addr == NULL) {\n \t\trte_errno = ENOMEM;\ndiff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c\nindex 701bffd..eabad66 100644\n--- a/lib/librte_eal/common/malloc_elem.c\n+++ b/lib/librte_eal/common/malloc_elem.c\n@@ -400,6 +400,91 @@ malloc_elem_free(struct malloc_elem *elem)\n \treturn elem;\n }\n \n+/* assume all checks were already done */\n+void\n+malloc_elem_hide_region(struct malloc_elem *elem, void *start, size_t len)\n+{\n+\tsize_t len_before, len_after;\n+\tstruct malloc_elem *prev, *next;\n+\tvoid *end, *elem_end;\n+\n+\tend = RTE_PTR_ADD(start, len);\n+\telem_end = RTE_PTR_ADD(elem, elem->size);\n+\tlen_before = RTE_PTR_DIFF(start, elem);\n+\tlen_after = RTE_PTR_DIFF(elem_end, end);\n+\n+\tprev = elem->prev;\n+\tnext = elem->next;\n+\n+\tif (len_after >= MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {\n+\t\t/* split after */\n+\t\tstruct malloc_elem *split_after = end;\n+\n+\t\tsplit_elem(elem, split_after);\n+\n+\t\tnext = split_after;\n+\n+\t\tmalloc_elem_free_list_insert(split_after);\n+\t} else if (len_after >= MALLOC_ELEM_HEADER_LEN) {\n+\t\tstruct malloc_elem *pad_elem = end;\n+\n+\t\t/* shrink current element */\n+\t\telem->size -= len_after;\n+\t\tmemset(pad_elem, 0, sizeof(*pad_elem));\n+\n+\t\t/* copy next element's data to our pad */\n+\t\tmemcpy(pad_elem, next, sizeof(*pad_elem));\n+\n+\t\t/* pad next element */\n+\t\tnext->state = ELEM_PAD;\n+\t\tnext->pad = len_after;\n+\n+\t\t/* next element is busy, would've been merged otherwise */\n+\t\tpad_elem->pad = len_after;\n+\t\tpad_elem->size += len_after;\n+\n+\t\t/* adjust pointers to point to our new pad */\n+\t\tpad_elem->next->prev = pad_elem;\n+\t\telem->next = pad_elem;\n+\t} else if (len_after > 0) {\n+\t\trte_panic(\"Unaligned element, heap is probably corrupt\\n\");\n+\t}\n+\n+\tif (len_before >= MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {\n+\t\t/* split before */\n+\t\tstruct malloc_elem *split_before = start;\n+\n+\t\tsplit_elem(elem, split_before);\n+\n+\t\tprev = elem;\n+\t\telem = split_before;\n+\n+\t\tmalloc_elem_free_list_insert(prev);\n+\t} else if (len_before > 0) {\n+\t\t/*\n+\t\t * unlike with elements after current, here we don't need to\n+\t\t * pad elements, but rather just increase the size of previous\n+\t\t * element, copy the old header and and set up trailer.\n+\t\t */\n+\t\tvoid *trailer = RTE_PTR_ADD(prev,\n+\t\t\t\tprev->size - MALLOC_ELEM_TRAILER_LEN);\n+\t\tstruct malloc_elem *new_elem = start;\n+\n+\t\tmemcpy(new_elem, elem, sizeof(*elem));\n+\t\tnew_elem->size -= len_before;\n+\n+\t\tprev->size += len_before;\n+\t\tset_trailer(prev);\n+\n+\t\telem = new_elem;\n+\n+\t\t/* erase old trailer */\n+\t\tmemset(trailer, 0, MALLOC_ELEM_TRAILER_LEN);\n+\t}\n+\n+\tremove_elem(elem);\n+}\n+\n /*\n  * attempt to resize a malloc_elem by expanding into any free space\n  * immediately after it in memory.\ndiff --git a/lib/librte_eal/common/malloc_elem.h b/lib/librte_eal/common/malloc_elem.h\nindex 388c16f..6d979d2 100644\n--- a/lib/librte_eal/common/malloc_elem.h\n+++ b/lib/librte_eal/common/malloc_elem.h\n@@ -152,6 +152,9 @@ int\n malloc_elem_resize(struct malloc_elem *elem, size_t size);\n \n void\n+malloc_elem_hide_region(struct malloc_elem *elem, void *start, size_t len);\n+\n+void\n malloc_elem_free_list_remove(struct malloc_elem *elem);\n \n /*\ndiff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c\nindex 058ad75..87dc9ad 100644\n--- a/lib/librte_eal/common/malloc_heap.c\n+++ b/lib/librte_eal/common/malloc_heap.c\n@@ -20,8 +20,10 @@\n #include <rte_spinlock.h>\n #include <rte_memcpy.h>\n #include <rte_atomic.h>\n+#include <rte_fbarray.h>\n \n #include \"eal_internal_cfg.h\"\n+#include \"eal_memalloc.h\"\n #include \"malloc_elem.h\"\n #include \"malloc_heap.h\"\n \n@@ -123,48 +125,356 @@ find_suitable_element(struct malloc_heap *heap, size_t size,\n  * scan fails. Once the new memseg is added, it re-scans and should return\n  * the new element after releasing the lock.\n  */\n-void *\n-malloc_heap_alloc(struct malloc_heap *heap,\n-\t\tconst char *type __attribute__((unused)), size_t size, unsigned flags,\n-\t\tsize_t align, size_t bound)\n+static void *\n+heap_alloc(struct malloc_heap *heap, const char *type __rte_unused, size_t size,\n+\t\tunsigned int flags, size_t align, size_t bound)\n {\n \tstruct malloc_elem *elem;\n \n \tsize = RTE_CACHE_LINE_ROUNDUP(size);\n \talign = RTE_CACHE_LINE_ROUNDUP(align);\n \n-\trte_spinlock_lock(&heap->lock);\n-\n \telem = find_suitable_element(heap, size, flags, align, bound);\n \tif (elem != NULL) {\n \t\telem = malloc_elem_alloc(elem, size, align, bound);\n+\n \t\t/* increase heap's count of allocated elements */\n \t\theap->alloc_count++;\n \t}\n-\trte_spinlock_unlock(&heap->lock);\n \n \treturn elem == NULL ? NULL : (void *)(&elem[1]);\n }\n \n+static int\n+try_expand_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,\n+\t\tint socket, unsigned int flags, size_t align, size_t bound)\n+{\n+\tstruct rte_memseg_list *msl;\n+\tstruct rte_memseg **ms;\n+\tstruct malloc_elem *elem;\n+\tsize_t map_len;\n+\tint i, n_pages, allocd_pages;\n+\tvoid *ret, *map_addr;\n+\n+\talign = RTE_MAX(align, MALLOC_ELEM_HEADER_LEN);\n+\tmap_len = RTE_ALIGN_CEIL(align + elt_size + MALLOC_ELEM_TRAILER_LEN,\n+\t\t\tpg_sz);\n+\n+\tn_pages = map_len / pg_sz;\n+\n+\t/* we can't know in advance how many pages we'll need, so malloc */\n+\tms = malloc(sizeof(*ms) * n_pages);\n+\n+\tallocd_pages = eal_memalloc_alloc_page_bulk(ms, n_pages, pg_sz, socket,\n+\t\t\ttrue);\n+\n+\t/* make sure we've allocated our pages... */\n+\tif (allocd_pages != n_pages)\n+\t\tgoto free_ms;\n+\n+\tmap_addr = ms[0]->addr;\n+\tmsl = rte_mem_virt2memseg_list(map_addr);\n+\n+\t/* add newly minted memsegs to malloc heap */\n+\telem = malloc_heap_add_memory(heap, msl, map_addr, map_len);\n+\n+\t/* try once more, as now we have allocated new memory */\n+\tret = find_suitable_element(heap, elt_size, flags, align, bound);\n+\n+\tif (ret == NULL)\n+\t\tgoto free_elem;\n+\n+\tRTE_LOG(DEBUG, EAL, \"Heap on socket %d was expanded by %zdMB\\n\",\n+\t\tsocket, map_len >> 20ULL);\n+\n+\tfree(ms);\n+\n+\treturn 0;\n+\n+free_elem:\n+\tmalloc_elem_free_list_remove(elem);\n+\tmalloc_elem_hide_region(elem, map_addr, map_len);\n+\theap->total_size -= map_len;\n+\n+\tfor (i = 0; i < n_pages; i++)\n+\t\teal_memalloc_free_page(ms[i]);\n+free_ms:\n+\tfree(ms);\n+\n+\treturn -1;\n+}\n+\n+static int\n+compare_pagesz(const void *a, const void *b)\n+{\n+\tconst struct rte_memseg_list * const*mpa = a;\n+\tconst struct rte_memseg_list * const*mpb = b;\n+\tconst struct rte_memseg_list *msla = *mpa;\n+\tconst struct rte_memseg_list *mslb = *mpb;\n+\tuint64_t pg_sz_a = msla->hugepage_sz;\n+\tuint64_t pg_sz_b = mslb->hugepage_sz;\n+\n+\tif (pg_sz_a < pg_sz_b)\n+\t\treturn -1;\n+\tif (pg_sz_a > pg_sz_b)\n+\t\treturn 1;\n+\treturn 0;\n+}\n+\n+static int\n+alloc_mem_on_socket(size_t size, int socket, unsigned int flags, size_t align,\n+\t\tsize_t bound)\n+{\n+\tstruct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;\n+\tstruct malloc_heap *heap = &mcfg->malloc_heaps[socket];\n+\tstruct rte_memseg_list *requested_msls[RTE_MAX_MEMSEG_LISTS];\n+\tstruct rte_memseg_list *other_msls[RTE_MAX_MEMSEG_LISTS];\n+\tuint64_t requested_pg_sz[RTE_MAX_MEMSEG_LISTS];\n+\tuint64_t other_pg_sz[RTE_MAX_MEMSEG_LISTS];\n+\tuint64_t prev_pg_sz;\n+\tint i, n_other_msls, n_other_pg_sz, n_requested_msls, n_requested_pg_sz;\n+\tbool size_hint = (flags & RTE_MEMZONE_SIZE_HINT_ONLY) > 0;\n+\tunsigned int size_flags = flags & ~RTE_MEMZONE_SIZE_HINT_ONLY;\n+\tvoid *ret;\n+\n+\tmemset(requested_msls, 0, sizeof(requested_msls));\n+\tmemset(other_msls, 0, sizeof(other_msls));\n+\tmemset(requested_pg_sz, 0, sizeof(requested_pg_sz));\n+\tmemset(other_pg_sz, 0, sizeof(other_pg_sz));\n+\n+\t/*\n+\t * go through memseg list and take note of all the page sizes available,\n+\t * and if any of them were specifically requested by the user.\n+\t */\n+\tn_requested_msls = 0;\n+\tn_other_msls = 0;\n+\tfor (i = 0; i < RTE_MAX_MEMSEG_LISTS; i++) {\n+\t\tstruct rte_memseg_list *msl = &mcfg->memsegs[i];\n+\n+\t\tif (msl->socket_id != socket)\n+\t\t\tcontinue;\n+\n+\t\tif (msl->base_va == NULL)\n+\t\t\tcontinue;\n+\n+\t\t/* if pages of specific size were requested */\n+\t\tif (size_flags != 0 && check_hugepage_sz(size_flags,\n+\t\t\t\tmsl->hugepage_sz))\n+\t\t\trequested_msls[n_requested_msls++] = msl;\n+\t\telse if (size_flags == 0 || size_hint)\n+\t\t\tother_msls[n_other_msls++] = msl;\n+\t}\n+\n+\t/* sort the lists, smallest first */\n+\tqsort(requested_msls, n_requested_msls, sizeof(requested_msls[0]),\n+\t\t\tcompare_pagesz);\n+\tqsort(other_msls, n_other_msls, sizeof(other_msls[0]),\n+\t\t\tcompare_pagesz);\n+\n+\t/* now, extract page sizes we are supposed to try */\n+\tprev_pg_sz = 0;\n+\tn_requested_pg_sz = 0;\n+\tfor (i = 0; i < n_requested_msls; i++) {\n+\t\tuint64_t pg_sz = requested_msls[i]->hugepage_sz;\n+\n+\t\tif (prev_pg_sz != pg_sz) {\n+\t\t\trequested_pg_sz[n_requested_pg_sz++] = pg_sz;\n+\t\t\tprev_pg_sz = pg_sz;\n+\t\t}\n+\t}\n+\tprev_pg_sz = 0;\n+\tn_other_pg_sz = 0;\n+\tfor (i = 0; i < n_other_msls; i++) {\n+\t\tuint64_t pg_sz = other_msls[i]->hugepage_sz;\n+\n+\t\tif (prev_pg_sz != pg_sz) {\n+\t\t\tother_pg_sz[n_other_pg_sz++] = pg_sz;\n+\t\t\tprev_pg_sz = pg_sz;\n+\t\t}\n+\t}\n+\n+\t/* finally, try allocating memory of specified page sizes, starting from\n+\t * the smallest sizes\n+\t */\n+\tfor (i = 0; i < n_requested_pg_sz; i++) {\n+\t\tuint64_t pg_sz = requested_pg_sz[i];\n+\n+\t\t/*\n+\t\t * do not pass the size hint here, as user expects other page\n+\t\t * sizes first, before resorting to best effort allocation.\n+\t\t */\n+\t\tif (!try_expand_heap(heap, pg_sz, size, socket, size_flags,\n+\t\t\t\talign, bound))\n+\t\t\treturn 0;\n+\t}\n+\tif (n_other_pg_sz == 0)\n+\t\treturn -1;\n+\n+\t/* now, check if we can reserve anything with size hint */\n+\tret = find_suitable_element(heap, size, flags, align, bound);\n+\tif (ret != NULL)\n+\t\treturn 0;\n+\n+\t/*\n+\t * we still couldn't reserve memory, so try expanding heap with other\n+\t * page sizes, if there are any\n+\t */\n+\tfor (i = 0; i < n_other_pg_sz; i++) {\n+\t\tuint64_t pg_sz = other_pg_sz[i];\n+\n+\t\tif (!try_expand_heap(heap, pg_sz, size, socket, flags,\n+\t\t\t\talign, bound))\n+\t\t\treturn 0;\n+\t}\n+\treturn -1;\n+}\n+\n+/* this will try lower page sizes first */\n+static void *\n+heap_alloc_on_socket(const char *type, size_t size, int socket,\n+\t\tunsigned int flags, size_t align, size_t bound)\n+{\n+\tstruct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;\n+\tstruct malloc_heap *heap = &mcfg->malloc_heaps[socket];\n+\tunsigned int size_flags = flags & ~RTE_MEMZONE_SIZE_HINT_ONLY;\n+\tvoid *ret;\n+\n+\trte_spinlock_lock(&(heap->lock));\n+\n+\talign = align == 0 ? 1 : align;\n+\n+\t/* for legacy mode, try once and with all flags */\n+\tif (internal_config.legacy_mem) {\n+\t\tret = heap_alloc(heap, type, size, flags, align, bound);\n+\t\tgoto alloc_unlock;\n+\t}\n+\n+\t/*\n+\t * we do not pass the size hint here, because even if allocation fails,\n+\t * we may still be able to allocate memory from appropriate page sizes,\n+\t * we just need to request more memory first.\n+\t */\n+\tret = heap_alloc(heap, type, size, size_flags, align, bound);\n+\tif (ret != NULL)\n+\t\tgoto alloc_unlock;\n+\n+\tif (!alloc_mem_on_socket(size, socket, flags, align, bound)) {\n+\t\tret = heap_alloc(heap, type, size, flags, align, bound);\n+\n+\t\t/* this should have succeeded */\n+\t\tif (ret == NULL)\n+\t\t\trte_panic(\"Error allocating from heap\\n\");\n+\t}\n+alloc_unlock:\n+\trte_spinlock_unlock(&(heap->lock));\n+\treturn ret;\n+}\n+\n+void *\n+malloc_heap_alloc(const char *type, size_t size, int socket_arg,\n+\t\tunsigned int flags, size_t align, size_t bound)\n+{\n+\tint socket, i;\n+\tvoid *ret;\n+\n+\t/* return NULL if size is 0 or alignment is not power-of-2 */\n+\tif (size == 0 || (align && !rte_is_power_of_2(align)))\n+\t\treturn NULL;\n+\n+\tif (!rte_eal_has_hugepages())\n+\t\tsocket_arg = SOCKET_ID_ANY;\n+\n+\tif (socket_arg == SOCKET_ID_ANY)\n+\t\tsocket = malloc_get_numa_socket();\n+\telse\n+\t\tsocket = socket_arg;\n+\n+\t/* Check socket parameter */\n+\tif (socket >= RTE_MAX_NUMA_NODES)\n+\t\treturn NULL;\n+\n+\tret = heap_alloc_on_socket(type, size, socket, flags, align, bound);\n+\tif (ret != NULL || socket_arg != SOCKET_ID_ANY)\n+\t\treturn ret;\n+\n+\t/* try other heaps */\n+\tfor (i = 0; i < (int) rte_num_sockets(); i++) {\n+\t\tif (i == socket)\n+\t\t\tcontinue;\n+\t\tret = heap_alloc_on_socket(type, size, i, flags,\n+\t\t\t\talign, bound);\n+\t\tif (ret != NULL)\n+\t\t\treturn ret;\n+\t}\n+\treturn NULL;\n+}\n+\n int\n malloc_heap_free(struct malloc_elem *elem)\n {\n \tstruct malloc_heap *heap;\n-\tstruct malloc_elem *ret;\n+\tvoid *start, *aligned_start, *end, *aligned_end;\n+\tsize_t len, aligned_len;\n+\tstruct rte_memseg_list *msl;\n+\tint n_pages, page_idx, max_page_idx, ret;\n \n \tif (!malloc_elem_cookies_ok(elem) || elem->state != ELEM_BUSY)\n \t\treturn -1;\n \n \t/* elem may be merged with previous element, so keep heap address */\n \theap = elem->heap;\n+\tmsl = elem->msl;\n \n \trte_spinlock_lock(&(heap->lock));\n \n-\tret = malloc_elem_free(elem);\n+\telem = malloc_elem_free(elem);\n \n-\trte_spinlock_unlock(&(heap->lock));\n+\t/* anything after this is a bonus */\n+\tret = 0;\n+\n+\t/* ...of which we can't avail if we are in legacy mode */\n+\tif (internal_config.legacy_mem)\n+\t\tgoto free_unlock;\n+\n+\t/* check if we can free any memory back to the system */\n+\tif (elem->size < msl->hugepage_sz)\n+\t\tgoto free_unlock;\n \n-\treturn ret != NULL ? 0 : -1;\n+\t/* probably, but let's make sure, as we may not be using up full page */\n+\tstart = elem;\n+\tlen = elem->size;\n+\taligned_start = RTE_PTR_ALIGN_CEIL(start, msl->hugepage_sz);\n+\tend = RTE_PTR_ADD(elem, len);\n+\taligned_end = RTE_PTR_ALIGN_FLOOR(end, msl->hugepage_sz);\n+\n+\taligned_len = RTE_PTR_DIFF(aligned_end, aligned_start);\n+\n+\t/* can't free anything */\n+\tif (aligned_len < msl->hugepage_sz)\n+\t\tgoto free_unlock;\n+\n+\tmalloc_elem_free_list_remove(elem);\n+\n+\tmalloc_elem_hide_region(elem, (void *) aligned_start, aligned_len);\n+\n+\t/* we don't really care if we fail to deallocate memory */\n+\tn_pages = aligned_len / msl->hugepage_sz;\n+\tpage_idx = RTE_PTR_DIFF(aligned_start, msl->base_va) / msl->hugepage_sz;\n+\tmax_page_idx = page_idx + n_pages;\n+\n+\tfor (; page_idx < max_page_idx; page_idx++) {\n+\t\tstruct rte_memseg *ms;\n+\n+\t\tms = rte_fbarray_get(&msl->memseg_arr, page_idx);\n+\t\teal_memalloc_free_page(ms);\n+\t\theap->total_size -= msl->hugepage_sz;\n+\t}\n+\n+\tRTE_LOG(DEBUG, EAL, \"Heap on socket %d was shrunk by %zdMB\\n\",\n+\t\tmsl->socket_id, aligned_len >> 20ULL);\n+free_unlock:\n+\trte_spinlock_unlock(&(heap->lock));\n+\treturn ret;\n }\n \n int\ndiff --git a/lib/librte_eal/common/malloc_heap.h b/lib/librte_eal/common/malloc_heap.h\nindex bb28422..292d578 100644\n--- a/lib/librte_eal/common/malloc_heap.h\n+++ b/lib/librte_eal/common/malloc_heap.h\n@@ -24,8 +24,8 @@ malloc_get_numa_socket(void)\n }\n \n void *\n-malloc_heap_alloc(struct malloc_heap *heap,\tconst char *type, size_t size,\n-\t\tunsigned flags, size_t align, size_t bound);\n+malloc_heap_alloc(const char *type, size_t size, int socket, unsigned int flags,\n+\t\tsize_t align, size_t bound);\n \n int\n malloc_heap_free(struct malloc_elem *elem);\ndiff --git a/lib/librte_eal/common/rte_malloc.c b/lib/librte_eal/common/rte_malloc.c\nindex bd7e757..b0fe11c 100644\n--- a/lib/librte_eal/common/rte_malloc.c\n+++ b/lib/librte_eal/common/rte_malloc.c\n@@ -39,10 +39,6 @@ void rte_free(void *addr)\n void *\n rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)\n {\n-\tstruct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;\n-\tint socket, i;\n-\tvoid *ret;\n-\n \t/* return NULL if size is 0 or alignment is not power-of-2 */\n \tif (size == 0 || (align && !rte_is_power_of_2(align)))\n \t\treturn NULL;\n@@ -50,33 +46,12 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)\n \tif (!rte_eal_has_hugepages())\n \t\tsocket_arg = SOCKET_ID_ANY;\n \n-\tif (socket_arg == SOCKET_ID_ANY)\n-\t\tsocket = malloc_get_numa_socket();\n-\telse\n-\t\tsocket = socket_arg;\n-\n \t/* Check socket parameter */\n-\tif (socket >= RTE_MAX_NUMA_NODES)\n+\tif (socket_arg >= RTE_MAX_NUMA_NODES)\n \t\treturn NULL;\n \n-\tret = malloc_heap_alloc(&mcfg->malloc_heaps[socket], type,\n-\t\t\t\tsize, 0, align == 0 ? 1 : align, 0);\n-\tif (ret != NULL || socket_arg != SOCKET_ID_ANY)\n-\t\treturn ret;\n-\n-\t/* try other heaps */\n-\tfor (i = 0; i < RTE_MAX_NUMA_NODES; i++) {\n-\t\t/* we already tried this one */\n-\t\tif (i == socket)\n-\t\t\tcontinue;\n-\n-\t\tret = malloc_heap_alloc(&mcfg->malloc_heaps[i], type,\n-\t\t\t\t\tsize, 0, align == 0 ? 1 : align, 0);\n-\t\tif (ret != NULL)\n-\t\t\treturn ret;\n-\t}\n-\n-\treturn NULL;\n+\treturn malloc_heap_alloc(type, size, socket_arg, 0,\n+\t\t\talign == 0 ? 1 : align, 0);\n }\n \n /*\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "17/41"
    ]
}