get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 104139,
    "url": "https://patches.dpdk.org/api/patches/104139/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1636594425-9692-5-git-send-email-navasile@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": "<1636594425-9692-5-git-send-email-navasile@linux.microsoft.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1636594425-9692-5-git-send-email-navasile@linux.microsoft.com",
    "date": "2021-11-11T01:33:41",
    "name": "[v18,4/8] eal: implement functions for thread affinity management",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "bfd0754b7f10596473e8f160143e3e8da220d09e",
    "submitter": {
        "id": 1668,
        "url": "https://patches.dpdk.org/api/people/1668/?format=api",
        "name": "Narcisa Ana Maria Vasile",
        "email": "navasile@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/1636594425-9692-5-git-send-email-navasile@linux.microsoft.com/mbox/",
    "series": [
        {
            "id": 20472,
            "url": "https://patches.dpdk.org/api/series/20472/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=20472",
            "date": "2021-11-11T01:33:40",
            "name": "eal: Add EAL API for threading",
            "version": 18,
            "mbox": "https://patches.dpdk.org/series/20472/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/104139/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/104139/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 57A2AA0C4B;\n\tThu, 11 Nov 2021 02:35:09 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 80F224114D;\n\tThu, 11 Nov 2021 02:34:58 +0100 (CET)",
            "from linux.microsoft.com (linux.microsoft.com [13.77.154.182])\n by mails.dpdk.org (Postfix) with ESMTP id 79084410F7\n for <dev@dpdk.org>; Thu, 11 Nov 2021 02:34:53 +0100 (CET)",
            "by linux.microsoft.com (Postfix, from userid 1059)\n id BF26820C357D; Wed, 10 Nov 2021 17:34:52 -0800 (PST)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 linux.microsoft.com BF26820C357D",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com;\n s=default; t=1636594492;\n bh=4LVnA6HfcZgzX9eXbDGMjHALoh0WFVFuZQz6pNzJaYE=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=BJd/UdDtCtGF4+I0B5EAvpcqqBSsYvxZm217SUZcBXUVAAHpyYfq6pBu3IVQnlVqT\n +J610rN7JUGTqaZVvEKJU0uIf6qFM2TDBCuh04vVRSDPMx8FBJo1qiYYTT5a1tcYum\n iQ80mM7PlJGiJ5zUQDvwiwty3cdQLjA79yiF9Ep4=",
        "From": "Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>",
        "To": "dev@dpdk.org, thomas@monjalon.net, dmitry.kozliuk@gmail.com,\n khot@microsoft.com, navasile@microsoft.com, dmitrym@microsoft.com,\n roretzla@microsoft.com, talshn@nvidia.com, ocardona@microsoft.com",
        "Cc": "bruce.richardson@intel.com, david.marchand@redhat.com,\n pallavi.kadam@intel.com",
        "Subject": "[PATCH v18 4/8] eal: implement functions for thread affinity\n management",
        "Date": "Wed, 10 Nov 2021 17:33:41 -0800",
        "Message-Id": "<1636594425-9692-5-git-send-email-navasile@linux.microsoft.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1636594425-9692-1-git-send-email-navasile@linux.microsoft.com>",
        "References": "<1636513302-7359-1-git-send-email-navasile@linux.microsoft.com>\n <1636594425-9692-1-git-send-email-navasile@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": "From: Narcisa Vasile <navasile@microsoft.com>\n\nImplement functions for getting/setting thread affinity.\nThreads can be pinned to specific cores by setting their\naffinity attribute.\n\nSigned-off-by: Narcisa Vasile <navasile@microsoft.com>\nSigned-off-by: Dmitry Malloy <dmitrym@microsoft.com>\n---\n lib/eal/common/rte_thread.c   |  16 ++++\n lib/eal/include/rte_thread.h  |  36 +++++++\n lib/eal/version.map           |   2 +\n lib/eal/windows/eal_lcore.c   | 176 +++++++++++++++++++++++++---------\n lib/eal/windows/eal_windows.h |  10 ++\n lib/eal/windows/rte_thread.c  | 125 +++++++++++++++++++++++-\n 6 files changed, 319 insertions(+), 46 deletions(-)",
    "diff": "diff --git a/lib/eal/common/rte_thread.c b/lib/eal/common/rte_thread.c\nindex 27ad1c7eb0..73b7b3141c 100644\n--- a/lib/eal/common/rte_thread.c\n+++ b/lib/eal/common/rte_thread.c\n@@ -34,6 +34,22 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)\n \treturn pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id);\n }\n \n+int\n+rte_thread_set_affinity_by_id(rte_thread_t thread_id,\n+\t\tconst rte_cpuset_t *cpuset)\n+{\n+\treturn pthread_setaffinity_np((pthread_t)thread_id.opaque_id,\n+\t\tsizeof(*cpuset), cpuset);\n+}\n+\n+int\n+rte_thread_get_affinity_by_id(rte_thread_t thread_id,\n+\t\trte_cpuset_t *cpuset)\n+{\n+\treturn pthread_getaffinity_np((pthread_t)thread_id.opaque_id,\n+\t\tsizeof(*cpuset), cpuset);\n+}\n+\n int\n rte_thread_attr_init(rte_thread_attr_t *attr)\n {\ndiff --git a/lib/eal/include/rte_thread.h b/lib/eal/include/rte_thread.h\nindex 8a20215a94..5b100cafda 100644\n--- a/lib/eal/include/rte_thread.h\n+++ b/lib/eal/include/rte_thread.h\n@@ -85,6 +85,42 @@ int rte_thread_equal(rte_thread_t t1, rte_thread_t t2);\n \n #ifdef RTE_HAS_CPUSET\n \n+/**\n+ * Set the affinity of thread 'thread_id' to the cpu set\n+ * specified by 'cpuset'.\n+ *\n+ * @param thread_id\n+ *    Id of the thread for which to set the affinity.\n+ *\n+ * @param cpuset\n+ *   Pointer to CPU affinity to 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_affinity_by_id(rte_thread_t thread_id,\n+\t\tconst rte_cpuset_t *cpuset);\n+\n+/**\n+ * Get the affinity of thread 'thread_id' and store it\n+ * in 'cpuset'.\n+ *\n+ * @param thread_id\n+ *    Id of the thread for which to get the affinity.\n+ *\n+ * @param cpuset\n+ *   Pointer for storing the affinity value.\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_affinity_by_id(rte_thread_t thread_id,\n+\t\trte_cpuset_t *cpuset);\n+\n /**\n  * Initialize the attributes of a thread.\n  * These attributes can be passed to the rte_thread_create() function\ndiff --git a/lib/eal/version.map b/lib/eal/version.map\nindex 3fc33fcd70..193a79a4d2 100644\n--- a/lib/eal/version.map\n+++ b/lib/eal/version.map\n@@ -427,6 +427,8 @@ EXPERIMENTAL {\n \trte_thread_attr_get_affinity;\n \trte_thread_attr_set_affinity;\n \trte_thread_attr_set_priority;\n+\trte_thread_get_affinity_by_id;\n+\trte_thread_set_affinity_by_id;\n };\n \n INTERNAL {\ndiff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c\nindex 476c2d2bdf..295af50698 100644\n--- a/lib/eal/windows/eal_lcore.c\n+++ b/lib/eal/windows/eal_lcore.c\n@@ -2,7 +2,6 @@\n  * Copyright(c) 2019 Intel Corporation\n  */\n \n-#include <pthread.h>\n #include <stdbool.h>\n #include <stdint.h>\n \n@@ -27,13 +26,15 @@ struct socket_map {\n };\n \n struct cpu_map {\n-\tunsigned int socket_count;\n \tunsigned int lcore_count;\n+\tunsigned int socket_count;\n+\tunsigned int cpu_count;\n \tstruct lcore_map lcores[RTE_MAX_LCORE];\n \tstruct socket_map sockets[RTE_MAX_NUMA_NODES];\n+\tGROUP_AFFINITY cpus[CPU_SETSIZE];\n };\n \n-static struct cpu_map cpu_map = { 0 };\n+static struct cpu_map cpu_map;\n \n /* eal_create_cpu_map() is called before logging is initialized */\n static void\n@@ -47,13 +48,118 @@ log_early(const char *format, ...)\n \tva_end(va);\n }\n \n+static int\n+eal_query_group_affinity(void)\n+{\n+\tSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos = NULL;\n+\tunsigned int *cpu_count = &cpu_map.cpu_count;\n+\tDWORD infos_size = 0;\n+\tint ret = 0;\n+\tUSHORT group_count;\n+\tKAFFINITY affinity;\n+\tUSHORT group_no;\n+\tunsigned int i;\n+\n+\tif (!GetLogicalProcessorInformationEx(RelationGroup, NULL,\n+\t\t\t\t\t      &infos_size)) {\n+\t\tDWORD error = GetLastError();\n+\t\tif (error != ERROR_INSUFFICIENT_BUFFER) {\n+\t\t\tlog_early(\"Cannot get group information size, \"\n+\t\t\t\t  \"error %lu\\n\", error);\n+\t\t\trte_errno = EINVAL;\n+\t\t\tret = -1;\n+\t\t\tgoto cleanup;\n+\t\t}\n+\t}\n+\n+\tinfos = malloc(infos_size);\n+\tif (infos == NULL) {\n+\t\tlog_early(\"Cannot allocate memory for NUMA node information\\n\");\n+\t\trte_errno = ENOMEM;\n+\t\tret = -1;\n+\t\tgoto cleanup;\n+\t}\n+\n+\tif (!GetLogicalProcessorInformationEx(RelationGroup, infos,\n+\t\t\t\t\t      &infos_size)) {\n+\t\tlog_early(\"Cannot get group information, error %lu\\n\",\n+\t\t\t  GetLastError());\n+\t\trte_errno = EINVAL;\n+\t\tret = -1;\n+\t\tgoto cleanup;\n+\t}\n+\n+\t*cpu_count = 0;\n+\tgroup_count = infos->Group.ActiveGroupCount;\n+\tfor (group_no = 0; group_no < group_count; group_no++) {\n+\n+\t\taffinity = infos->Group.GroupInfo[group_no].ActiveProcessorMask;\n+\n+\t\tfor (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {\n+\t\t\tif ((affinity & ((KAFFINITY)1 << i)) == 0)\n+\t\t\t\tcontinue;\n+\t\t\tcpu_map.cpus[*cpu_count].Group = group_no;\n+\t\t\tcpu_map.cpus[*cpu_count].Mask = (KAFFINITY)1 << i;\n+\t\t\t(*cpu_count)++;\n+\t\t}\n+\t}\n+\n+cleanup:\n+\tfree(infos);\n+\treturn ret;\n+}\n+\n+static bool\n+eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)\n+{\n+\tconst unsigned int node_id = info->NumaNode.NodeNumber;\n+\tconst GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;\n+\tstruct lcore_map *lcore;\n+\tunsigned int socket_id;\n+\tunsigned int i;\n+\n+\t/* NUMA node may be reported multiple times if it includes\n+\t * cores from different processor groups, e. g. 80 cores\n+\t * of a physical processor comprise one NUMA node, but two\n+\t * processor groups, because group size is limited by 32/64.\n+\t */\n+\tfor (socket_id = 0; socket_id < cpu_map.socket_count; socket_id++) {\n+\t\tif (cpu_map.sockets[socket_id].node_id == node_id)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (socket_id == cpu_map.socket_count) {\n+\t\tif (socket_id == RTE_DIM(cpu_map.sockets))\n+\t\t\treturn true;\n+\n+\t\tcpu_map.sockets[socket_id].node_id = node_id;\n+\t\tcpu_map.socket_count++;\n+\t}\n+\n+\tfor (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {\n+\t\tif ((cores->Mask & ((KAFFINITY)1 << i)) == 0)\n+\t\t\tcontinue;\n+\n+\t\tif (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))\n+\t\t\treturn true;\n+\n+\t\tlcore = &cpu_map.lcores[cpu_map.lcore_count];\n+\t\tlcore->socket_id = socket_id;\n+\t\tlcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;\n+\t\tcpu_map.lcore_count++;\n+\t}\n+\treturn false;\n+}\n+\n int\n eal_create_cpu_map(void)\n {\n \tSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;\n \tDWORD infos_size;\n \tbool full = false;\n+\tint ret = 0;\n \n+\tinfos = NULL;\n \tinfos_size = 0;\n \tif (!GetLogicalProcessorInformationEx(\n \t\t\tRelationNumaNode, NULL, &infos_size)) {\n@@ -78,57 +184,29 @@ eal_create_cpu_map(void)\n \t\tlog_early(\"Cannot get NUMA node information, error %lu\\n\",\n \t\t\tGetLastError());\n \t\trte_errno = EINVAL;\n-\t\treturn -1;\n+\t\tret = -1;\n+\t\tgoto exit;\n \t}\n \n \tinfo = infos;\n \twhile ((uint8_t *)info - (uint8_t *)infos < infos_size) {\n-\t\tunsigned int node_id = info->NumaNode.NodeNumber;\n-\t\tGROUP_AFFINITY *cores = &info->NumaNode.GroupMask;\n-\t\tstruct lcore_map *lcore;\n-\t\tunsigned int i, socket_id;\n-\n-\t\t/* NUMA node may be reported multiple times if it includes\n-\t\t * cores from different processor groups, e. g. 80 cores\n-\t\t * of a physical processor comprise one NUMA node, but two\n-\t\t * processor groups, because group size is limited by 32/64.\n-\t\t */\n-\t\tfor (socket_id = 0; socket_id < cpu_map.socket_count;\n-\t\t    socket_id++) {\n-\t\t\tif (cpu_map.sockets[socket_id].node_id == node_id)\n-\t\t\t\tbreak;\n-\t\t}\n-\n-\t\tif (socket_id == cpu_map.socket_count) {\n-\t\t\tif (socket_id == RTE_DIM(cpu_map.sockets)) {\n-\t\t\t\tfull = true;\n-\t\t\t\tgoto exit;\n-\t\t\t}\n-\n-\t\t\tcpu_map.sockets[socket_id].node_id = node_id;\n-\t\t\tcpu_map.socket_count++;\n-\t\t}\n-\n-\t\tfor (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {\n-\t\t\tif ((cores->Mask & ((KAFFINITY)1 << i)) == 0)\n-\t\t\t\tcontinue;\n-\n-\t\t\tif (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {\n-\t\t\t\tfull = true;\n-\t\t\t\tgoto exit;\n-\t\t\t}\n-\n-\t\t\tlcore = &cpu_map.lcores[cpu_map.lcore_count];\n-\t\t\tlcore->socket_id = socket_id;\n-\t\t\tlcore->core_id =\n-\t\t\t\tcores->Group * EAL_PROCESSOR_GROUP_SIZE + i;\n-\t\t\tcpu_map.lcore_count++;\n+\t\tif (eal_create_lcore_map(info)) {\n+\t\t\tfull = true;\n+\t\t\tbreak;\n \t\t}\n \n \t\tinfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(\n \t\t\t(uint8_t *)info + info->Size);\n \t}\n \n+\tif (eal_query_group_affinity()) {\n+\t\t/*\n+\t\t * No need to set rte_errno here.\n+\t\t * It is set by eal_query_group_affinity().\n+\t\t */\n+\t\tret = -1;\n+\t\tgoto exit;\n+\t}\n exit:\n \tif (full) {\n \t\t/* Not a fatal error, but important for troubleshooting. */\n@@ -138,7 +216,7 @@ eal_create_cpu_map(void)\n \n \tfree(infos);\n \n-\treturn 0;\n+\treturn ret;\n }\n \n int\n@@ -164,3 +242,11 @@ eal_socket_numa_node(unsigned int socket_id)\n {\n \treturn cpu_map.sockets[socket_id].node_id;\n }\n+\n+PGROUP_AFFINITY\n+eal_get_cpu_affinity(size_t cpu_index)\n+{\n+\tRTE_VERIFY(cpu_index < CPU_SETSIZE);\n+\n+\treturn &cpu_map.cpus[cpu_index];\n+}\ndiff --git a/lib/eal/windows/eal_windows.h b/lib/eal/windows/eal_windows.h\nindex 23ead6d30c..355ef181a5 100644\n--- a/lib/eal/windows/eal_windows.h\n+++ b/lib/eal/windows/eal_windows.h\n@@ -55,6 +55,16 @@ int eal_thread_create(pthread_t *thread);\n  */\n unsigned int eal_socket_numa_node(unsigned int socket_id);\n \n+/**\n+ * Get pointer to the group affinity for the cpu.\n+ *\n+ * @param cpu_index\n+ *  Index of the cpu, as it comes from rte_cpuset_t.\n+ * @return\n+ *  Pointer to the group affinity for the cpu.\n+ */\n+PGROUP_AFFINITY eal_get_cpu_affinity(size_t cpu_index);\n+\n /**\n  * Schedule code for execution in the interrupt thread.\n  *\ndiff --git a/lib/eal/windows/rte_thread.c b/lib/eal/windows/rte_thread.c\nindex c1ecfbd6ae..0127119f49 100644\n--- a/lib/eal/windows/rte_thread.c\n+++ b/lib/eal/windows/rte_thread.c\n@@ -7,7 +7,8 @@\n #include <rte_debug.h>\n #include <rte_errno.h>\n #include <rte_thread.h>\n-#include <rte_windows.h>\n+\n+#include \"eal_windows.h\"\n \n struct eal_tls_key {\n \tDWORD thread_index;\n@@ -77,6 +78,128 @@ rte_thread_equal(rte_thread_t t1, rte_thread_t t2)\n \treturn t1.opaque_id == t2.opaque_id;\n }\n \n+static int\n+rte_convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,\n+\t\tPGROUP_AFFINITY affinity)\n+{\n+\tint ret = 0;\n+\tPGROUP_AFFINITY cpu_affinity = NULL;\n+\tunsigned int cpu_idx;\n+\n+\tmemset(affinity, 0, sizeof(GROUP_AFFINITY));\n+\taffinity->Group = (USHORT)-1;\n+\n+\t/* Check that all cpus of the set belong to the same processor group and\n+\t * accumulate thread affinity to be applied.\n+\t */\n+\tfor (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {\n+\t\tif (!CPU_ISSET(cpu_idx, cpuset))\n+\t\t\tcontinue;\n+\n+\t\tcpu_affinity = eal_get_cpu_affinity(cpu_idx);\n+\n+\t\tif (affinity->Group == (USHORT)-1) {\n+\t\t\taffinity->Group = cpu_affinity->Group;\n+\t\t} else if (affinity->Group != cpu_affinity->Group) {\n+\t\t\tret = EINVAL;\n+\t\t\tgoto cleanup;\n+\t\t}\n+\n+\t\taffinity->Mask |= cpu_affinity->Mask;\n+\t}\n+\n+\tif (affinity->Mask == 0) {\n+\t\tret = EINVAL;\n+\t\tgoto cleanup;\n+\t}\n+\n+cleanup:\n+\treturn ret;\n+}\n+\n+int\n+rte_thread_set_affinity_by_id(rte_thread_t thread_id,\n+\t\tconst rte_cpuset_t *cpuset)\n+{\n+\tint ret = 0;\n+\tGROUP_AFFINITY thread_affinity;\n+\tHANDLE thread_handle = NULL;\n+\n+\tRTE_VERIFY(cpuset != NULL);\n+\n+\tret = rte_convert_cpuset_to_affinity(cpuset, &thread_affinity);\n+\tif (ret != 0) {\n+\t\tRTE_LOG(DEBUG, EAL, \"Unable to convert cpuset to thread affinity\\n\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tthread_handle = OpenThread(THREAD_ALL_ACCESS, 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+\tif (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {\n+\t\tret = thread_log_last_error(\"SetThreadGroupAffinity()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+cleanup:\n+\tif (thread_handle != NULL) {\n+\t\tCloseHandle(thread_handle);\n+\t\tthread_handle = NULL;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int\n+rte_thread_get_affinity_by_id(rte_thread_t thread_id,\n+\t\trte_cpuset_t *cpuset)\n+{\n+\tHANDLE thread_handle = NULL;\n+\tPGROUP_AFFINITY cpu_affinity;\n+\tGROUP_AFFINITY thread_affinity;\n+\tunsigned int cpu_idx;\n+\tint ret = 0;\n+\n+\tRTE_VERIFY(cpuset != NULL);\n+\n+\tthread_handle = OpenThread(THREAD_ALL_ACCESS, 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+\t/* obtain previous thread affinity */\n+\tif (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {\n+\t\tret = thread_log_last_error(\"GetThreadGroupAffinity()\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tCPU_ZERO(cpuset);\n+\n+\t/* Convert affinity to DPDK cpu set */\n+\tfor (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {\n+\n+\t\tcpu_affinity = eal_get_cpu_affinity(cpu_idx);\n+\n+\t\tif ((cpu_affinity->Group == thread_affinity.Group) &&\n+\t\t   ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {\n+\t\t\tCPU_SET(cpu_idx, cpuset);\n+\t\t}\n+\t}\n+\n+cleanup:\n+\tif (thread_handle != NULL) {\n+\t\tCloseHandle(thread_handle);\n+\t\tthread_handle = NULL;\n+\t}\n+\treturn ret;\n+}\n+\n int\n rte_thread_attr_init(rte_thread_attr_t *attr)\n {\n",
    "prefixes": [
        "v18",
        "4/8"
    ]
}