eal: move OS-specific sub-directories
[dpdk.git] / lib / librte_eal / windows / eal.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Intel Corporation
3  */
4
5 #include <fcntl.h>
6 #include <io.h>
7 #include <share.h>
8 #include <sys/stat.h>
9
10 #include <rte_debug.h>
11 #include <rte_eal.h>
12 #include <eal_memcfg.h>
13 #include <rte_errno.h>
14 #include <rte_lcore.h>
15 #include <eal_thread.h>
16 #include <eal_internal_cfg.h>
17 #include <eal_filesystem.h>
18 #include <eal_options.h>
19 #include <eal_private.h>
20
21  /* Allow the application to print its usage message too if set */
22 static rte_usage_hook_t rte_application_usage_hook;
23
24 /* define fd variable here, because file needs to be kept open for the
25  * duration of the program, as we hold a write lock on it in the primary proc
26  */
27 static int mem_cfg_fd = -1;
28
29 /* early configuration structure, when memory config is not mmapped */
30 static struct rte_mem_config early_mem_config;
31
32 /* Address of global and public configuration */
33 static struct rte_config rte_config = {
34                 .mem_config = &early_mem_config,
35 };
36
37 /* internal configuration (per-core) */
38 struct lcore_config lcore_config[RTE_MAX_LCORE];
39
40 /* internal configuration */
41 struct internal_config internal_config;
42
43 /* platform-specific runtime dir */
44 static char runtime_dir[PATH_MAX];
45
46 const char *
47 rte_eal_get_runtime_dir(void)
48 {
49         return runtime_dir;
50 }
51
52 /* Return a pointer to the configuration structure */
53 struct rte_config *
54 rte_eal_get_configuration(void)
55 {
56         return &rte_config;
57 }
58
59 /* Detect if we are a primary or a secondary process */
60 enum rte_proc_type_t
61 eal_proc_type_detect(void)
62 {
63         enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
64         const char *pathname = eal_runtime_config_path();
65
66         /* if we can open the file but not get a write-lock we are a secondary
67          * process. NOTE: if we get a file handle back, we keep that open
68          * and don't close it to prevent a race condition between multiple opens
69          */
70         errno_t err = _sopen_s(&mem_cfg_fd, pathname,
71                 _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
72         if (err == 0) {
73                 OVERLAPPED soverlapped = { 0 };
74                 soverlapped.Offset = sizeof(*rte_config.mem_config);
75                 soverlapped.OffsetHigh = 0;
76
77                 HANDLE hwinfilehandle = (HANDLE)_get_osfhandle(mem_cfg_fd);
78
79                 if (!LockFileEx(hwinfilehandle,
80                         LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0,
81                         sizeof(*rte_config.mem_config), 0, &soverlapped))
82                         ptype = RTE_PROC_SECONDARY;
83         }
84
85         RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n",
86                 ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY");
87
88         return ptype;
89 }
90
91 /* display usage */
92 static void
93 eal_usage(const char *prgname)
94 {
95         printf("\nUsage: %s ", prgname);
96         eal_common_usage();
97         /* Allow the application to print its usage message too
98          * if hook is set
99          */
100         if (rte_application_usage_hook) {
101                 printf("===== Application Usage =====\n\n");
102                 rte_application_usage_hook(prgname);
103         }
104 }
105
106 /* Parse the arguments for --log-level only */
107 static void
108 eal_log_level_parse(int argc, char **argv)
109 {
110         int opt;
111         char **argvopt;
112         int option_index;
113
114         argvopt = argv;
115
116         eal_reset_internal_config(&internal_config);
117
118         while ((opt = getopt_long(argc, argvopt, eal_short_options,
119                 eal_long_options, &option_index)) != EOF) {
120
121                 int ret;
122
123                 /* getopt is not happy, stop right now */
124                 if (opt == '?')
125                         break;
126
127                 ret = (opt == OPT_LOG_LEVEL_NUM) ?
128                         eal_parse_common_option(opt, optarg,
129                                 &internal_config) : 0;
130
131                 /* common parser is not happy */
132                 if (ret < 0)
133                         break;
134         }
135
136         optind = 0; /* reset getopt lib */
137 }
138
139 /* Parse the argument given in the command line of the application */
140 __attribute__((optnone)) static int
141 eal_parse_args(int argc, char **argv)
142 {
143         int opt, ret;
144         char **argvopt;
145         int option_index;
146         char *prgname = argv[0];
147
148         argvopt = argv;
149
150         while ((opt = getopt_long(argc, argvopt, eal_short_options,
151                 eal_long_options, &option_index)) != EOF) {
152
153                 int ret;
154
155                 /* getopt is not happy, stop right now */
156                 if (opt == '?') {
157                         eal_usage(prgname);
158                         return -1;
159                 }
160
161                 ret = eal_parse_common_option(opt, optarg, &internal_config);
162                 /* common parser is not happy */
163                 if (ret < 0) {
164                         eal_usage(prgname);
165                         return -1;
166                 }
167                 /* common parser handled this option */
168                 if (ret == 0)
169                         continue;
170
171                 switch (opt) {
172                 case 'h':
173                         eal_usage(prgname);
174                         exit(EXIT_SUCCESS);
175                 default:
176                         if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
177                                 RTE_LOG(ERR, EAL, "Option %c is not supported "
178                                         "on Windows\n", opt);
179                         } else if (opt >= OPT_LONG_MIN_NUM &&
180                                 opt < OPT_LONG_MAX_NUM) {
181                                 RTE_LOG(ERR, EAL, "Option %s is not supported "
182                                         "on Windows\n",
183                                         eal_long_options[option_index].name);
184                         } else {
185                                 RTE_LOG(ERR, EAL, "Option %d is not supported "
186                                         "on Windows\n", opt);
187                         }
188                         eal_usage(prgname);
189                         return -1;
190                 }
191         }
192
193         if (eal_adjust_config(&internal_config) != 0)
194                 return -1;
195
196         /* sanity checks */
197         if (eal_check_common_options(&internal_config) != 0) {
198                 eal_usage(prgname);
199                 return -1;
200         }
201
202         if (optind >= 0)
203                 argv[optind - 1] = prgname;
204         ret = optind - 1;
205         optind = 0; /* reset getopt lib */
206         return ret;
207 }
208
209 static int
210 sync_func(void *arg __rte_unused)
211 {
212         return 0;
213 }
214
215 static void
216 rte_eal_init_alert(const char *msg)
217 {
218         fprintf(stderr, "EAL: FATAL: %s\n", msg);
219         RTE_LOG(ERR, EAL, "%s\n", msg);
220 }
221
222  /* Launch threads, called at application init(). */
223 int
224 rte_eal_init(int argc, char **argv)
225 {
226         int i, fctret;
227
228         eal_log_level_parse(argc, argv);
229
230         /* create a map of all processors in the system */
231         eal_create_cpu_map();
232
233         if (rte_eal_cpu_init() < 0) {
234                 rte_eal_init_alert("Cannot detect lcores.");
235                 rte_errno = ENOTSUP;
236                 return -1;
237         }
238
239         fctret = eal_parse_args(argc, argv);
240         if (fctret < 0)
241                 exit(1);
242
243         eal_thread_init_master(rte_config.master_lcore);
244
245         RTE_LCORE_FOREACH_SLAVE(i) {
246
247                 /*
248                  * create communication pipes between master thread
249                  * and children
250                  */
251                 if (_pipe(lcore_config[i].pipe_master2slave,
252                         sizeof(char), _O_BINARY) < 0)
253                         rte_panic("Cannot create pipe\n");
254                 if (_pipe(lcore_config[i].pipe_slave2master,
255                         sizeof(char), _O_BINARY) < 0)
256                         rte_panic("Cannot create pipe\n");
257
258                 lcore_config[i].state = WAIT;
259
260                 /* create a thread for each lcore */
261                 if (eal_thread_create(&lcore_config[i].thread_id) != 0)
262                         rte_panic("Cannot create thread\n");
263         }
264
265         /*
266          * Launch a dummy function on all slave lcores, so that master lcore
267          * knows they are all ready when this function returns.
268          */
269         rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
270         rte_eal_mp_wait_lcore();
271         return fctret;
272 }