get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 54420,
    "url": "http://patches.dpdk.org/api/patches/54420/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1559750328-22377-2-git-send-email-phil.yang@arm.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": "<1559750328-22377-2-git-send-email-phil.yang@arm.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1559750328-22377-2-git-send-email-phil.yang@arm.com",
    "date": "2019-06-05T15:58:46",
    "name": "[v1,1/3] eal/mcslock: add mcs queued lock implementation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "596562e4905110f26c4848a1c8ad8dcf27000d49",
    "submitter": {
        "id": 833,
        "url": "http://patches.dpdk.org/api/people/833/?format=api",
        "name": "Phil Yang",
        "email": "phil.yang@arm.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1559750328-22377-2-git-send-email-phil.yang@arm.com/mbox/",
    "series": [
        {
            "id": 4910,
            "url": "http://patches.dpdk.org/api/series/4910/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=4910",
            "date": "2019-06-05T15:58:45",
            "name": "MCS queued lock implementation",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/4910/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/54420/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/54420/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 8FBC01BBD8;\n\tWed,  5 Jun 2019 17:59:44 +0200 (CEST)",
            "from foss.arm.com (usa-sjc-mx-foss1.foss.arm.com [217.140.101.70])\n\tby dpdk.org (Postfix) with ESMTP id 29CD41BBD3\n\tfor <dev@dpdk.org>; Wed,  5 Jun 2019 17:59:42 +0200 (CEST)",
            "from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249])\n\tby usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7F88C15A2;\n\tWed,  5 Jun 2019 08:59:41 -0700 (PDT)",
            "from phil-VirtualBox.shanghai.arm.com (unknown [10.171.20.59])\n\tby usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id\n\t2284E3F246; Wed,  5 Jun 2019 08:59:39 -0700 (PDT)"
        ],
        "From": "Phil Yang <phil.yang@arm.com>",
        "To": "dev@dpdk.org",
        "Cc": "thomas@monjalon.net, jerinj@marvell.com, hemant.agrawal@nxp.com,\n\tHonnappa.Nagarahalli@arm.com, gavin.hu@arm.com, phil.yang@arm.com,\n\tnd@arm.com",
        "Date": "Wed,  5 Jun 2019 23:58:46 +0800",
        "Message-Id": "<1559750328-22377-2-git-send-email-phil.yang@arm.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1559750328-22377-1-git-send-email-phil.yang@arm.com>",
        "References": "<1559750328-22377-1-git-send-email-phil.yang@arm.com>",
        "Subject": "[dpdk-dev] [PATCH v1 1/3] eal/mcslock: add mcs queued lock\n\timplementation",
        "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://mails.dpdk.org/options/dev>,\n\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "If there are multiple threads contending, they all attempt to take the\nspinlock lock at the same time once it is released. This results in a\nhuge amount of processor bus traffic, which is a huge performance\nkiller. Thus, if we somehow order the lock-takers so that they know who\nis next in line for the resource we can vastly reduce the amount of bus\ntraffic.\n\nThis patch added MCS lock library. It provides scalability by spinning\non a CPU/thread local variable which avoids expensive cache bouncings.\nIt provides fairness by maintaining a list of acquirers and passing the\nlock to each CPU/thread in the order they acquired the lock.\n\nSigned-off-by: Phil Yang <phil.yang@arm.com>\nReviewed-by: Steve Capper <steve.capper@arm.com>\nReviewed-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>\n\n---\n MAINTAINERS                                        |   4 +\n doc/api/doxy-api-index.md                          |   1 +\n doc/guides/rel_notes/release_19_08.rst             |   6 +\n lib/librte_eal/common/Makefile                     |   2 +-\n .../common/include/generic/rte_mcslock.h           | 169 +++++++++++++++++++++\n lib/librte_eal/common/meson.build                  |   1 +\n 6 files changed, 182 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_eal/common/include/generic/rte_mcslock.h",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 15d0829..1390238 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -222,6 +222,10 @@ M: Joyce Kong <joyce.kong@arm.com>\n F: lib/librte_eal/common/include/generic/rte_ticketlock.h\n F: app/test/test_ticketlock.c\n \n+MCSlock - EXPERIMENTAL\n+M: Phil Yang <phil.yang@arm.com>\n+F: lib/librte_eal/common/include/generic/rte_mcslock.h\n+\n ARM v7\n M: Jan Viktorin <viktorin@rehivetech.com>\n M: Gavin Hu <gavin.hu@arm.com>\ndiff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md\nindex 715248d..d0e32b1 100644\n--- a/doc/api/doxy-api-index.md\n+++ b/doc/api/doxy-api-index.md\n@@ -63,6 +63,7 @@ The public API headers are grouped by topics:\n \n - **locks**:\n   [atomic]             (@ref rte_atomic.h),\n+  [mcslock]            (@ref rte_mcslock.h),\n   [rwlock]             (@ref rte_rwlock.h),\n   [spinlock]           (@ref rte_spinlock.h),\n   [ticketlock]         (@ref rte_ticketlock.h),\ndiff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst\nindex a17e7de..ebd5105 100644\n--- a/doc/guides/rel_notes/release_19_08.rst\n+++ b/doc/guides/rel_notes/release_19_08.rst\n@@ -54,6 +54,12 @@ New Features\n      Also, make sure to start the actual text at the margin.\n      =========================================================\n \n+* **Added MCS lock library.**\n+\n+  Added MCS lock library. It provides scalability by spinning on a\n+  CPU/thread local variable which avoids expensive cache bouncings.\n+  It provides fairness by maintaining a list of acquirers and passing\n+  the lock to each CPU/thread in the order they acquired the lock.\n \n Removed Items\n -------------\ndiff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile\nindex 1647af7..a00d4fc 100644\n--- a/lib/librte_eal/common/Makefile\n+++ b/lib/librte_eal/common/Makefile\n@@ -21,7 +21,7 @@ INC += rte_reciprocal.h rte_fbarray.h rte_uuid.h\n \n GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h\n GENERIC_INC += rte_memcpy.h rte_cpuflags.h\n-GENERIC_INC += rte_spinlock.h rte_rwlock.h rte_ticketlock.h\n+GENERIC_INC += rte_mcslock.h rte_spinlock.h rte_rwlock.h rte_ticketlock.h\n GENERIC_INC += rte_vect.h rte_pause.h rte_io.h\n \n # defined in mk/arch/$(RTE_ARCH)/rte.vars.mk\ndiff --git a/lib/librte_eal/common/include/generic/rte_mcslock.h b/lib/librte_eal/common/include/generic/rte_mcslock.h\nnew file mode 100644\nindex 0000000..20e9bb8\n--- /dev/null\n+++ b/lib/librte_eal/common/include/generic/rte_mcslock.h\n@@ -0,0 +1,169 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Arm Limited\n+ */\n+\n+#ifndef _RTE_MCSLOCK_H_\n+#define _RTE_MCSLOCK_H_\n+\n+/**\n+ * @file\n+ *\n+ * RTE MCS lock\n+ *\n+ * This file defines the main data structure and APIs for MCS queued lock.\n+ *\n+ * The MCS lock (proposed by JOHN M. MELLOR-CRUMMEY and MICHAEL L. SCOTT)\n+ * provides scalability by spinning on a CPU/thread local variable which\n+ * avoids expensive cache bouncings. It provides fairness by maintaining\n+ * a list of acquirers and passing the lock to each CPU/thread in the order\n+ * they acquired the lock.\n+ */\n+\n+#include <rte_lcore.h>\n+#include <rte_common.h>\n+#include <rte_pause.h>\n+\n+/**\n+ * The rte_mcslock_t type.\n+ */\n+typedef struct rte_mcslock {\n+\tstruct rte_mcslock *next;\n+\tint locked; /* 1 if the queue locked, 0 otherwise */\n+} rte_mcslock_t;\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: This API may change without prior notice\n+ *\n+ * Take the MCS lock.\n+ *\n+ * @param msl\n+ *   A pointer to the pointer of a MCS lock.\n+ *   When the lock is initialized or declared, the msl pointer should be\n+ *   set to NULL.\n+ * @param me\n+ *   A pointer to a new node of MCS lock. Each CPU/thread acquiring the\n+ *   lock should use its 'own node'.\n+ */\n+static inline __rte_experimental void\n+rte_mcslock_lock(rte_mcslock_t **msl, rte_mcslock_t *me)\n+{\n+\trte_mcslock_t *prev;\n+\n+\t/* Init me node */\n+\t__atomic_store_n(&me->next, NULL, __ATOMIC_RELAXED);\n+\n+\t/* If the queue is empty, the exchange operation is enough to acquire\n+\t * the lock. Hence, the exchange operation requires acquire semantics.\n+\t * The store to me->next above should complete before the node is\n+\t * visible to other CPUs/threads. Hence, the exchange operation requires\n+\t * release semantics as well.\n+\t */\n+\tprev = __atomic_exchange_n(msl, me, __ATOMIC_ACQ_REL);\n+\tif (likely(prev == NULL)) {\n+\t\t/* Queue was empty, no further action required,\n+\t\t * proceed with lock taken.\n+\t\t */\n+\t\treturn;\n+\t}\n+\t__atomic_store_n(&me->locked, 1, __ATOMIC_RELAXED);\n+\t__atomic_store_n(&prev->next, me, __ATOMIC_RELAXED);\n+\n+\t/* The while-load of me->locked should not move above the previous\n+\t * store to prev->next. Otherwise it will cause a deadlock. Need a\n+\t * store-load barrier.\n+\t */\n+\t__atomic_thread_fence(__ATOMIC_ACQ_REL);\n+\t/* If the lock has already been acquired, it first atomically\n+\t * places the node at the end of the queue and then proceeds\n+\t * to spin on me->locked until the previous lock holder resets\n+\t * the me->locked using mcslock_unlock().\n+\t */\n+\twhile (__atomic_load_n(&me->locked, __ATOMIC_ACQUIRE))\n+\t\trte_pause();\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: This API may change without prior notice\n+ *\n+ * Release the MCS lock.\n+ *\n+ * @param msl\n+ *   A pointer to the pointer of a MCS lock.\n+ * @param me\n+ *   A pointer to the node of MCS lock passed in rte_mcslock_lock.\n+ */\n+static inline __rte_experimental void\n+rte_mcslock_unlock(rte_mcslock_t **msl, rte_mcslock_t *me)\n+{\n+\t/* Check if there are more nodes in the queue. */\n+\tif (likely(__atomic_load_n(&me->next, __ATOMIC_RELAXED) == NULL)) {\n+\t\t/* No, last member in the queue. */\n+\t\trte_mcslock_t *save_me = __atomic_load_n(&me, __ATOMIC_RELAXED);\n+\n+\t\t/* Release the lock by setting it to NULL */\n+\t\tif (likely(__atomic_compare_exchange_n(msl, &save_me, NULL, 0,\n+\t\t\t\t__ATOMIC_RELEASE, __ATOMIC_RELAXED)))\n+\t\t\treturn;\n+\t\t/* More nodes added to the queue by other CPUs.\n+\t\t * Wait until the next pointer is set.\n+\t\t */\n+\t\twhile (__atomic_load_n(&me->next, __ATOMIC_RELAXED) == NULL)\n+\t\t\trte_pause();\n+\t}\n+\n+\t/* Pass lock to next waiter. */\n+\t__atomic_store_n(&me->next->locked, 0, __ATOMIC_RELEASE);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: This API may change without prior notice\n+ *\n+ * Try to take the lock.\n+ *\n+ * @param msl\n+ *   A pointer to the pointer of a MCS lock.\n+ * @param me\n+ *   A pointer to a new node of MCS lock.\n+ * @return\n+ *   1 if the lock is successfully taken; 0 otherwise.\n+ */\n+static inline __rte_experimental int\n+rte_mcslock_trylock(rte_mcslock_t **msl, rte_mcslock_t *me)\n+{\n+\t/* Init me node */\n+\t__atomic_store_n(&me->next, NULL, __ATOMIC_RELAXED);\n+\n+\t/* Try to lock */\n+\trte_mcslock_t *expected = NULL;\n+\n+\t/* The lock can be taken only when the queue is empty. Hence,\n+\t * the compare-exchange operation requires acquire semantics.\n+\t * The store to me->next above should complete before the node\n+\t * is visible to other CPUs/threads. Hence, the compare-exchange\n+\t * operation requires release semantics as well.\n+\t */\n+\treturn __atomic_compare_exchange_n(msl, &expected, me, 0,\n+\t\t\t__ATOMIC_ACQ_REL, __ATOMIC_RELAXED);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: This API may change without prior notice\n+ *\n+ * Test if the lock is taken.\n+ *\n+ * @param msl\n+ *   A pointer to a MCS lock node.\n+ * @return\n+ *   1 if the lock is currently taken; 0 otherwise.\n+ */\n+static inline __rte_experimental int\n+rte_mcslock_is_locked(rte_mcslock_t *msl)\n+{\n+\treturn (__atomic_load_n(&msl, __ATOMIC_RELAXED) != NULL);\n+}\n+\n+#endif /* _RTE_MCSLOCK_H_ */\ndiff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build\nindex 0670e41..f74db29 100644\n--- a/lib/librte_eal/common/meson.build\n+++ b/lib/librte_eal/common/meson.build\n@@ -94,6 +94,7 @@ generic_headers = files(\n \t'include/generic/rte_cpuflags.h',\n \t'include/generic/rte_cycles.h',\n \t'include/generic/rte_io.h',\n+\t'include/generic/rte_mcslock.h',\n \t'include/generic/rte_memcpy.h',\n \t'include/generic/rte_pause.h',\n \t'include/generic/rte_prefetch.h',\n",
    "prefixes": [
        "v1",
        "1/3"
    ]
}