get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 123214,
    "url": "http://patchwork.dpdk.org/api/patches/123214/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230207104532.2370869-2-david.marchand@redhat.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20230207104532.2370869-2-david.marchand@redhat.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230207104532.2370869-2-david.marchand@redhat.com",
    "date": "2023-02-07T10:45:24",
    "name": "[v6,1/9] eal: annotate spinlock, rwlock and seqlock",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "cbedeb4d9487ca2f2bc3927f23683fbe54d51bce",
    "submitter": {
        "id": 1173,
        "url": "http://patchwork.dpdk.org/api/people/1173/?format=api",
        "name": "David Marchand",
        "email": "david.marchand@redhat.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20230207104532.2370869-2-david.marchand@redhat.com/mbox/",
    "series": [
        {
            "id": 26843,
            "url": "http://patchwork.dpdk.org/api/series/26843/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=26843",
            "date": "2023-02-07T10:45:23",
            "name": "Lock annotations",
            "version": 6,
            "mbox": "http://patchwork.dpdk.org/series/26843/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/123214/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/123214/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 DC26141C2D;\n\tTue,  7 Feb 2023 11:45:52 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id BFD6F4282D;\n\tTue,  7 Feb 2023 11:45:52 +0100 (CET)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by mails.dpdk.org (Postfix) with ESMTP id B6A1D40042\n for <dev@dpdk.org>; Tue,  7 Feb 2023 11:45:51 +0100 (CET)",
            "from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com\n [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n us-mta-70-_rUDxvbKN6iX1ziYK3rwBQ-1; Tue, 07 Feb 2023 05:45:46 -0500",
            "from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com\n [10.11.54.8])\n (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n (No client certificate requested)\n by mimecast-mx02.redhat.com (Postfix) with ESMTPS id ADB352932488;\n Tue,  7 Feb 2023 10:45:45 +0000 (UTC)",
            "from dmarchan.redhat.com (ovpn-195-46.brq.redhat.com [10.40.195.46])\n by smtp.corp.redhat.com (Postfix) with ESMTP id 26568C15BA0;\n Tue,  7 Feb 2023 10:45:43 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1675766751;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=KfrSfjin3JAU8NqN1oy5MyRhMeTWyT3DX8RYXh24LRU=;\n b=gT7J53pJMbUwYZAvWL1VEzWXNr6axeyxqNp9TkUscAUQt8D16iVT7VAEAevT0eoftC9UaE\n 4o6evQ08uWja3MUxZ1c83JO3sr6VXSp9CRtJQnqsBtqme7t09NV6S8XgrbH2uOtbUmaHuX\n 4okAuV9tdQmqGTRYWCShvmCYZiY0ysA=",
        "X-MC-Unique": "_rUDxvbKN6iX1ziYK3rwBQ-1",
        "From": "David Marchand <david.marchand@redhat.com>",
        "To": "dev@dpdk.org",
        "Cc": "maxime.coquelin@redhat.com, stephen@networkplumber.org,\n chenbo.xia@intel.com, jiayu.hu@intel.com, yuanx.wang@intel.com,\n xuan.ding@intel.com, mb@smartsharesystems.com,\n Anatoly Burakov <anatoly.burakov@intel.com>, =?utf-8?q?Mattias_R=C3=B6nnblo?=\n\t=?utf-8?q?m?= <mattias.ronnblom@ericsson.com>,\n David Christensen <drc@linux.vnet.ibm.com>,\n Bruce Richardson <bruce.richardson@intel.com>,\n Konstantin Ananyev <konstantin.v.ananyev@yandex.ru>",
        "Subject": "[PATCH v6 1/9] eal: annotate spinlock, rwlock and seqlock",
        "Date": "Tue,  7 Feb 2023 11:45:24 +0100",
        "Message-Id": "<20230207104532.2370869-2-david.marchand@redhat.com>",
        "In-Reply-To": "<20230207104532.2370869-1-david.marchand@redhat.com>",
        "References": "<20220328121758.26632-1-david.marchand@redhat.com>\n <20230207104532.2370869-1-david.marchand@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.1 on 10.11.54.8",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "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": "clang offers some thread safety checks, statically verifying that locks\nare taken and released in the code.\nTo use those checks, the full code leading to taking or releasing locks\nmust be annotated with some attributes.\n\nWrap those attributes into our own set of macros.\n\nrwlock, seqlock and the \"normal\" spinlock are instrumented.\n\nThose checks might be of interest out of DPDK, but it requires that the\nincluding application locks are annotated.\nOn the other hand, applications out there might have been using\nthose same checks.\nTo be on the safe side, keep this instrumentation under a\nRTE_ANNOTATE_LOCKS internal build flag.\n\nA component may en/disable this check by setting\nannotate_locks = true/false in its meson.build.\n\nNote:\nDoxygen preprocessor does not understand trailing function attributes\n(this can be observed with the rte_seqlock.h header).\nOne would think that expanding the annotation macros to a noop in\nrte_lock_annotations.h would be enough (since RTE_ANNOTATE_LOCKS is not\nset during doxygen processing)). Unfortunately, the use of\nEXPAND_ONLY_PREDEF defeats this.\n\nRemoving EXPAND_ONLY_PREDEF entirely is not an option as it would expand\nall other DPDK macros.\n\nThe chosen solution is to expand the annotation macros explicitly to a\nnoop in PREDEFINED.\n\nSigned-off-by: David Marchand <david.marchand@redhat.com>\nAcked-by: Morten Brørup <mb@smartsharesystems.com>\nReviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>\n---\nChanges since v4:\n- hid annotations from Doxygen,\n- fixed typos,\n\nChanges since RFC v3:\n- rebased,\n- added some documentation,\n- added assert attribute,\n- instrumented seqlock,\n- cleaned annotations in arch-specific headers,\n\nChanges since RFC v2:\n- fixed rwlock trylock,\n- instrumented _tm spinlocks,\n- aligned attribute names to clang,\n\n---\n doc/api/doxy-api.conf.in                      | 11 +++\n .../prog_guide/env_abstraction_layer.rst      | 24 ++++++\n doc/guides/rel_notes/release_23_03.rst        |  5 ++\n drivers/meson.build                           |  5 ++\n lib/eal/include/generic/rte_rwlock.h          | 27 +++++--\n lib/eal/include/generic/rte_spinlock.h        | 31 +++++---\n lib/eal/include/meson.build                   |  1 +\n lib/eal/include/rte_lock_annotations.h        | 73 +++++++++++++++++++\n lib/eal/include/rte_seqlock.h                 |  2 +\n lib/eal/ppc/include/rte_spinlock.h            |  3 +\n lib/eal/x86/include/rte_rwlock.h              |  4 +\n lib/eal/x86/include/rte_spinlock.h            |  9 +++\n lib/meson.build                               |  5 ++\n 13 files changed, 186 insertions(+), 14 deletions(-)\n create mode 100644 lib/eal/include/rte_lock_annotations.h",
    "diff": "diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in\nindex f0886c3bd1..e859426099 100644\n--- a/doc/api/doxy-api.conf.in\n+++ b/doc/api/doxy-api.conf.in\n@@ -84,6 +84,17 @@ FILE_PATTERNS           = rte_*.h \\\n PREDEFINED              = __DOXYGEN__ \\\n                           RTE_HAS_CPUSET \\\n                           VFIO_PRESENT \\\n+                          __rte_lockable= \\\n+                          __rte_guarded_by(x)= \\\n+                          __rte_exclusive_locks_required(x)= \\\n+                          __rte_exclusive_lock_function(x)= \\\n+                          __rte_exclusive_trylock_function(x)= \\\n+                          __rte_assert_exclusive_lock(x)= \\\n+                          __rte_shared_locks_required(x)= \\\n+                          __rte_shared_lock_function(x)= \\\n+                          __rte_shared_trylock_function(x)= \\\n+                          __rte_assert_shared_lock(x)= \\\n+                          __rte_unlock_function(x)= \\\n                           __attribute__(x)=\n \n OPTIMIZE_OUTPUT_FOR_C   = YES\ndiff --git a/doc/guides/prog_guide/env_abstraction_layer.rst b/doc/guides/prog_guide/env_abstraction_layer.rst\nindex 35fbebe1be..3f33621e05 100644\n--- a/doc/guides/prog_guide/env_abstraction_layer.rst\n+++ b/doc/guides/prog_guide/env_abstraction_layer.rst\n@@ -529,6 +529,30 @@ Misc Functions\n \n Locks and atomic operations are per-architecture (i686 and x86_64).\n \n+Lock annotations\n+~~~~~~~~~~~~~~~~\n+\n+R/W locks, seq locks and spinlocks have been instrumented to help developers in\n+catching issues in DPDK.\n+\n+This instrumentation relies on\n+`clang Thread Safety checks <https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_.\n+All attributes are prefixed with __rte and are fully described in the clang\n+documentation.\n+\n+Some general comments:\n+\n+- it is important that lock requirements are expressed at the function\n+  declaration level in headers so that other code units can be inspected,\n+- when some global lock is necessary to some user-exposed API, it is preferred\n+  to expose it via an internal helper rather than expose the global variable,\n+- there are a list of known limitations with clang instrumentation, but before\n+  waiving checks with ``__rte_no_thread_safety_analysis`` in your code, please\n+  discuss it on the mailing list,\n+\n+A DPDK library/driver can enable/disable the checks by setting\n+``annotate_locks`` accordingly in its ``meson.build`` file.\n+\n IOVA Mode Detection\n ~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst\nindex 1fa101c420..bf90feba68 100644\n--- a/doc/guides/rel_notes/release_23_03.rst\n+++ b/doc/guides/rel_notes/release_23_03.rst\n@@ -55,6 +55,11 @@ New Features\n      Also, make sure to start the actual text at the margin.\n      =======================================================\n \n+* **Introduced lock annotations.**\n+\n+  Added lock annotations attributes so that clang can statically analyze lock\n+  correctness.\n+\n * **Updated AMD axgbe driver.**\n \n   * Added multi-process support.\ndiff --git a/drivers/meson.build b/drivers/meson.build\nindex c6d619200f..bddc4a6cc4 100644\n--- a/drivers/meson.build\n+++ b/drivers/meson.build\n@@ -91,6 +91,7 @@ foreach subpath:subdirs\n         build = true # set to false to disable, e.g. missing deps\n         reason = '<unknown reason>' # set if build == false to explain\n         name = drv\n+        annotate_locks = false\n         sources = []\n         headers = []\n         driver_sdk_headers = [] # public headers included by drivers\n@@ -167,6 +168,10 @@ foreach subpath:subdirs\n         enabled_drivers += name\n         lib_name = '_'.join(['rte', class, name])\n         cflags += '-DRTE_LOG_DEFAULT_LOGTYPE=' + '.'.join([log_prefix, name])\n+        if annotate_locks and cc.has_argument('-Wthread-safety')\n+            cflags += '-DRTE_ANNOTATE_LOCKS'\n+            cflags += '-Wthread-safety'\n+        endif\n         dpdk_conf.set(lib_name.to_upper(), 1)\n \n         dpdk_extra_ldflags += pkgconfig_extra_libs\ndiff --git a/lib/eal/include/generic/rte_rwlock.h b/lib/eal/include/generic/rte_rwlock.h\nindex 233d4262be..d45c22c189 100644\n--- a/lib/eal/include/generic/rte_rwlock.h\n+++ b/lib/eal/include/generic/rte_rwlock.h\n@@ -30,6 +30,7 @@ extern \"C\" {\n \n #include <rte_branch_prediction.h>\n #include <rte_common.h>\n+#include <rte_lock_annotations.h>\n #include <rte_pause.h>\n \n /**\n@@ -55,7 +56,7 @@ extern \"C\" {\n \t\t\t\t/* Writer is waiting or has lock */\n #define RTE_RWLOCK_READ\t 0x4\t/* Reader increment */\n \n-typedef struct {\n+typedef struct __rte_lockable {\n \tint32_t cnt;\n } rte_rwlock_t;\n \n@@ -84,6 +85,8 @@ rte_rwlock_init(rte_rwlock_t *rwl)\n  */\n static inline void\n rte_rwlock_read_lock(rte_rwlock_t *rwl)\n+\t__rte_shared_lock_function(rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint32_t x;\n \n@@ -119,6 +122,8 @@ rte_rwlock_read_lock(rte_rwlock_t *rwl)\n  */\n static inline int\n rte_rwlock_read_trylock(rte_rwlock_t *rwl)\n+\t__rte_shared_trylock_function(0, rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint32_t x;\n \n@@ -150,6 +155,8 @@ rte_rwlock_read_trylock(rte_rwlock_t *rwl)\n  */\n static inline void\n rte_rwlock_read_unlock(rte_rwlock_t *rwl)\n+\t__rte_unlock_function(rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \t__atomic_fetch_sub(&rwl->cnt, RTE_RWLOCK_READ, __ATOMIC_RELEASE);\n }\n@@ -166,6 +173,8 @@ rte_rwlock_read_unlock(rte_rwlock_t *rwl)\n  */\n static inline int\n rte_rwlock_write_trylock(rte_rwlock_t *rwl)\n+\t__rte_exclusive_trylock_function(0, rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint32_t x;\n \n@@ -186,6 +195,8 @@ rte_rwlock_write_trylock(rte_rwlock_t *rwl)\n  */\n static inline void\n rte_rwlock_write_lock(rte_rwlock_t *rwl)\n+\t__rte_exclusive_lock_function(rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint32_t x;\n \n@@ -219,6 +230,8 @@ rte_rwlock_write_lock(rte_rwlock_t *rwl)\n  */\n static inline void\n rte_rwlock_write_unlock(rte_rwlock_t *rwl)\n+\t__rte_unlock_function(rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \t__atomic_fetch_sub(&rwl->cnt, RTE_RWLOCK_WRITE, __ATOMIC_RELEASE);\n }\n@@ -237,7 +250,8 @@ rte_rwlock_write_unlock(rte_rwlock_t *rwl)\n  *   A pointer to a rwlock structure.\n  */\n static inline void\n-rte_rwlock_read_lock_tm(rte_rwlock_t *rwl);\n+rte_rwlock_read_lock_tm(rte_rwlock_t *rwl)\n+\t__rte_shared_lock_function(rwl);\n \n /**\n  * Commit hardware memory transaction or release the read lock if the lock is used as a fall-back\n@@ -246,7 +260,8 @@ rte_rwlock_read_lock_tm(rte_rwlock_t *rwl);\n  *   A pointer to the rwlock structure.\n  */\n static inline void\n-rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl);\n+rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl)\n+\t__rte_unlock_function(rwl);\n \n /**\n  * Try to execute critical section in a hardware memory transaction, if it\n@@ -262,7 +277,8 @@ rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl);\n  *   A pointer to a rwlock structure.\n  */\n static inline void\n-rte_rwlock_write_lock_tm(rte_rwlock_t *rwl);\n+rte_rwlock_write_lock_tm(rte_rwlock_t *rwl)\n+\t__rte_exclusive_lock_function(rwl);\n \n /**\n  * Commit hardware memory transaction or release the write lock if the lock is used as a fall-back\n@@ -271,7 +287,8 @@ rte_rwlock_write_lock_tm(rte_rwlock_t *rwl);\n  *   A pointer to a rwlock structure.\n  */\n static inline void\n-rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl);\n+rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl)\n+\t__rte_unlock_function(rwl);\n \n #ifdef __cplusplus\n }\ndiff --git a/lib/eal/include/generic/rte_spinlock.h b/lib/eal/include/generic/rte_spinlock.h\nindex 73ed4bfbdc..8ca47bbfaa 100644\n--- a/lib/eal/include/generic/rte_spinlock.h\n+++ b/lib/eal/include/generic/rte_spinlock.h\n@@ -22,12 +22,13 @@\n #ifdef RTE_FORCE_INTRINSICS\n #include <rte_common.h>\n #endif\n+#include <rte_lock_annotations.h>\n #include <rte_pause.h>\n \n /**\n  * The rte_spinlock_t type.\n  */\n-typedef struct {\n+typedef struct __rte_lockable {\n \tvolatile int locked; /**< lock status 0 = unlocked, 1 = locked */\n } rte_spinlock_t;\n \n@@ -55,11 +56,13 @@ rte_spinlock_init(rte_spinlock_t *sl)\n  *   A pointer to the spinlock.\n  */\n static inline void\n-rte_spinlock_lock(rte_spinlock_t *sl);\n+rte_spinlock_lock(rte_spinlock_t *sl)\n+\t__rte_exclusive_lock_function(sl);\n \n #ifdef RTE_FORCE_INTRINSICS\n static inline void\n rte_spinlock_lock(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint exp = 0;\n \n@@ -79,11 +82,13 @@ rte_spinlock_lock(rte_spinlock_t *sl)\n  *   A pointer to the spinlock.\n  */\n static inline void\n-rte_spinlock_unlock (rte_spinlock_t *sl);\n+rte_spinlock_unlock(rte_spinlock_t *sl)\n+\t__rte_unlock_function(sl);\n \n #ifdef RTE_FORCE_INTRINSICS\n static inline void\n-rte_spinlock_unlock (rte_spinlock_t *sl)\n+rte_spinlock_unlock(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \t__atomic_store_n(&sl->locked, 0, __ATOMIC_RELEASE);\n }\n@@ -99,11 +104,13 @@ rte_spinlock_unlock (rte_spinlock_t *sl)\n  */\n __rte_warn_unused_result\n static inline int\n-rte_spinlock_trylock (rte_spinlock_t *sl);\n+rte_spinlock_trylock(rte_spinlock_t *sl)\n+\t__rte_exclusive_trylock_function(1, sl);\n \n #ifdef RTE_FORCE_INTRINSICS\n static inline int\n-rte_spinlock_trylock (rte_spinlock_t *sl)\n+rte_spinlock_trylock(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint exp = 0;\n \treturn __atomic_compare_exchange_n(&sl->locked, &exp, 1,\n@@ -147,7 +154,8 @@ static inline int rte_tm_supported(void);\n  *   A pointer to the spinlock.\n  */\n static inline void\n-rte_spinlock_lock_tm(rte_spinlock_t *sl);\n+rte_spinlock_lock_tm(rte_spinlock_t *sl)\n+\t__rte_exclusive_lock_function(sl);\n \n /**\n  * Commit hardware memory transaction or release the spinlock if\n@@ -157,7 +165,8 @@ rte_spinlock_lock_tm(rte_spinlock_t *sl);\n  *   A pointer to the spinlock.\n  */\n static inline void\n-rte_spinlock_unlock_tm(rte_spinlock_t *sl);\n+rte_spinlock_unlock_tm(rte_spinlock_t *sl)\n+\t__rte_unlock_function(sl);\n \n /**\n  * Try to execute critical section in a hardware memory transaction,\n@@ -177,7 +186,8 @@ rte_spinlock_unlock_tm(rte_spinlock_t *sl);\n  */\n __rte_warn_unused_result\n static inline int\n-rte_spinlock_trylock_tm(rte_spinlock_t *sl);\n+rte_spinlock_trylock_tm(rte_spinlock_t *sl)\n+\t__rte_exclusive_trylock_function(1, sl);\n \n /**\n  * The rte_spinlock_recursive_t type.\n@@ -213,6 +223,7 @@ static inline void rte_spinlock_recursive_init(rte_spinlock_recursive_t *slr)\n  *   A pointer to the recursive spinlock.\n  */\n static inline void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr)\n+\t__rte_no_thread_safety_analysis\n {\n \tint id = rte_gettid();\n \n@@ -229,6 +240,7 @@ static inline void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr)\n  *   A pointer to the recursive spinlock.\n  */\n static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (--(slr->count) == 0) {\n \t\tslr->user = -1;\n@@ -247,6 +259,7 @@ static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)\n  */\n __rte_warn_unused_result\n static inline int rte_spinlock_recursive_trylock(rte_spinlock_recursive_t *slr)\n+\t__rte_no_thread_safety_analysis\n {\n \tint id = rte_gettid();\n \ndiff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build\nindex cfcd40aaed..b0db9b3b3a 100644\n--- a/lib/eal/include/meson.build\n+++ b/lib/eal/include/meson.build\n@@ -27,6 +27,7 @@ headers += files(\n         'rte_keepalive.h',\n         'rte_launch.h',\n         'rte_lcore.h',\n+        'rte_lock_annotations.h',\n         'rte_log.h',\n         'rte_malloc.h',\n         'rte_mcslock.h',\ndiff --git a/lib/eal/include/rte_lock_annotations.h b/lib/eal/include/rte_lock_annotations.h\nnew file mode 100644\nindex 0000000000..9fc50082d6\n--- /dev/null\n+++ b/lib/eal/include/rte_lock_annotations.h\n@@ -0,0 +1,73 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2022 Red Hat, Inc.\n+ */\n+\n+#ifndef RTE_LOCK_ANNOTATIONS_H\n+#define RTE_LOCK_ANNOTATIONS_H\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#ifdef RTE_ANNOTATE_LOCKS\n+\n+#define __rte_lockable \\\n+\t__attribute__((lockable))\n+\n+#define __rte_guarded_by(...) \\\n+\t__attribute__((guarded_by(__VA_ARGS__)))\n+#define __rte_guarded_var \\\n+\t__attribute__((guarded_var))\n+\n+#define __rte_exclusive_locks_required(...) \\\n+\t__attribute__((exclusive_locks_required(__VA_ARGS__)))\n+#define __rte_exclusive_lock_function(...) \\\n+\t__attribute__((exclusive_lock_function(__VA_ARGS__)))\n+#define __rte_exclusive_trylock_function(ret, ...) \\\n+\t__attribute__((exclusive_trylock_function(ret, __VA_ARGS__)))\n+#define __rte_assert_exclusive_lock(...) \\\n+\t__attribute__((assert_exclusive_lock(__VA_ARGS__)))\n+\n+#define __rte_shared_locks_required(...) \\\n+\t__attribute__((shared_locks_required(__VA_ARGS__)))\n+#define __rte_shared_lock_function(...) \\\n+\t__attribute__((shared_lock_function(__VA_ARGS__)))\n+#define __rte_shared_trylock_function(ret, ...) \\\n+\t__attribute__((shared_trylock_function(ret, __VA_ARGS__)))\n+#define __rte_assert_shared_lock(...) \\\n+\t__attribute__((assert_shared_lock(__VA_ARGS__)))\n+\n+#define __rte_unlock_function(...) \\\n+\t__attribute__((unlock_function(__VA_ARGS__)))\n+\n+#define __rte_no_thread_safety_analysis \\\n+\t__attribute__((no_thread_safety_analysis))\n+\n+#else /* ! RTE_ANNOTATE_LOCKS */\n+\n+#define __rte_lockable\n+\n+#define __rte_guarded_by(...)\n+#define __rte_guarded_var\n+\n+#define __rte_exclusive_locks_required(...)\n+#define __rte_exclusive_lock_function(...)\n+#define __rte_exclusive_trylock_function(...)\n+#define __rte_assert_exclusive_lock(...)\n+\n+#define __rte_shared_locks_required(...)\n+#define __rte_shared_lock_function(...)\n+#define __rte_shared_trylock_function(...)\n+#define __rte_assert_shared_lock(...)\n+\n+#define __rte_unlock_function(...)\n+\n+#define __rte_no_thread_safety_analysis\n+\n+#endif /* RTE_ANNOTATE_LOCKS */\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* RTE_LOCK_ANNOTATIONS_H */\ndiff --git a/lib/eal/include/rte_seqlock.h b/lib/eal/include/rte_seqlock.h\nindex 1663af62e8..fcbb9c5866 100644\n--- a/lib/eal/include/rte_seqlock.h\n+++ b/lib/eal/include/rte_seqlock.h\n@@ -215,6 +215,7 @@ rte_seqlock_read_retry(const rte_seqlock_t *seqlock, uint32_t begin_sn)\n __rte_experimental\n static inline void\n rte_seqlock_write_lock(rte_seqlock_t *seqlock)\n+\t__rte_exclusive_lock_function(&seqlock->lock)\n {\n \t/* To synchronize with other writers. */\n \trte_spinlock_lock(&seqlock->lock);\n@@ -240,6 +241,7 @@ rte_seqlock_write_lock(rte_seqlock_t *seqlock)\n __rte_experimental\n static inline void\n rte_seqlock_write_unlock(rte_seqlock_t *seqlock)\n+\t__rte_unlock_function(&seqlock->lock)\n {\n \trte_seqcount_write_end(&seqlock->count);\n \ndiff --git a/lib/eal/ppc/include/rte_spinlock.h b/lib/eal/ppc/include/rte_spinlock.h\nindex 149ec245c7..3a4c905b22 100644\n--- a/lib/eal/ppc/include/rte_spinlock.h\n+++ b/lib/eal/ppc/include/rte_spinlock.h\n@@ -20,6 +20,7 @@ extern \"C\" {\n \n static inline void\n rte_spinlock_lock(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \twhile (__sync_lock_test_and_set(&sl->locked, 1))\n \t\twhile (sl->locked)\n@@ -28,12 +29,14 @@ rte_spinlock_lock(rte_spinlock_t *sl)\n \n static inline void\n rte_spinlock_unlock(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \t__sync_lock_release(&sl->locked);\n }\n \n static inline int\n rte_spinlock_trylock(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \treturn __sync_lock_test_and_set(&sl->locked, 1) == 0;\n }\ndiff --git a/lib/eal/x86/include/rte_rwlock.h b/lib/eal/x86/include/rte_rwlock.h\nindex eec4c7123c..1796b69265 100644\n--- a/lib/eal/x86/include/rte_rwlock.h\n+++ b/lib/eal/x86/include/rte_rwlock.h\n@@ -14,6 +14,7 @@ extern \"C\" {\n \n static inline void\n rte_rwlock_read_lock_tm(rte_rwlock_t *rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (likely(rte_try_tm(&rwl->cnt)))\n \t\treturn;\n@@ -22,6 +23,7 @@ rte_rwlock_read_lock_tm(rte_rwlock_t *rwl)\n \n static inline void\n rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (unlikely(rwl->cnt))\n \t\trte_rwlock_read_unlock(rwl);\n@@ -31,6 +33,7 @@ rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl)\n \n static inline void\n rte_rwlock_write_lock_tm(rte_rwlock_t *rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (likely(rte_try_tm(&rwl->cnt)))\n \t\treturn;\n@@ -39,6 +42,7 @@ rte_rwlock_write_lock_tm(rte_rwlock_t *rwl)\n \n static inline void\n rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (unlikely(rwl->cnt))\n \t\trte_rwlock_write_unlock(rwl);\ndiff --git a/lib/eal/x86/include/rte_spinlock.h b/lib/eal/x86/include/rte_spinlock.h\nindex e2e2b2643c..0b20ddfd73 100644\n--- a/lib/eal/x86/include/rte_spinlock.h\n+++ b/lib/eal/x86/include/rte_spinlock.h\n@@ -23,6 +23,7 @@ extern \"C\" {\n #ifndef RTE_FORCE_INTRINSICS\n static inline void\n rte_spinlock_lock(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint lock_val = 1;\n \tasm volatile (\n@@ -43,6 +44,7 @@ rte_spinlock_lock(rte_spinlock_t *sl)\n \n static inline void\n rte_spinlock_unlock (rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint unlock_val = 0;\n \tasm volatile (\n@@ -54,6 +56,7 @@ rte_spinlock_unlock (rte_spinlock_t *sl)\n \n static inline int\n rte_spinlock_trylock (rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tint lockval = 1;\n \n@@ -121,6 +124,7 @@ rte_try_tm(volatile int *lock)\n \n static inline void\n rte_spinlock_lock_tm(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (likely(rte_try_tm(&sl->locked)))\n \t\treturn;\n@@ -130,6 +134,7 @@ rte_spinlock_lock_tm(rte_spinlock_t *sl)\n \n static inline int\n rte_spinlock_trylock_tm(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (likely(rte_try_tm(&sl->locked)))\n \t\treturn 1;\n@@ -139,6 +144,7 @@ rte_spinlock_trylock_tm(rte_spinlock_t *sl)\n \n static inline void\n rte_spinlock_unlock_tm(rte_spinlock_t *sl)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (unlikely(sl->locked))\n \t\trte_spinlock_unlock(sl);\n@@ -148,6 +154,7 @@ rte_spinlock_unlock_tm(rte_spinlock_t *sl)\n \n static inline void\n rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (likely(rte_try_tm(&slr->sl.locked)))\n \t\treturn;\n@@ -157,6 +164,7 @@ rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr)\n \n static inline void\n rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (unlikely(slr->sl.locked))\n \t\trte_spinlock_recursive_unlock(slr);\n@@ -166,6 +174,7 @@ rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr)\n \n static inline int\n rte_spinlock_recursive_trylock_tm(rte_spinlock_recursive_t *slr)\n+\t__rte_no_thread_safety_analysis\n {\n \tif (likely(rte_try_tm(&slr->sl.locked)))\n \t\treturn 1;\ndiff --git a/lib/meson.build b/lib/meson.build\nindex a90fee31b7..450c061d2b 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -120,6 +120,7 @@ foreach l:libraries\n     reason = '<unknown reason>' # set if build == false to explain why\n     name = l\n     use_function_versioning = false\n+    annotate_locks = false\n     sources = []\n     headers = []\n     indirect_headers = [] # public headers not directly included by apps\n@@ -202,6 +203,10 @@ foreach l:libraries\n         cflags += '-DRTE_USE_FUNCTION_VERSIONING'\n     endif\n     cflags += '-DRTE_LOG_DEFAULT_LOGTYPE=lib.' + l\n+    if annotate_locks and cc.has_argument('-Wthread-safety')\n+        cflags += '-DRTE_ANNOTATE_LOCKS'\n+        cflags += '-Wthread-safety'\n+    endif\n \n     # first build static lib\n     static_lib = static_library(libname,\n",
    "prefixes": [
        "v6",
        "1/9"
    ]
}