get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 129612,
    "url": "http://patches.dpdk.org/api/patches/129612/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230718024006.2154-4-fengchengwen@huawei.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20230718024006.2154-4-fengchengwen@huawei.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230718024006.2154-4-fengchengwen@huawei.com",
    "date": "2023-07-18T02:40:03",
    "name": "[v17,3/6] memarea: support alloc and free API",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "053a860b5b49e769de1261fb3941ba97722cc9df",
    "submitter": {
        "id": 2146,
        "url": "http://patches.dpdk.org/api/people/2146/?format=api",
        "name": "fengchengwen",
        "email": "fengchengwen@huawei.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230718024006.2154-4-fengchengwen@huawei.com/mbox/",
    "series": [
        {
            "id": 28961,
            "url": "http://patches.dpdk.org/api/series/28961/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=28961",
            "date": "2023-07-18T02:40:06",
            "name": "introduce memarea library",
            "version": 17,
            "mbox": "http://patches.dpdk.org/series/28961/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/129612/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/129612/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 9A05842EA1;\n\tTue, 18 Jul 2023 04:48:56 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id A647442D48;\n\tTue, 18 Jul 2023 04:48:29 +0200 (CEST)",
            "from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188])\n by mails.dpdk.org (Postfix) with ESMTP id A42A040223\n for <dev@dpdk.org>; Tue, 18 Jul 2023 04:48:21 +0200 (CEST)",
            "from dggpeml100024.china.huawei.com (unknown [172.30.72.54])\n by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4R4jwW07N7zNmTN;\n Tue, 18 Jul 2023 10:44:59 +0800 (CST)",
            "from localhost.localdomain (10.50.163.32) by\n dggpeml100024.china.huawei.com (7.185.36.115) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id\n 15.1.2507.27; Tue, 18 Jul 2023 10:48:18 +0800"
        ],
        "From": "Chengwen Feng <fengchengwen@huawei.com>",
        "To": "<thomas@monjalon.net>, <david.marchand@redhat.com>",
        "CC": "<dev@dpdk.org>, <mb@smartsharesystems.com>, <anatoly.burakov@intel.com>,\n <dmitry.kozliuk@gmail.com>, <jerinjacobk@gmail.com>, <hofors@lysator.liu.se>,\n <stephen@networkplumber.org>",
        "Subject": "[PATCH v17 3/6] memarea: support alloc and free API",
        "Date": "Tue, 18 Jul 2023 02:40:03 +0000",
        "Message-ID": "<20230718024006.2154-4-fengchengwen@huawei.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20230718024006.2154-1-fengchengwen@huawei.com>",
        "References": "<20220721044648.6817-1-fengchengwen@huawei.com>\n <20230718024006.2154-1-fengchengwen@huawei.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"UTF-8\"",
        "Content-Transfer-Encoding": "8bit",
        "X-Originating-IP": "[10.50.163.32]",
        "X-ClientProxiedBy": "dggems705-chm.china.huawei.com (10.3.19.182) To\n dggpeml100024.china.huawei.com (7.185.36.115)",
        "X-CFilter-Loop": "Reflected",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "This patch supports rte_memarea_alloc() and rte_memarea_free() API.\n\nSigned-off-by: Chengwen Feng <fengchengwen@huawei.com>\nReviewed-by: Dongdong Liu <liudongdong3@huawei.com>\nAcked-by: Morten Brørup <mb@smartsharesystems.com>\nAcked-by: Anatoly Burakov <anatoly.burakov@intel.com>\n---\n doc/guides/prog_guide/memarea_lib.rst |   6 +\n lib/memarea/memarea_private.h         |  10 ++\n lib/memarea/rte_memarea.c             | 159 ++++++++++++++++++++++++++\n lib/memarea/rte_memarea.h             |  46 ++++++++\n lib/memarea/version.map               |   2 +\n 5 files changed, 223 insertions(+)",
    "diff": "diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst\nindex bf19090294..157baf3c7e 100644\n--- a/doc/guides/prog_guide/memarea_lib.rst\n+++ b/doc/guides/prog_guide/memarea_lib.rst\n@@ -33,6 +33,12 @@ returns the pointer to the created memarea or ``NULL`` if the creation failed.\n \n The ``rte_memarea_destroy()`` function is used to destroy a memarea.\n \n+The ``rte_memarea_alloc()`` function is used to alloc one memory object from\n+the memarea.\n+\n+The ``rte_memarea_free()`` function is used to free one memory object which\n+allocated by ``rte_memarea_alloc()``.\n+\n Debug Mode\n ----------\n \ndiff --git a/lib/memarea/memarea_private.h b/lib/memarea/memarea_private.h\nindex fd485bb7e7..ab6253294e 100644\n--- a/lib/memarea/memarea_private.h\n+++ b/lib/memarea/memarea_private.h\n@@ -52,10 +52,20 @@ enum {\n #define MEMAREA_OBJECT_GET_SIZE(hdr) \\\n \t\t((uintptr_t)TAILQ_NEXT((hdr), obj_next) - (uintptr_t)(hdr) - \\\n \t\t sizeof(struct memarea_objhdr) - sizeof(struct memarea_objtlr))\n+#define MEMAREA_SPLIT_OBJECT_MIN_SIZE \\\n+\t\t(sizeof(struct memarea_objhdr) + MEMAREA_OBJECT_SIZE_ALIGN + \\\n+\t\t sizeof(struct memarea_objtlr))\n+#define MEMAREA_SPLIT_OBJECT_GET_HEADER(hdr, alloc_sz) \\\n+\t\tRTE_PTR_ADD(hdr, sizeof(struct memarea_objhdr) + alloc_sz + \\\n+\t\t\t    sizeof(struct memarea_objtlr))\n #else\n #define MEMAREA_OBJECT_GET_SIZE(hdr) \\\n \t\t((uintptr_t)TAILQ_NEXT((hdr), obj_next) - (uintptr_t)(hdr) - \\\n \t\t sizeof(struct memarea_objhdr))\n+#define MEMAREA_SPLIT_OBJECT_MIN_SIZE \\\n+\t\t(sizeof(struct memarea_objhdr) + MEMAREA_OBJECT_SIZE_ALIGN)\n+#define MEMAREA_SPLIT_OBJECT_GET_HEADER(hdr, alloc_sz) \\\n+\t\tRTE_PTR_ADD(hdr, sizeof(struct memarea_objhdr) + alloc_sz)\n #endif\n \n struct memarea_objhdr {\ndiff --git a/lib/memarea/rte_memarea.c b/lib/memarea/rte_memarea.c\nindex ea9067fb35..0c538b54ba 100644\n--- a/lib/memarea/rte_memarea.c\n+++ b/lib/memarea/rte_memarea.c\n@@ -2,8 +2,10 @@\n  * Copyright(c) 2023 HiSilicon Limited\n  */\n \n+#include <inttypes.h>\n #include <stdio.h>\n #include <stdlib.h>\n+#include <sys/queue.h>\n \n #include <rte_common.h>\n #include <rte_errno.h>\n@@ -94,6 +96,8 @@ memarea_alloc_area(const struct rte_memarea_param *init)\n \t\t\t\t\tinit->heap.socket_id);\n \telse if (init->source == RTE_MEMAREA_SOURCE_LIBC)\n \t\tptr = memarea_alloc_from_libc(init->total_sz);\n+\telse if (init->source == RTE_MEMAREA_SOURCE_MEMAREA)\n+\t\tptr = rte_memarea_alloc(init->ma.src, init->total_sz);\n \n \treturn ptr;\n }\n@@ -105,6 +109,8 @@ memarea_free_area(const struct rte_memarea_param *init, void *ptr)\n \t\trte_free(ptr);\n \telse if (init->source == RTE_MEMAREA_SOURCE_LIBC)\n \t\tfree(ptr);\n+\telse if (init->source == RTE_MEMAREA_SOURCE_MEMAREA)\n+\t\trte_memarea_free(init->ma.src, ptr);\n }\n \n static inline void\n@@ -206,3 +212,156 @@ rte_memarea_destroy(struct rte_memarea *ma)\n \tmemarea_free_area(&ma->init, ma->area_base);\n \trte_free(ma);\n }\n+\n+static inline void\n+memarea_lock(struct rte_memarea *ma)\n+{\n+\tif (ma->init.mt_safe)\n+\t\trte_spinlock_lock(&ma->lock);\n+}\n+\n+static inline void\n+memarea_unlock(struct rte_memarea *ma)\n+{\n+\tif (ma->init.mt_safe)\n+\t\trte_spinlock_unlock(&ma->lock);\n+}\n+\n+static inline void\n+memarea_check_cookie(const struct rte_memarea *ma, const struct memarea_objhdr *hdr, int status)\n+{\n+#ifdef RTE_LIBRTE_MEMAREA_DEBUG\n+\tstatic const char *const str[] = { \"PASS\", \"FAILED\" };\n+\tstruct memarea_objtlr *tlr;\n+\tbool hdr_fail, tlr_fail;\n+\n+\tif (hdr == ma->guard_hdr)\n+\t\treturn;\n+\n+\ttlr = RTE_PTR_SUB(TAILQ_NEXT(hdr, obj_next), sizeof(struct memarea_objtlr));\n+\thdr_fail = (status == COOKIE_EXPECT_STATUS_AVAILABLE &&\n+\t\t    hdr->cookie != MEMAREA_OBJECT_HEADER_AVAILABLE_COOKIE) ||\n+\t\t   (status == COOKIE_EXPECT_STATUS_ALLOCATED &&\n+\t\t    hdr->cookie != MEMAREA_OBJECT_HEADER_ALLOCATED_COOKIE) ||\n+\t\t   (status == COOKIE_EXPECT_STATUS_VALID &&\n+\t\t    (hdr->cookie != MEMAREA_OBJECT_HEADER_AVAILABLE_COOKIE &&\n+\t\t     hdr->cookie != MEMAREA_OBJECT_HEADER_ALLOCATED_COOKIE));\n+\ttlr_fail = (tlr->cookie != MEMAREA_OBJECT_TRAILER_COOKIE);\n+\tif (!hdr_fail && !tlr_fail)\n+\t\treturn;\n+\n+\trte_panic(\"MEMAREA: %s check cookies failed! addr-%p header-cookie<0x%\" PRIx64 \" %s> trailer-cookie<0x%\" PRIx64 \" %s>\\n\",\n+\t\tma->init.name, RTE_PTR_ADD(hdr, sizeof(struct memarea_objhdr)),\n+\t\thdr->cookie, str[hdr_fail], tlr->cookie, str[tlr_fail]);\n+#else\n+\tRTE_SET_USED(ma);\n+\tRTE_SET_USED(hdr);\n+\tRTE_SET_USED(status);\n+#endif\n+}\n+\n+static inline void\n+memarea_split_object(struct rte_memarea *ma, struct memarea_objhdr *hdr, size_t alloc_sz)\n+{\n+\tstruct memarea_objhdr *split_hdr;\n+\n+\tsplit_hdr = MEMAREA_SPLIT_OBJECT_GET_HEADER(hdr, alloc_sz);\n+\tmemarea_set_cookie(split_hdr, COOKIE_TARGET_STATUS_NEW_AVAILABLE);\n+\tTAILQ_INSERT_AFTER(&ma->obj_list, hdr, split_hdr, obj_next);\n+\tTAILQ_INSERT_AFTER(&ma->avail_list, hdr, split_hdr, avail_next);\n+}\n+\n+void *\n+rte_memarea_alloc(struct rte_memarea *ma, size_t size)\n+{\n+\tsize_t align_sz = RTE_ALIGN(size, MEMAREA_OBJECT_SIZE_ALIGN);\n+\tstruct memarea_objhdr *hdr;\n+\tsize_t avail_sz;\n+\tvoid *ptr = NULL;\n+\n+\tif (ma == NULL || size == 0 || align_sz < size) {\n+\t\trte_errno = EINVAL;\n+\t\treturn ptr;\n+\t}\n+\n+\tmemarea_lock(ma);\n+\n+\t/** traverse every available object, return the first satisfied one. */\n+\tTAILQ_FOREACH(hdr, &ma->avail_list, avail_next) {\n+\t\t/** 1st: check whether the object size meets. */\n+\t\tmemarea_check_cookie(ma, hdr, COOKIE_EXPECT_STATUS_AVAILABLE);\n+\t\tavail_sz = MEMAREA_OBJECT_GET_SIZE(hdr);\n+\t\tif (avail_sz < align_sz)\n+\t\t\tcontinue;\n+\n+\t\t/** 2nd: if the object size is too long, a new object can be split. */\n+\t\tif (avail_sz - align_sz > MEMAREA_SPLIT_OBJECT_MIN_SIZE)\n+\t\t\tmemarea_split_object(ma, hdr, align_sz);\n+\n+\t\t/** 3rd: allocate successful. */\n+\t\tTAILQ_REMOVE(&ma->avail_list, hdr, avail_next);\n+\t\tMEMAREA_OBJECT_MARK_ALLOCATED(hdr);\n+\t\tmemarea_set_cookie(hdr, COOKIE_TARGET_STATUS_ALLOCATED);\n+\n+\t\tptr = RTE_PTR_ADD(hdr, sizeof(struct memarea_objhdr));\n+\t\tbreak;\n+\t}\n+\n+\tmemarea_unlock(ma);\n+\n+\tif (ptr == NULL)\n+\t\trte_errno = ENOMEM;\n+\treturn ptr;\n+}\n+\n+static inline void\n+memarea_merge_object(struct rte_memarea *ma, struct memarea_objhdr *curr,\n+\t\t   struct memarea_objhdr *next)\n+{\n+\tRTE_SET_USED(curr);\n+\tTAILQ_REMOVE(&ma->obj_list, next, obj_next);\n+\tTAILQ_REMOVE(&ma->avail_list, next, avail_next);\n+\tmemarea_set_cookie(next, COOKIE_TARGET_STATUS_CLEARED);\n+}\n+\n+void\n+rte_memarea_free(struct rte_memarea *ma, void *ptr)\n+{\n+\tstruct memarea_objhdr *hdr, *prev, *next;\n+\n+\tif (ma == NULL || ptr == NULL) {\n+\t\trte_errno = EINVAL;\n+\t\treturn;\n+\t}\n+\n+\thdr = RTE_PTR_SUB(ptr, sizeof(struct memarea_objhdr));\n+\tif (!MEMAREA_OBJECT_IS_ALLOCATED(hdr)) {\n+\t\tRTE_MEMAREA_LOG(ERR, \"detect invalid object in %s!\", ma->init.name);\n+\t\trte_errno = EFAULT;\n+\t\treturn;\n+\t}\n+\tmemarea_check_cookie(ma, hdr, COOKIE_EXPECT_STATUS_ALLOCATED);\n+\n+\tmemarea_lock(ma);\n+\n+\t/** 1st: add to avail list. */\n+\tTAILQ_INSERT_HEAD(&ma->avail_list, hdr, avail_next);\n+\tmemarea_set_cookie(hdr, COOKIE_TARGET_STATUS_AVAILABLE);\n+\n+\t/** 2nd: merge if previous object is avail. */\n+\tprev = TAILQ_PREV(hdr, memarea_objhdr_list, obj_next);\n+\tif (prev != NULL && !MEMAREA_OBJECT_IS_ALLOCATED(prev)) {\n+\t\tmemarea_check_cookie(ma, prev, COOKIE_EXPECT_STATUS_AVAILABLE);\n+\t\tmemarea_merge_object(ma, prev, hdr);\n+\t\thdr = prev;\n+\t}\n+\n+\t/** 3rd: merge if next object is avail. */\n+\tnext = TAILQ_NEXT(hdr, obj_next);\n+\tif (next != NULL && !MEMAREA_OBJECT_IS_ALLOCATED(next)) {\n+\t\tmemarea_check_cookie(ma, next, COOKIE_EXPECT_STATUS_AVAILABLE);\n+\t\tmemarea_merge_object(ma, hdr, next);\n+\t}\n+\n+\tmemarea_unlock(ma);\n+}\ndiff --git a/lib/memarea/rte_memarea.h b/lib/memarea/rte_memarea.h\nindex 1d4381efd7..bb1bd5bae5 100644\n--- a/lib/memarea/rte_memarea.h\n+++ b/lib/memarea/rte_memarea.h\n@@ -134,6 +134,52 @@ struct rte_memarea *rte_memarea_create(const struct rte_memarea_param *init);\n __rte_experimental\n void rte_memarea_destroy(struct rte_memarea *ma);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Allocate memory from memarea.\n+ *\n+ * Allocate one memory object from the memarea.\n+ *\n+ * @param ma\n+ *   The pointer of memarea.\n+ * @param size\n+ *   The memory size to be allocated.\n+ *\n+ * @return\n+ *   - NULL on error. Not enough memory, or invalid arguments (see the\n+ *     rte_errno).\n+ *   - Otherwise, the pointer to the allocated object.\n+ *\n+ * @note The memory allocated is not guaranteed to be zeroed.\n+ */\n+__rte_experimental\n+void *rte_memarea_alloc(struct rte_memarea *ma, size_t size);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Free memory to memarea.\n+ *\n+ * Free one memory object to the memarea.\n+ * @note The memory object must have been returned by a previous call to\n+ * rte_memarea_alloc(), it must be freed to the same memarea which previous\n+ * allocated from. The behaviour of rte_memarea_free() is undefined if the\n+ * memarea or pointer does not match these requirements.\n+ *\n+ * @param ma\n+ *   The pointer of memarea. If the ma is NULL, the function does nothing.\n+ * @param ptr\n+ *   The pointer of memory object which need be freed. If the pointer is NULL,\n+ *   the function does nothing.\n+ *\n+ * @note The rte_errno is set if free failed.\n+ */\n+__rte_experimental\n+void rte_memarea_free(struct rte_memarea *ma, void *ptr);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/memarea/version.map b/lib/memarea/version.map\nindex f36a04d7cf..effbd0b488 100644\n--- a/lib/memarea/version.map\n+++ b/lib/memarea/version.map\n@@ -1,8 +1,10 @@\n EXPERIMENTAL {\n \tglobal:\n \n+\trte_memarea_alloc;\n \trte_memarea_create;\n \trte_memarea_destroy;\n+\trte_memarea_free;\n \n \tlocal: *;\n };\n",
    "prefixes": [
        "v17",
        "3/6"
    ]
}