examples/packet_ordering: enhance getopt_long usage
[dpdk.git] / lib / librte_eal / windows / eal_lcore.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Intel Corporation
3  */
4
5 #include <pthread.h>
6 #include <stdbool.h>
7 #include <stdint.h>
8
9 #include <rte_common.h>
10 #include <rte_debug.h>
11 #include <rte_lcore.h>
12 #include <rte_os.h>
13
14 #include "eal_private.h"
15 #include "eal_thread.h"
16 #include "eal_windows.h"
17
18 /** Number of logical processors (cores) in a processor group (32 or 64). */
19 #define EAL_PROCESSOR_GROUP_SIZE (sizeof(KAFFINITY) * CHAR_BIT)
20
21 struct lcore_map {
22         uint8_t socket_id;
23         uint8_t core_id;
24 };
25
26 struct socket_map {
27         uint16_t node_id;
28 };
29
30 struct cpu_map {
31         unsigned int socket_count;
32         unsigned int lcore_count;
33         struct lcore_map lcores[RTE_MAX_LCORE];
34         struct socket_map sockets[RTE_MAX_NUMA_NODES];
35 };
36
37 static struct cpu_map cpu_map = { 0 };
38
39 /* eal_create_cpu_map() is called before logging is initialized */
40 static void
41 __rte_format_printf(1, 2)
42 log_early(const char *format, ...)
43 {
44         va_list va;
45
46         va_start(va, format);
47         vfprintf(stderr, format, va);
48         va_end(va);
49 }
50
51 int
52 eal_create_cpu_map(void)
53 {
54         SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infos, *info;
55         DWORD infos_size;
56         bool full = false;
57
58         infos_size = 0;
59         if (!GetLogicalProcessorInformationEx(
60                         RelationNumaNode, NULL, &infos_size)) {
61                 DWORD error = GetLastError();
62                 if (error != ERROR_INSUFFICIENT_BUFFER) {
63                         log_early("Cannot get NUMA node info size, error %lu\n",
64                                 GetLastError());
65                         rte_errno = ENOMEM;
66                         return -1;
67                 }
68         }
69
70         infos = malloc(infos_size);
71         if (infos == NULL) {
72                 log_early("Cannot allocate memory for NUMA node information\n");
73                 rte_errno = ENOMEM;
74                 return -1;
75         }
76
77         if (!GetLogicalProcessorInformationEx(
78                         RelationNumaNode, infos, &infos_size)) {
79                 log_early("Cannot get NUMA node information, error %lu\n",
80                         GetLastError());
81                 rte_errno = EINVAL;
82                 return -1;
83         }
84
85         info = infos;
86         while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
87                 unsigned int node_id = info->NumaNode.NodeNumber;
88                 GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
89                 struct lcore_map *lcore;
90                 unsigned int i, socket_id;
91
92                 /* NUMA node may be reported multiple times if it includes
93                  * cores from different processor groups, e. g. 80 cores
94                  * of a physical processor comprise one NUMA node, but two
95                  * processor groups, because group size is limited by 32/64.
96                  */
97                 for (socket_id = 0; socket_id < cpu_map.socket_count;
98                     socket_id++) {
99                         if (cpu_map.sockets[socket_id].node_id == node_id)
100                                 break;
101                 }
102
103                 if (socket_id == cpu_map.socket_count) {
104                         if (socket_id == RTE_DIM(cpu_map.sockets)) {
105                                 full = true;
106                                 goto exit;
107                         }
108
109                         cpu_map.sockets[socket_id].node_id = node_id;
110                         cpu_map.socket_count++;
111                 }
112
113                 for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
114                         if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
115                                 continue;
116
117                         if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores)) {
118                                 full = true;
119                                 goto exit;
120                         }
121
122                         lcore = &cpu_map.lcores[cpu_map.lcore_count];
123                         lcore->socket_id = socket_id;
124                         lcore->core_id =
125                                 cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
126                         cpu_map.lcore_count++;
127                 }
128
129                 info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
130                         (uint8_t *)info + info->Size);
131         }
132
133 exit:
134         if (full) {
135                 /* Not a fatal error, but important for troubleshooting. */
136                 log_early("Enumerated maximum of %u NUMA nodes and %u cores\n",
137                         cpu_map.socket_count, cpu_map.lcore_count);
138         }
139
140         free(infos);
141
142         return 0;
143 }
144
145 int
146 eal_cpu_detected(unsigned int lcore_id)
147 {
148         return lcore_id < cpu_map.lcore_count;
149 }
150
151 unsigned
152 eal_cpu_socket_id(unsigned int lcore_id)
153 {
154         return cpu_map.lcores[lcore_id].socket_id;
155 }
156
157 unsigned
158 eal_cpu_core_id(unsigned int lcore_id)
159 {
160         return cpu_map.lcores[lcore_id].core_id;
161 }
162
163 unsigned int
164 eal_socket_numa_node(unsigned int socket_id)
165 {
166         return cpu_map.sockets[socket_id].node_id;
167 }