get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 32461,
    "url": "https://patches.dpdk.org/api/patches/32461/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/5db1054689acb30ec0139f06dd2c43845dea68cd.1513681966.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": "<5db1054689acb30ec0139f06dd2c43845dea68cd.1513681966.git.anatoly.burakov@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/5db1054689acb30ec0139f06dd2c43845dea68cd.1513681966.git.anatoly.burakov@intel.com",
    "date": "2017-12-19T11:14:39",
    "name": "[dpdk-dev,RFC,v2,12/23] eal: add support for dynamic memory allocation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "33c7a99d3e8803137c26c53c72d8ca9c578c9570",
    "submitter": {
        "id": 4,
        "url": "https://patches.dpdk.org/api/people/4/?format=api",
        "name": "Anatoly Burakov",
        "email": "anatoly.burakov@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/5db1054689acb30ec0139f06dd2c43845dea68cd.1513681966.git.anatoly.burakov@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/32461/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/32461/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 6927B1B1BD;\n\tTue, 19 Dec 2017 12:15:14 +0100 (CET)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id D9DAB1B01C\n\tfor <dev@dpdk.org>; Tue, 19 Dec 2017 12:14:55 +0100 (CET)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t19 Dec 2017 03:14:54 -0800",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby fmsmga002.fm.intel.com with ESMTP; 19 Dec 2017 03:14:53 -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\tvBJBEqFG003120; Tue, 19 Dec 2017 11:14:52 GMT",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id vBJBEqUd010264;\n\tTue, 19 Dec 2017 11:14:52 GMT",
            "(from aburakov@localhost)\n\tby sivswdev01.ir.intel.com with LOCAL id vBJBEqE7010259;\n\tTue, 19 Dec 2017 11:14:52 GMT"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.45,426,1508828400\"; d=\"scan'208\";a=\"3023084\"",
        "From": "Anatoly Burakov <anatoly.burakov@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "andras.kovacs@ericsson.com, laszlo.vadkeri@ericsson.com,\n\tkeith.wiles@intel.com, benjamin.walker@intel.com,\n\tbruce.richardson@intel.com, thomas@monjalon.net",
        "Date": "Tue, 19 Dec 2017 11:14:39 +0000",
        "Message-Id": "<5db1054689acb30ec0139f06dd2c43845dea68cd.1513681966.git.anatoly.burakov@intel.com>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "In-Reply-To": [
            "<cover.1513681966.git.anatoly.burakov@intel.com>",
            "<cover.1513681966.git.anatoly.burakov@intel.com>"
        ],
        "References": [
            "<cover.1513681966.git.anatoly.burakov@intel.com>",
            "<cover.1513681966.git.anatoly.burakov@intel.com>"
        ],
        "Subject": "[dpdk-dev] [RFC v2 12/23] eal: add support for dynamic memory\n\tallocation",
        "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": "Nothing uses that code yet. The bulk of it is copied from old\nmemory allocation stuff (eal_memory.c). We provide an API to\nallocate either one page or multiple pages, guaranteeing that\nwe'll get contiguous VA for all of the pages that we requested.\n\nSigned-off-by: Anatoly Burakov <anatoly.burakov@intel.com>\n---\n lib/librte_eal/common/eal_memalloc.h       |  47 ++++\n lib/librte_eal/linuxapp/eal/Makefile       |   2 +\n lib/librte_eal/linuxapp/eal/eal_memalloc.c | 416 +++++++++++++++++++++++++++++\n 3 files changed, 465 insertions(+)\n create mode 100755 lib/librte_eal/common/eal_memalloc.h\n create mode 100755 lib/librte_eal/linuxapp/eal/eal_memalloc.c",
    "diff": "diff --git a/lib/librte_eal/common/eal_memalloc.h b/lib/librte_eal/common/eal_memalloc.h\nnew file mode 100755\nindex 0000000..59fd330\n--- /dev/null\n+++ b/lib/librte_eal/common/eal_memalloc.h\n@@ -0,0 +1,47 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef EAL_MEMALLOC_H\n+#define EAL_MEMALLOC_H\n+\n+#include <stdbool.h>\n+\n+#include <rte_memory.h>\n+\n+struct rte_memseg *\n+eal_memalloc_alloc_page(uint64_t size, int socket);\n+\n+int\n+eal_memalloc_alloc_page_bulk(struct rte_memseg **ms, int n, uint64_t size,\n+\t\tint socket, bool exact);\n+\n+#endif // EAL_MEMALLOC_H\ndiff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile\nindex 782e1ad..88f10e9 100644\n--- a/lib/librte_eal/linuxapp/eal/Makefile\n+++ b/lib/librte_eal/linuxapp/eal/Makefile\n@@ -62,6 +62,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_thread.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_log.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio_mp_sync.c\n+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_memalloc.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_debug.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c\n@@ -105,6 +106,7 @@ CFLAGS_eal_interrupts.o := -D_GNU_SOURCE\n CFLAGS_eal_vfio_mp_sync.o := -D_GNU_SOURCE\n CFLAGS_eal_timer.o := -D_GNU_SOURCE\n CFLAGS_eal_lcore.o := -D_GNU_SOURCE\n+CFLAGS_eal_memalloc.o := -D_GNU_SOURCE\n CFLAGS_eal_thread.o := -D_GNU_SOURCE\n CFLAGS_eal_log.o := -D_GNU_SOURCE\n CFLAGS_eal_common_log.o := -D_GNU_SOURCE\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_memalloc.c b/lib/librte_eal/linuxapp/eal/eal_memalloc.c\nnew file mode 100755\nindex 0000000..527c2f6\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/eal/eal_memalloc.c\n@@ -0,0 +1,416 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#define _FILE_OFFSET_BITS 64\n+#include <errno.h>\n+#include <stdarg.h>\n+#include <stdbool.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+#include <string.h>\n+#include <sys/mman.h>\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <sys/queue.h>\n+#include <sys/file.h>\n+#include <unistd.h>\n+#include <limits.h>\n+#include <fcntl.h>\n+#include <sys/ioctl.h>\n+#include <sys/time.h>\n+#include <signal.h>\n+#include <setjmp.h>\n+#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES\n+#include <numa.h>\n+#include <numaif.h>\n+#endif\n+\n+#include <rte_common.h>\n+#include <rte_log.h>\n+#include <rte_eal_memconfig.h>\n+#include <rte_eal.h>\n+#include <rte_memory.h>\n+\n+#include \"eal_filesystem.h\"\n+#include \"eal_internal_cfg.h\"\n+#include \"eal_memalloc.h\"\n+\n+static sigjmp_buf huge_jmpenv;\n+\n+static void __rte_unused huge_sigbus_handler(int signo __rte_unused)\n+{\n+\tsiglongjmp(huge_jmpenv, 1);\n+}\n+\n+/* Put setjmp into a wrap method to avoid compiling error. Any non-volatile,\n+ * non-static local variable in the stack frame calling sigsetjmp might be\n+ * clobbered by a call to longjmp.\n+ */\n+static int __rte_unused huge_wrap_sigsetjmp(void)\n+{\n+\treturn sigsetjmp(huge_jmpenv, 1);\n+}\n+\n+static struct sigaction huge_action_old;\n+static int huge_need_recover;\n+\n+static void __rte_unused\n+huge_register_sigbus(void)\n+{\n+\tsigset_t mask;\n+\tstruct sigaction action;\n+\n+\tsigemptyset(&mask);\n+\tsigaddset(&mask, SIGBUS);\n+\taction.sa_flags = 0;\n+\taction.sa_mask = mask;\n+\taction.sa_handler = huge_sigbus_handler;\n+\n+\thuge_need_recover = !sigaction(SIGBUS, &action, &huge_action_old);\n+}\n+\n+static void __rte_unused\n+huge_recover_sigbus(void)\n+{\n+\tif (huge_need_recover) {\n+\t\tsigaction(SIGBUS, &huge_action_old, NULL);\n+\t\thuge_need_recover = 0;\n+\t}\n+}\n+\n+#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES\n+static bool\n+prepare_numa(int *oldpolicy, struct bitmask *oldmask, int socket_id) {\n+\tbool have_numa = true;\n+\n+\t/* Check if kernel supports NUMA. */\n+\tif (numa_available() != 0) {\n+\t\tRTE_LOG(DEBUG, EAL, \"NUMA is not supported.\\n\");\n+\t\thave_numa = false;\n+\t}\n+\n+\tif (have_numa) {\n+\t\tRTE_LOG(DEBUG, EAL, \"Trying to obtain current memory policy.\\n\");\n+\t\tif (get_mempolicy(oldpolicy, oldmask->maskp,\n+\t\t\t\t  oldmask->size + 1, 0, 0) < 0) {\n+\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\"Failed to get current mempolicy: %s. \"\n+\t\t\t\t\"Assuming MPOL_DEFAULT.\\n\", strerror(errno));\n+\t\t\toldpolicy = MPOL_DEFAULT;\n+\t\t}\n+\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\"Setting policy MPOL_PREFERRED for socket %d\\n\",\n+\t\t\tsocket_id);\n+\t\tnuma_set_preferred(socket_id);\n+\t}\n+\treturn have_numa;\n+}\n+\n+static void\n+resotre_numa(int *oldpolicy, struct bitmask *oldmask) {\n+\tRTE_LOG(DEBUG, EAL,\n+\t\t\"Restoring previous memory policy: %d\\n\", *oldpolicy);\n+\tif (oldpolicy == MPOL_DEFAULT) {\n+\t\tnuma_set_localalloc();\n+\t} else if (set_mempolicy(*oldpolicy, oldmask->maskp,\n+\t\t\t\t oldmask->size + 1) < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to restore mempolicy: %s\\n\",\n+\t\t\tstrerror(errno));\n+\t\tnuma_set_localalloc();\n+\t}\n+\tnuma_free_cpumask(oldmask);\n+}\n+#endif\n+\n+static int\n+alloc_page(struct rte_memseg *ms, void *addr, uint64_t size, int socket_id,\n+\t\tstruct hugepage_info *hi, unsigned list_idx, unsigned seg_idx) {\n+\tint cur_socket_id = 0;\n+\tuint64_t fa_offset;\n+\tchar path[PATH_MAX];\n+\tint ret = 0;\n+\n+\tif (internal_config.single_file_segments) {\n+\t\teal_get_hugefile_path(path, sizeof(path), hi->hugedir, list_idx);\n+\t} else {\n+\t\teal_get_hugefile_path(path, sizeof(path), hi->hugedir,\n+\t\t\t\tlist_idx * RTE_MAX_MEMSEG_PER_LIST + seg_idx);\n+\t}\n+\n+\t/* try to create hugepage file */\n+\tint fd = open(path, O_CREAT | O_RDWR, 0600);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(DEBUG, EAL, \"%s(): open failed: %s\\n\", __func__,\n+\t\t\t\tstrerror(errno));\n+\t\tgoto fname;\n+\t}\n+\tif (internal_config.single_file_segments) {\n+\t\tfa_offset = seg_idx * size;\n+\t\tif (fallocate(fd, 0, fa_offset, size)) {\n+\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): fallocate() failed: %s\\n\",\n+\t\t\t\t__func__, strerror(errno));\n+\t\t\tgoto opened;\n+\t\t}\n+\t} else {\n+\t\tif (ftruncate(fd, size) < 0) {\n+\t\t\tRTE_LOG(DEBUG, EAL, \"%s(): ftruncate() failed: %s\\n\",\n+\t\t\t\t__func__, strerror(errno));\n+\t\t\tgoto opened;\n+\t\t}\n+\t\tfa_offset = 0;\n+\t}\n+\n+\t/* map the segment, and populate page tables,\n+\t * the kernel fills this segment with zeros */\n+\tvoid *va = mmap(addr, size, PROT_READ | PROT_WRITE,\n+\t\t\tMAP_SHARED | MAP_POPULATE | MAP_FIXED, fd, fa_offset);\n+\tif (va == MAP_FAILED) {\n+\t\tRTE_LOG(DEBUG, EAL, \"%s(): mmap() failed: %s\\n\", __func__,\n+\t\t\tstrerror(errno));\n+\t\tgoto resized;\n+\t}\n+\tif (va != addr) {\n+\t\tRTE_LOG(DEBUG, EAL, \"%s(): wrong mmap() address\\n\", __func__);\n+\t\tgoto mapped;\n+\t}\n+\n+\trte_iova_t iova = rte_mem_virt2iova(addr);\n+\tif (iova == RTE_BAD_PHYS_ADDR) {\n+\t\tRTE_LOG(DEBUG, EAL, \"%s(): can't get IOVA addr\\n\",\n+\t\t\t__func__);\n+\t\tgoto mapped;\n+\t}\n+\n+#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES\n+\tmove_pages(getpid(), 1, &addr, NULL, &cur_socket_id, 0);\n+\n+\tif (cur_socket_id != socket_id) {\n+\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\t\"%s(): allocation happened on wrong socket (wanted %d, got %d)\\n\",\n+\t\t\t__func__, socket_id, cur_socket_id);\n+\t\tgoto mapped;\n+\t}\n+#endif\n+\n+\t/* In linux, hugetlb limitations, like cgroup, are\n+\t * enforced at fault time instead of mmap(), even\n+\t * with the option of MAP_POPULATE. Kernel will send\n+\t * a SIGBUS signal. To avoid to be killed, save stack\n+\t * environment here, if SIGBUS happens, we can jump\n+\t * back here.\n+\t */\n+\tif (huge_wrap_sigsetjmp()) {\n+\t\tRTE_LOG(DEBUG, EAL, \"SIGBUS: Cannot mmap more hugepages of size %uMB\\n\",\n+\t\t\t(unsigned)(size / 0x100000));\n+\t\tgoto mapped;\n+\t}\n+\t*(int *)addr = *(int *) addr;\n+\n+\tclose(fd);\n+\n+\tms->addr = addr;\n+\tms->hugepage_sz = size;\n+\tms->len = size;\n+\tms->nchannel = rte_memory_get_nchannel();\n+\tms->nrank = rte_memory_get_nrank();\n+\tms->iova = iova;\n+\tms->socket_id = socket_id;\n+\n+\tgoto out;\n+\n+mapped:\n+\tmunmap(addr, size);\n+resized:\n+\tif (internal_config.single_file_segments)\n+\t\tfallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,\n+\t\t\t\tfa_offset, size);\n+\telse {\n+\t\tunlink(path);\n+\t}\n+opened:\n+\tclose(fd);\n+fname:\n+\t/* anything but goto out is an error */\n+\tret = -1;\n+out:\n+\treturn ret;\n+}\n+\n+int\n+eal_memalloc_alloc_page_bulk(struct rte_memseg **ms, int n,\n+\t\tuint64_t size, int socket, bool exact) {\n+\tstruct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;\n+\tstruct rte_memseg_list *msl = NULL;\n+\tvoid *addr;\n+\tunsigned msl_idx;\n+\tint cur_idx, next_idx, end_idx, i, ret = 0;\n+#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES\n+\tbool have_numa;\n+\tint oldpolicy;\n+\tstruct bitmask *oldmask = numa_allocate_nodemask();\n+#endif\n+\tstruct hugepage_info *hi = NULL;\n+\n+\t/* dynamic allocation not supported in legacy mode */\n+\tif (internal_config.legacy_mem)\n+\t\treturn -1;\n+\n+\tfor (i = 0; i < (int) RTE_DIM(internal_config.hugepage_info); i++) {\n+\t\tif (size ==\n+\t\t\t\tinternal_config.hugepage_info[i].hugepage_sz) {\n+\t\t\thi = &internal_config.hugepage_info[i];\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (!hi) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): can't find relevant hugepage_info entry\\n\",\n+\t\t\t__func__);\n+\t\treturn -1;\n+\t}\n+\n+\t/* find our memseg list */\n+\tfor (msl_idx = 0; msl_idx < RTE_MAX_MEMSEG_LISTS; msl_idx++) {\n+\t\tstruct rte_memseg_list *cur_msl = &mcfg->memsegs[msl_idx];\n+\n+\t\tif (cur_msl->hugepage_sz != size) {\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (cur_msl->socket_id != socket) {\n+\t\t\tcontinue;\n+\t\t}\n+\t\tmsl = cur_msl;\n+\t\tbreak;\n+\t}\n+\tif (!msl) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): couldn't find suitable memseg_list\\n\",\n+\t\t\t__func__);\n+\t\treturn -1;\n+\t}\n+\n+\t/* first, try finding space in already existing list */\n+\tcur_idx = rte_fbarray_find_next_n_free(&msl->memseg_arr, 0, n);\n+\n+\tif (cur_idx < 0) {\n+\t\tint old_len = msl->memseg_arr.len;\n+\t\tint space = 0;\n+\t\tint new_len = old_len;\n+\n+\t\t/* grow new len until we can either fit n or can't grow */\n+\t\twhile (new_len < msl->memseg_arr.capacity &&\n+\t\t\t\t(space < n)) {\n+\t\t\tnew_len = RTE_MIN(new_len * 2, msl->memseg_arr.capacity);\n+\t\t\tspace = new_len - old_len;\n+\t\t}\n+\n+\t\t/* check if we can expand the list */\n+\t\tif (old_len == new_len) {\n+\t\t\t/* can't expand, the list is full */\n+\t\t\tRTE_LOG(ERR, EAL, \"%s(): no space in memseg list\\n\",\n+\t\t\t\t__func__);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (rte_fbarray_resize(&msl->memseg_arr, new_len)) {\n+\t\t\tRTE_LOG(ERR, EAL, \"%s(): can't resize memseg list\\n\",\n+\t\t\t\t__func__);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/*\n+\t\t * we could conceivably end up with free space at the end of the\n+\t\t * list that wasn't enough to cover everything but can cover\n+\t\t * some of it, so start at (old_len - n) if possible.\n+\t\t */\n+\t\tnext_idx = RTE_MAX(0, old_len - n);\n+\n+\t\tcur_idx = rte_fbarray_find_next_n_free(&msl->memseg_arr,\n+\t\t\t\tnext_idx, n);\n+\n+\t\tif (cur_idx < 0) {\n+\t\t\t/* still no space, bail out */\n+\t\t\tRTE_LOG(ERR, EAL, \"%s(): no space in memseg list\\n\",\n+\t\t\t\t__func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tend_idx = cur_idx + n;\n+\n+#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES\n+\thave_numa = prepare_numa(&oldpolicy, oldmask, socket);\n+#endif\n+\n+\tfor (i = 0; cur_idx < end_idx; cur_idx++, i++) {\n+\t\tstruct rte_memseg *cur;\n+\n+\t\tcur = rte_fbarray_get(&msl->memseg_arr, cur_idx);\n+\t\taddr = RTE_PTR_ADD(msl->base_va,\n+\t\t\t\tcur_idx * msl->hugepage_sz);\n+\n+\t\tif (alloc_page(cur, addr, size, socket, hi, msl_idx, cur_idx)) {\n+\t\t\tRTE_LOG(DEBUG, EAL, \"attempted to allocate %i pages, but only %i were allocated\\n\",\n+\t\t\t\tn, i);\n+\n+\t\t\t/* if exact number of pages wasn't requested, stop */\n+\t\t\tif (!exact) {\n+\t\t\t\tret = i;\n+\t\t\t\tgoto restore_numa;\n+\t\t\t}\n+\t\t\tif (ms)\n+\t\t\t\tmemset(ms, 0, sizeof(struct rte_memseg*) * n);\n+\t\t\tret = -1;\n+\t\t\tgoto restore_numa;\n+\t\t}\n+\t\tif (ms)\n+\t\t\tms[i] = cur;\n+\n+\t\trte_fbarray_set_used(&msl->memseg_arr, cur_idx, true);\n+\t}\n+\tret = n;\n+\n+restore_numa:\n+#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES\n+\tif (have_numa)\n+\t\tresotre_numa(&oldpolicy, oldmask);\n+#endif\n+\treturn ret;\n+}\n+\n+struct rte_memseg *\n+eal_memalloc_alloc_page(uint64_t size, int socket) {\n+\tstruct rte_memseg *ms;\n+\tif (eal_memalloc_alloc_page_bulk(&ms, 1, size, socket, true) < 0)\n+\t\treturn NULL;\n+\treturn ms;\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "RFC",
        "v2",
        "12/23"
    ]
}