get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 111626,
    "url": "https://patches.dpdk.org/api/patches/111626/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1653311234-329-2-git-send-email-roretzla@linux.microsoft.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": "<1653311234-329-2-git-send-email-roretzla@linux.microsoft.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1653311234-329-2-git-send-email-roretzla@linux.microsoft.com",
    "date": "2022-05-23T13:07:13",
    "name": "[v2,1/2] eal: get/set thread priority per thread identifier",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "285e274189c809f910dcc5bcaa39b9bd678ef2c0",
    "submitter": {
        "id": 2077,
        "url": "https://patches.dpdk.org/api/people/2077/?format=api",
        "name": "Tyler Retzlaff",
        "email": "roretzla@linux.microsoft.com"
    },
    "delegate": {
        "id": 24651,
        "url": "https://patches.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1653311234-329-2-git-send-email-roretzla@linux.microsoft.com/mbox/",
    "series": [
        {
            "id": 23095,
            "url": "https://patches.dpdk.org/api/series/23095/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=23095",
            "date": "2022-05-23T13:07:13",
            "name": "add thread priority accessors",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/23095/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/111626/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/111626/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 E89B8A00C2;\n\tMon, 23 May 2022 15:07:17 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 958564014F;\n\tMon, 23 May 2022 15:07:17 +0200 (CEST)",
            "from linux.microsoft.com (linux.microsoft.com [13.77.154.182])\n by mails.dpdk.org (Postfix) with ESMTP id 5BEE140141\n for <dev@dpdk.org>; Mon, 23 May 2022 15:07:16 +0200 (CEST)",
            "by linux.microsoft.com (Postfix, from userid 1086)\n id A1EE820B6C7C; Mon, 23 May 2022 06:07:15 -0700 (PDT)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 linux.microsoft.com A1EE820B6C7C",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com;\n s=default; t=1653311235;\n bh=CE+AELR+NMUSch5CfJgvEaeCfyjr6KA/4jYNtfvv8AY=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=YDoAV2tHy02zPK5mMfVQcQTwjKqqYUmDfQbt0tPSnQOAXejBh9bGR11b0jWZyoPsO\n GvIS93OnAWktAjGxo+nGtI5QQKvyqeRPt80Efz7wiaaqTVV4h3fM2SR68aWTJaNhxz\n a7nnDGfvutju5RjOSDkB9KrVw2tbplZyv/1Ln9oI=",
        "From": "Tyler Retzlaff <roretzla@linux.microsoft.com>",
        "To": "dev@dpdk.org",
        "Cc": "thomas@monjalon.net, dmitry.kozliuk@gmail.com, anatoly.burakov@intel.com,\n Tyler Retzlaff <roretzla@linux.microsoft.com>,\n Narcisa Vasile <navasile@linux.microsoft.com>",
        "Subject": "[PATCH v2 1/2] eal: get/set thread priority per thread identifier",
        "Date": "Mon, 23 May 2022 06:07:13 -0700",
        "Message-Id": "<1653311234-329-2-git-send-email-roretzla@linux.microsoft.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1653311234-329-1-git-send-email-roretzla@linux.microsoft.com>",
        "References": "<1653302773-11043-1-git-send-email-roretzla@linux.microsoft.com>\n <1653311234-329-1-git-send-email-roretzla@linux.microsoft.com>",
        "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": "Add functions for setting and getting the priority of a thread.\nPriorities on multiple platforms are similarly determined by a priority\nvalue and a priority class/policy.\n\nCurrently in DPDK most threads operate at the OS-default priority level\nbut there are cases when increasing the priority is useful. For\nexample, high performance applications may require elevated priority\nlevels.\n\nFor these reasons, EAL will expose two priority levels which are named\nsuggestively \"normal\" and \"realtime_critical\" and are computed as\nfollows:\n\n  On Linux, the following mapping is created:\n    RTE_THREAD_PRIORITY_NORMAL corresponds to\n      * policy SCHED_OTHER\n      * priority value:   (sched_get_priority_min(SCHED_OTHER) +\n\t\t\t   sched_get_priority_max(SCHED_OTHER))/2;\n    RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to\n      * policy SCHED_RR\n      * priority value: sched_get_priority_max(SCHED_RR);\n\n  On Windows, the following mapping is created:\n    RTE_THREAD_PRIORITY_NORMAL corresponds to\n      * class NORMAL_PRIORITY_CLASS\n      * priority THREAD_PRIORITY_NORMAL\n    RTE_THREAD_PRIORITY_REALTIME_CRITICAL corresponds to\n      * class REALTIME_PRIORITY_CLASS (when running with privileges)\n      * class HIGH_PRIORITY_CLASS (when running without privileges)\n      * priority THREAD_PRIORITY_TIME_CRITICAL\n\nNote that on Linux the resulting priority value will be 0, in\naccordance to the documentation that mention the value should be 0 for\nSCHED_OTHER policy.\n\nSigned-off-by: Narcisa Vasile <navasile@linux.microsoft.com>\nSigned-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>\n---\n lib/eal/include/rte_thread.h |  50 +++++++++++++++++\n lib/eal/unix/rte_thread.c    | 101 +++++++++++++++++++++++++++++++++\n lib/eal/version.map          |   2 +\n lib/eal/windows/rte_thread.c | 130 +++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 283 insertions(+)",
    "diff": "diff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h\nindex 7888f7a..9e261bf 100644\n--- a/lib/eal/include/rte_thread.h\n+++ b/lib/eal/include/rte_thread.h\n@@ -31,6 +31,16 @@\n } rte_thread_t;\n \n /**\n+ * Thread priority values.\n+ */\n+enum rte_thread_priority {\n+\tRTE_THREAD_PRIORITY_NORMAL            = 0,\n+\t/**< normal thread priority, the default */\n+\tRTE_THREAD_PRIORITY_REALTIME_CRITICAL = 1,\n+\t/**< highest thread priority allowed */\n+};\n+\n+/**\n  * TLS key type, an opaque pointer.\n  */\n typedef struct eal_tls_key *rte_thread_key;\n@@ -115,6 +125,46 @@ int rte_thread_get_affinity_by_id(rte_thread_t thread_id,\n #endif /* RTE_HAS_CPUSET */\n \n /**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Get the priority of a thread.\n+ *\n+ * @param thread_id\n+ *   Id of the thread for which to get priority.\n+ *\n+ * @param priority\n+ *   Location to store the retrieved priority.\n+ *\n+ * @return\n+ *   On success, return 0.\n+ *   On failure, return a positive errno-style error number.\n+ */\n+__rte_experimental\n+int rte_thread_get_priority(rte_thread_t thread_id,\n+\t\tenum rte_thread_priority *priority);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Set the priority of a thread.\n+ *\n+ * @param thread_id\n+ *   Id of the thread for which to set priority.\n+ *\n+ * @param priority\n+ *   Priority value to be set.\n+ *\n+ * @return\n+ *   On success, return 0.\n+ *   On failure, return a positive errno-style error number.\n+ */\n+__rte_experimental\n+int rte_thread_set_priority(rte_thread_t thread_id,\n+\t\tenum rte_thread_priority priority);\n+\n+/**\n  * Create a TLS data key visible to all threads in the process.\n  * the created key is later used to get/set a value.\n  * and optional destructor can be set to be called when a thread exits.\ndiff --git a/lib/eal/unix/rte_thread.c b/lib/eal/unix/rte_thread.c\nindex 9e5fa47..2b19f4a 100644\n--- a/lib/eal/unix/rte_thread.c\n+++ b/lib/eal/unix/rte_thread.c\n@@ -16,6 +16,64 @@ struct eal_tls_key {\n \tpthread_key_t thread_index;\n };\n \n+static int\n+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,\n+\t\tint *os_pri, int *pol)\n+{\n+\t/* Clear the output parameters */\n+\t*os_pri = sched_get_priority_min(SCHED_OTHER) - 1;\n+\t*pol = -1;\n+\n+\tswitch (eal_pri) {\n+\tcase RTE_THREAD_PRIORITY_NORMAL:\n+\t\t*pol = SCHED_OTHER;\n+\n+\t\t/*\n+\t\t * Choose the middle of the range to represent\n+\t\t * the priority 'normal'.\n+\t\t * On Linux, this should be 0, since both\n+\t\t * sched_get_priority_min/_max return 0 for SCHED_OTHER.\n+\t\t */\n+\t\t*os_pri = (sched_get_priority_min(SCHED_OTHER) +\n+\t\t\tsched_get_priority_max(SCHED_OTHER))/2;\n+\t\tbreak;\n+\tcase RTE_THREAD_PRIORITY_REALTIME_CRITICAL:\n+\t\t*pol = SCHED_RR;\n+\t\t*os_pri = sched_get_priority_max(SCHED_RR);\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL, \"The requested priority value is invalid.\\n\");\n+\t\treturn EINVAL;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+thread_map_os_priority_to_eal_priority(int policy, int os_pri,\n+\t\tenum rte_thread_priority *eal_pri)\n+{\n+\tswitch (policy) {\n+\tcase SCHED_OTHER:\n+\t\tif (os_pri == (sched_get_priority_min(SCHED_OTHER) +\n+\t\t\t\tsched_get_priority_max(SCHED_OTHER))/2) {\n+\t\t\t*eal_pri = RTE_THREAD_PRIORITY_NORMAL;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tbreak;\n+\tcase SCHED_RR:\n+\t\tif (os_pri == sched_get_priority_max(SCHED_RR)) {\n+\t\t\t*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL, \"The OS priority value does not map to an EAL-defined priority.\\n\");\n+\t\treturn EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n rte_thread_t\n rte_thread_self(void)\n {\n@@ -29,6 +87,49 @@ struct eal_tls_key {\n }\n \n int\n+rte_thread_get_priority(rte_thread_t thread_id,\n+\t\tenum rte_thread_priority *priority)\n+{\n+\tint ret;\n+\tint policy;\n+\tstruct sched_param param;\n+\n+\tret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy,\n+\t\t\t&param);\n+\tif (ret != 0) {\n+\t\tRTE_LOG(DEBUG, EAL, \"pthread_getschedparam failed\\n\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\treturn thread_map_os_priority_to_eal_priority(policy,\n+\t\t\tparam.sched_priority, priority);\n+\n+cleanup:\n+\treturn ret;\n+}\n+\n+int\n+rte_thread_set_priority(rte_thread_t thread_id,\n+\t\tenum rte_thread_priority priority)\n+{\n+\tint ret;\n+\tint policy;\n+\tstruct sched_param param;\n+\n+/* Realtime priority can cause crashes on non-Windows platforms. */\n+\tif (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL)\n+\t\treturn ENOTSUP;\n+\n+\tret = thread_map_priority_to_os_value(priority, &param.sched_priority,\n+\t\t&policy);\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+\treturn pthread_setschedparam((pthread_t)thread_id.opaque_id,\n+\t\tpolicy, &param);\n+}\n+\n+int\n rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *))\n {\n \tint err;\ndiff --git a/lib/eal/version.map b/lib/eal/version.map\nindex d49e30b..ab27a4b 100644\n--- a/lib/eal/version.map\n+++ b/lib/eal/version.map\n@@ -423,8 +423,10 @@ EXPERIMENTAL {\n \n \t# added in 22.07\n \trte_thread_get_affinity_by_id;\n+\trte_thread_get_priority;\n \trte_thread_self;\n \trte_thread_set_affinity_by_id;\n+\trte_thread_set_priority;\n };\n \n INTERNAL {\ndiff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c\nindex a616703..495225e 100644\n--- a/lib/eal/windows/rte_thread.c\n+++ b/lib/eal/windows/rte_thread.c\n@@ -61,6 +61,58 @@ struct eal_tls_key {\n \treturn thread_translate_win32_error(error);\n }\n \n+static int\n+thread_map_priority_to_os_value(enum rte_thread_priority eal_pri,\n+\t\tint *os_pri, DWORD *pri_class)\n+{\n+\t/* Clear the output parameters */\n+\t*os_pri = -1;\n+\t*pri_class = -1;\n+\n+\tswitch (eal_pri) {\n+\tcase RTE_THREAD_PRIORITY_NORMAL:\n+\t\t*pri_class = NORMAL_PRIORITY_CLASS;\n+\t\t*os_pri = THREAD_PRIORITY_NORMAL;\n+\t\tbreak;\n+\tcase RTE_THREAD_PRIORITY_REALTIME_CRITICAL:\n+\t\t*pri_class = REALTIME_PRIORITY_CLASS;\n+\t\t*os_pri = THREAD_PRIORITY_TIME_CRITICAL;\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL, \"The requested priority value is invalid.\\n\");\n+\t\treturn EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+thread_map_os_priority_to_eal_value(int os_pri, DWORD pri_class,\n+\t\tenum rte_thread_priority *eal_pri)\n+{\n+\tswitch (pri_class) {\n+\tcase NORMAL_PRIORITY_CLASS:\n+\t\tif (os_pri == THREAD_PRIORITY_NORMAL) {\n+\t\t\t*eal_pri = RTE_THREAD_PRIORITY_NORMAL;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tbreak;\n+\tcase HIGH_PRIORITY_CLASS:\n+\t\tRTE_LOG(WARNING, EAL, \"The OS priority class is high not real-time.\\n\");\n+\t\t/* FALLTHROUGH */\n+\tcase REALTIME_PRIORITY_CLASS:\n+\t\tif (os_pri == THREAD_PRIORITY_TIME_CRITICAL) {\n+\t\t\t*eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL, \"The OS priority value does not map to an EAL-defined priority.\\n\");\n+\t\treturn EINVAL;\n+\t}\n+\treturn 0;\n+}\n+\n rte_thread_t\n rte_thread_self(void)\n {\n@@ -72,6 +124,84 @@ struct eal_tls_key {\n }\n \n int\n+rte_thread_get_priority(rte_thread_t thread_id,\n+\t\tenum rte_thread_priority *priority)\n+{\n+\tHANDLE thread_handle = NULL;\n+\tDWORD pri_class;\n+\tint os_pri;\n+\tint ret;\n+\n+\tpri_class = GetPriorityClass(GetCurrentProcess());\n+\tif (pri_class == 0) {\n+\t\tret = thread_log_last_error(\"GetPriorityClass()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tthread_handle = OpenThread(THREAD_SET_INFORMATION |\n+\t\t\tTHREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);\n+\tif (thread_handle == NULL) {\n+\t\tret = thread_log_last_error(\"OpenThread()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tos_pri = GetThreadPriority(thread_handle);\n+\tif (os_pri == THREAD_PRIORITY_ERROR_RETURN) {\n+\t\tret = thread_log_last_error(\"GetThreadPriority()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority);\n+\tif (ret != 0)\n+\t\tgoto cleanup;\n+\n+cleanup:\n+\tif (thread_handle != NULL)\n+\t\tCloseHandle(thread_handle);\n+\n+\treturn ret;\n+}\n+\n+int\n+rte_thread_set_priority(rte_thread_t thread_id,\n+\t\t\tenum rte_thread_priority priority)\n+{\n+\tHANDLE thread_handle;\n+\tDWORD priority_class;\n+\tint os_priority;\n+\tint ret = 0;\n+\n+\tthread_handle = OpenThread(THREAD_SET_INFORMATION |\n+\t\tTHREAD_QUERY_INFORMATION, FALSE,\n+\t\tthread_id.opaque_id);\n+\tif (thread_handle == NULL) {\n+\t\tret = thread_log_last_error(\"OpenThread()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tret = thread_map_priority_to_os_value(priority, &os_priority,\n+\t\t&priority_class);\n+\tif (ret != 0)\n+\t\tgoto cleanup;\n+\n+\tif (!SetPriorityClass(GetCurrentProcess(), priority_class)) {\n+\t\tret = thread_log_last_error(\"SetPriorityClass()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tif (!SetThreadPriority(thread_handle, os_priority)) {\n+\t\tret = thread_log_last_error(\"SetThreadPriority()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+cleanup:\n+\tif (thread_handle != NULL)\n+\t\tCloseHandle(thread_handle);\n+\n+\treturn ret;\n+}\n+\n+int\n rte_thread_key_create(rte_thread_key *key,\n \t\t__rte_unused void (*destructor)(void *))\n {\n",
    "prefixes": [
        "v2",
        "1/2"
    ]
}