1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019 Intel Corporation
10 #include <rte_debug.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>
21 /* Allow the application to print its usage message too if set */
22 static rte_usage_hook_t rte_application_usage_hook;
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
27 static int mem_cfg_fd = -1;
29 /* early configuration structure, when memory config is not mmapped */
30 static struct rte_mem_config early_mem_config;
32 /* Address of global and public configuration */
33 static struct rte_config rte_config = {
34 .mem_config = &early_mem_config,
37 /* internal configuration (per-core) */
38 struct lcore_config lcore_config[RTE_MAX_LCORE];
40 /* internal configuration */
41 struct internal_config internal_config;
43 /* platform-specific runtime dir */
44 static char runtime_dir[PATH_MAX];
47 rte_eal_get_runtime_dir(void)
52 /* Return a pointer to the configuration structure */
54 rte_eal_get_configuration(void)
59 /* Detect if we are a primary or a secondary process */
61 eal_proc_type_detect(void)
63 enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
64 const char *pathname = eal_runtime_config_path();
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
70 errno_t err = _sopen_s(&mem_cfg_fd, pathname,
71 _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
73 OVERLAPPED soverlapped = { 0 };
74 soverlapped.Offset = sizeof(*rte_config.mem_config);
75 soverlapped.OffsetHigh = 0;
77 HANDLE hwinfilehandle = (HANDLE)_get_osfhandle(mem_cfg_fd);
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;
85 RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n",
86 ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY");
93 eal_usage(const char *prgname)
95 printf("\nUsage: %s ", prgname);
97 /* Allow the application to print its usage message too
100 if (rte_application_usage_hook) {
101 printf("===== Application Usage =====\n\n");
102 rte_application_usage_hook(prgname);
106 /* Parse the arguments for --log-level only */
108 eal_log_level_parse(int argc, char **argv)
116 eal_reset_internal_config(&internal_config);
118 while ((opt = getopt_long(argc, argvopt, eal_short_options,
119 eal_long_options, &option_index)) != EOF) {
123 /* getopt is not happy, stop right now */
127 ret = (opt == OPT_LOG_LEVEL_NUM) ?
128 eal_parse_common_option(opt, optarg,
129 &internal_config) : 0;
131 /* common parser is not happy */
136 optind = 0; /* reset getopt lib */
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)
146 char *prgname = argv[0];
150 while ((opt = getopt_long(argc, argvopt, eal_short_options,
151 eal_long_options, &option_index)) != EOF) {
155 /* getopt is not happy, stop right now */
161 ret = eal_parse_common_option(opt, optarg, &internal_config);
162 /* common parser is not happy */
167 /* common parser handled this option */
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 "
183 eal_long_options[option_index].name);
185 RTE_LOG(ERR, EAL, "Option %d is not supported "
186 "on Windows\n", opt);
193 if (eal_adjust_config(&internal_config) != 0)
197 if (eal_check_common_options(&internal_config) != 0) {
203 argv[optind - 1] = prgname;
205 optind = 0; /* reset getopt lib */
210 sync_func(void *arg __rte_unused)
216 rte_eal_init_alert(const char *msg)
218 fprintf(stderr, "EAL: FATAL: %s\n", msg);
219 RTE_LOG(ERR, EAL, "%s\n", msg);
222 /* Launch threads, called at application init(). */
224 rte_eal_init(int argc, char **argv)
228 eal_log_level_parse(argc, argv);
230 /* create a map of all processors in the system */
231 eal_create_cpu_map();
233 if (rte_eal_cpu_init() < 0) {
234 rte_eal_init_alert("Cannot detect lcores.");
239 fctret = eal_parse_args(argc, argv);
243 eal_thread_init_master(rte_config.master_lcore);
245 RTE_LCORE_FOREACH_SLAVE(i) {
248 * create communication pipes between master thread
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");
258 lcore_config[i].state = WAIT;
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");
266 * Launch a dummy function on all slave lcores, so that master lcore
267 * knows they are all ready when this function returns.
269 rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
270 rte_eal_mp_wait_lcore();