diff options
Diffstat (limited to 'src/spdk/dpdk/lib/librte_eal/windows')
20 files changed, 2801 insertions, 0 deletions
diff --git a/src/spdk/dpdk/lib/librte_eal/windows/eal.c b/src/spdk/dpdk/lib/librte_eal/windows/eal.c new file mode 100644 index 000000000..d084606a6 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/eal.c @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include <fcntl.h> +#include <io.h> +#include <share.h> +#include <sys/stat.h> + +#include <rte_debug.h> +#include <rte_eal.h> +#include <eal_memcfg.h> +#include <rte_errno.h> +#include <rte_lcore.h> +#include <eal_thread.h> +#include <eal_internal_cfg.h> +#include <eal_filesystem.h> +#include <eal_options.h> +#include <eal_private.h> + +#include "eal_windows.h" + + /* Allow the application to print its usage message too if set */ +static rte_usage_hook_t rte_application_usage_hook; + +/* define fd variable here, because file needs to be kept open for the + * duration of the program, as we hold a write lock on it in the primary proc + */ +static int mem_cfg_fd = -1; + +/* early configuration structure, when memory config is not mmapped */ +static struct rte_mem_config early_mem_config; + +/* Address of global and public configuration */ +static struct rte_config rte_config = { + .mem_config = &early_mem_config, +}; + +/* internal configuration (per-core) */ +struct lcore_config lcore_config[RTE_MAX_LCORE]; + +/* internal configuration */ +struct internal_config internal_config; + +/* platform-specific runtime dir */ +static char runtime_dir[PATH_MAX]; + +const char * +rte_eal_get_runtime_dir(void) +{ + return runtime_dir; +} + +/* Return a pointer to the configuration structure */ +struct rte_config * +rte_eal_get_configuration(void) +{ + return &rte_config; +} + +/* Detect if we are a primary or a secondary process */ +enum rte_proc_type_t +eal_proc_type_detect(void) +{ + enum rte_proc_type_t ptype = RTE_PROC_PRIMARY; + const char *pathname = eal_runtime_config_path(); + + /* if we can open the file but not get a write-lock we are a secondary + * process. NOTE: if we get a file handle back, we keep that open + * and don't close it to prevent a race condition between multiple opens + */ + errno_t err = _sopen_s(&mem_cfg_fd, pathname, + _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE); + if (err == 0) { + OVERLAPPED soverlapped = { 0 }; + soverlapped.Offset = sizeof(*rte_config.mem_config); + soverlapped.OffsetHigh = 0; + + HANDLE hwinfilehandle = (HANDLE)_get_osfhandle(mem_cfg_fd); + + if (!LockFileEx(hwinfilehandle, + LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, + sizeof(*rte_config.mem_config), 0, &soverlapped)) + ptype = RTE_PROC_SECONDARY; + } + + RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n", + ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY"); + + return ptype; +} + +/* display usage */ +static void +eal_usage(const char *prgname) +{ + printf("\nUsage: %s ", prgname); + eal_common_usage(); + /* Allow the application to print its usage message too + * if hook is set + */ + if (rte_application_usage_hook) { + printf("===== Application Usage =====\n\n"); + rte_application_usage_hook(prgname); + } +} + +/* Parse the arguments for --log-level only */ +static void +eal_log_level_parse(int argc, char **argv) +{ + int opt; + char **argvopt; + int option_index; + + argvopt = argv; + + eal_reset_internal_config(&internal_config); + + while ((opt = getopt_long(argc, argvopt, eal_short_options, + eal_long_options, &option_index)) != EOF) { + + int ret; + + /* getopt is not happy, stop right now */ + if (opt == '?') + break; + + ret = (opt == OPT_LOG_LEVEL_NUM) ? + eal_parse_common_option(opt, optarg, + &internal_config) : 0; + + /* common parser is not happy */ + if (ret < 0) + break; + } + + optind = 0; /* reset getopt lib */ +} + +/* Parse the argument given in the command line of the application */ +__attribute__((optnone)) static int +eal_parse_args(int argc, char **argv) +{ + int opt, ret; + char **argvopt; + int option_index; + char *prgname = argv[0]; + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, eal_short_options, + eal_long_options, &option_index)) != EOF) { + + int ret; + + /* getopt is not happy, stop right now */ + if (opt == '?') { + eal_usage(prgname); + return -1; + } + + ret = eal_parse_common_option(opt, optarg, &internal_config); + /* common parser is not happy */ + if (ret < 0) { + eal_usage(prgname); + return -1; + } + /* common parser handled this option */ + if (ret == 0) + continue; + + switch (opt) { + case 'h': + eal_usage(prgname); + exit(EXIT_SUCCESS); + default: + if (opt < OPT_LONG_MIN_NUM && isprint(opt)) { + RTE_LOG(ERR, EAL, "Option %c is not supported " + "on Windows\n", opt); + } else if (opt >= OPT_LONG_MIN_NUM && + opt < OPT_LONG_MAX_NUM) { + RTE_LOG(ERR, EAL, "Option %s is not supported " + "on Windows\n", + eal_long_options[option_index].name); + } else { + RTE_LOG(ERR, EAL, "Option %d is not supported " + "on Windows\n", opt); + } + eal_usage(prgname); + return -1; + } + } + + if (eal_adjust_config(&internal_config) != 0) + return -1; + + /* sanity checks */ + if (eal_check_common_options(&internal_config) != 0) { + eal_usage(prgname); + return -1; + } + + if (optind >= 0) + argv[optind - 1] = prgname; + ret = optind - 1; + optind = 0; /* reset getopt lib */ + return ret; +} + +static int +sync_func(void *arg __rte_unused) +{ + return 0; +} + +static void +rte_eal_init_alert(const char *msg) +{ + fprintf(stderr, "EAL: FATAL: %s\n", msg); + RTE_LOG(ERR, EAL, "%s\n", msg); +} + + /* Launch threads, called at application init(). */ +int +rte_eal_init(int argc, char **argv) +{ + int i, fctret; + + rte_eal_log_init(NULL, 0); + + eal_log_level_parse(argc, argv); + + /* create a map of all processors in the system */ + eal_create_cpu_map(); + + if (rte_eal_cpu_init() < 0) { + rte_eal_init_alert("Cannot detect lcores."); + rte_errno = ENOTSUP; + return -1; + } + + fctret = eal_parse_args(argc, argv); + if (fctret < 0) + exit(1); + + eal_thread_init_master(rte_config.master_lcore); + + RTE_LCORE_FOREACH_SLAVE(i) { + + /* + * create communication pipes between master thread + * and children + */ + if (_pipe(lcore_config[i].pipe_master2slave, + sizeof(char), _O_BINARY) < 0) + rte_panic("Cannot create pipe\n"); + if (_pipe(lcore_config[i].pipe_slave2master, + sizeof(char), _O_BINARY) < 0) + rte_panic("Cannot create pipe\n"); + + lcore_config[i].state = WAIT; + + /* create a thread for each lcore */ + if (eal_thread_create(&lcore_config[i].thread_id) != 0) + rte_panic("Cannot create thread\n"); + } + + /* + * Launch a dummy function on all slave lcores, so that master lcore + * knows they are all ready when this function returns. + */ + rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER); + rte_eal_mp_wait_lcore(); + return fctret; +} diff --git a/src/spdk/dpdk/lib/librte_eal/windows/eal_debug.c b/src/spdk/dpdk/lib/librte_eal/windows/eal_debug.c new file mode 100644 index 000000000..669be6ff9 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/eal_debug.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include <stdarg.h> +#include <rte_log.h> +#include <rte_debug.h> + + /* call abort(), it will generate a coredump if enabled */ +void +__rte_panic(const char *funcname, const char *format, ...) +{ + va_list ap; + + rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n", funcname); + va_start(ap, format); + rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap); + va_end(ap); + abort(); +} diff --git a/src/spdk/dpdk/lib/librte_eal/windows/eal_lcore.c b/src/spdk/dpdk/lib/librte_eal/windows/eal_lcore.c new file mode 100644 index 000000000..82ee45413 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/eal_lcore.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include <pthread.h> +#include <stdint.h> + +#include <rte_common.h> + +#include "eal_private.h" +#include "eal_thread.h" +#include "eal_windows.h" + +/* global data structure that contains the CPU map */ +static struct _wcpu_map { + unsigned int total_procs; + unsigned int proc_sockets; + unsigned int proc_cores; + unsigned int reserved; + struct _win_lcore_map { + uint8_t socket_id; + uint8_t core_id; + } wlcore_map[RTE_MAX_LCORE]; +} wcpu_map = { 0 }; + +/* + * Create a map of all processors and associated cores on the system + */ +void +eal_create_cpu_map() +{ + wcpu_map.total_procs = + GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); + + LOGICAL_PROCESSOR_RELATIONSHIP lprocRel; + DWORD lprocInfoSize = 0; + BOOL ht_enabled = FALSE; + + /* First get the processor package information */ + lprocRel = RelationProcessorPackage; + /* Determine the size of buffer we need (pass NULL) */ + GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize); + wcpu_map.proc_sockets = lprocInfoSize / 48; + + lprocInfoSize = 0; + /* Next get the processor core information */ + lprocRel = RelationProcessorCore; + GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize); + wcpu_map.proc_cores = lprocInfoSize / 48; + + if (wcpu_map.total_procs > wcpu_map.proc_cores) + ht_enabled = TRUE; + + /* Distribute the socket and core ids appropriately + * across the logical cores. For now, split the cores + * equally across the sockets. + */ + unsigned int lcore = 0; + for (unsigned int socket = 0; socket < + wcpu_map.proc_sockets; ++socket) { + for (unsigned int core = 0; + core < (wcpu_map.proc_cores / wcpu_map.proc_sockets); + ++core) { + wcpu_map.wlcore_map[lcore] + .socket_id = socket; + wcpu_map.wlcore_map[lcore] + .core_id = core; + lcore++; + if (ht_enabled) { + wcpu_map.wlcore_map[lcore] + .socket_id = socket; + wcpu_map.wlcore_map[lcore] + .core_id = core; + lcore++; + } + } + } +} + +/* + * Check if a cpu is present by the presence of the cpu information for it + */ +int +eal_cpu_detected(unsigned int lcore_id) +{ + return (lcore_id < wcpu_map.total_procs); +} + +/* + * Get CPU socket id for a logical core + */ +unsigned +eal_cpu_socket_id(unsigned int lcore_id) +{ + return wcpu_map.wlcore_map[lcore_id].socket_id; +} + +/* + * Get CPU socket id (NUMA node) for a logical core + */ +unsigned +eal_cpu_core_id(unsigned int lcore_id) +{ + return wcpu_map.wlcore_map[lcore_id].core_id; +} diff --git a/src/spdk/dpdk/lib/librte_eal/windows/eal_log.c b/src/spdk/dpdk/lib/librte_eal/windows/eal_log.c new file mode 100644 index 000000000..875981f13 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/eal_log.c @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#include "eal_private.h" + +/* set the log to default function, called during eal init process. */ +int +rte_eal_log_init(__rte_unused const char *id, __rte_unused int facility) +{ + rte_openlog_stream(stderr); + + eal_log_set_default(stderr); + + return 0; +} diff --git a/src/spdk/dpdk/lib/librte_eal/windows/eal_thread.c b/src/spdk/dpdk/lib/librte_eal/windows/eal_thread.c new file mode 100644 index 000000000..e149199a6 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/eal_thread.c @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include <io.h> + +#include <rte_atomic.h> +#include <rte_debug.h> +#include <rte_launch.h> +#include <rte_lcore.h> +#include <rte_per_lcore.h> +#include <rte_common.h> +#include <rte_memory.h> +#include <eal_thread.h> + +#include "eal_private.h" +#include "eal_windows.h" + +RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY; +RTE_DEFINE_PER_LCORE(unsigned int, _socket_id) = (unsigned int)SOCKET_ID_ANY; +RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); + +/* + * Send a message to a slave lcore identified by slave_id to call a + * function f with argument arg. Once the execution is done, the + * remote lcore switch in FINISHED state. + */ +int +rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned int slave_id) +{ + int n; + char c = 0; + int m2s = lcore_config[slave_id].pipe_master2slave[1]; + int s2m = lcore_config[slave_id].pipe_slave2master[0]; + + if (lcore_config[slave_id].state != WAIT) + return -EBUSY; + + lcore_config[slave_id].f = f; + lcore_config[slave_id].arg = arg; + + /* send message */ + n = 0; + while (n == 0 || (n < 0 && errno == EINTR)) + n = _write(m2s, &c, 1); + if (n < 0) + rte_panic("cannot write on configuration pipe\n"); + + /* wait ack */ + do { + n = _read(s2m, &c, 1); + } while (n < 0 && errno == EINTR); + + if (n <= 0) + rte_panic("cannot read on configuration pipe\n"); + + return 0; +} + +void +eal_thread_init_master(unsigned int lcore_id) +{ + /* set the lcore ID in per-lcore memory area */ + RTE_PER_LCORE(_lcore_id) = lcore_id; +} + +static inline pthread_t +eal_thread_self(void) +{ + return GetCurrentThreadId(); +} + +/* main loop of threads */ +void * +eal_thread_loop(void *arg __rte_unused) +{ + char c; + int n, ret; + unsigned int lcore_id; + pthread_t thread_id; + int m2s, s2m; + char cpuset[RTE_CPU_AFFINITY_STR_LEN]; + + thread_id = eal_thread_self(); + + /* retrieve our lcore_id from the configuration structure */ + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (thread_id == lcore_config[lcore_id].thread_id) + break; + } + if (lcore_id == RTE_MAX_LCORE) + rte_panic("cannot retrieve lcore id\n"); + + m2s = lcore_config[lcore_id].pipe_master2slave[0]; + s2m = lcore_config[lcore_id].pipe_slave2master[1]; + + /* set the lcore ID in per-lcore memory area */ + RTE_PER_LCORE(_lcore_id) = lcore_id; + + RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%zx;cpuset=[%s])\n", + lcore_id, (uintptr_t)thread_id, cpuset); + + /* read on our pipe to get commands */ + while (1) { + void *fct_arg; + + /* wait command */ + do { + n = _read(m2s, &c, 1); + } while (n < 0 && errno == EINTR); + + if (n <= 0) + rte_panic("cannot read on configuration pipe\n"); + + lcore_config[lcore_id].state = RUNNING; + + /* send ack */ + n = 0; + while (n == 0 || (n < 0 && errno == EINTR)) + n = _write(s2m, &c, 1); + if (n < 0) + rte_panic("cannot write on configuration pipe\n"); + + if (lcore_config[lcore_id].f == NULL) + rte_panic("NULL function pointer\n"); + + /* call the function and store the return value */ + fct_arg = lcore_config[lcore_id].arg; + ret = lcore_config[lcore_id].f(fct_arg); + lcore_config[lcore_id].ret = ret; + rte_wmb(); + + /* when a service core returns, it should go directly to WAIT + * state, because the application will not lcore_wait() for it. + */ + if (lcore_config[lcore_id].core_role == ROLE_SERVICE) + lcore_config[lcore_id].state = WAIT; + else + lcore_config[lcore_id].state = FINISHED; + } +} + +/* function to create threads */ +int +eal_thread_create(pthread_t *thread) +{ + HANDLE th; + + th = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)eal_thread_loop, + NULL, 0, (LPDWORD)thread); + if (!th) + return -1; + + SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + SetThreadPriority(th, THREAD_PRIORITY_TIME_CRITICAL); + + return 0; +} + +int +rte_thread_setname(__rte_unused pthread_t id, __rte_unused const char *name) +{ + /* TODO */ + /* This is a stub, not the expected result */ + return 0; +} diff --git a/src/spdk/dpdk/lib/librte_eal/windows/eal_windows.h b/src/spdk/dpdk/lib/librte_eal/windows/eal_windows.h new file mode 100644 index 000000000..fadd676b2 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/eal_windows.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2020 Dmitry Kozlyuk + */ + +#ifndef _EAL_WINDOWS_H_ +#define _EAL_WINDOWS_H_ + +/** + * @file Facilities private to Windows EAL + */ + +#include <rte_windows.h> + +/** + * Create a map of processors and cores on the system. + */ +void eal_create_cpu_map(void); + +/** + * Create a thread. + * + * @param thread + * The location to store the thread id if successful. + * @return + * 0 for success, -1 if the thread is not created. + */ +int eal_thread_create(pthread_t *thread); + +#endif /* _EAL_WINDOWS_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/fnmatch.c b/src/spdk/dpdk/lib/librte_eal/windows/fnmatch.c new file mode 100644 index 000000000..f622bf54c --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/fnmatch.c @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +#include <ctype.h> +#include <string.h> +#include <stdio.h> + +#include "fnmatch.h" + +#define EOS '\0' + +static const char *rangematch(const char *, char, int); + +int +fnmatch(const char *pattern, const char *string, int flags) +{ + const char *stringstart; + char c, test; + + for (stringstart = string;;) + switch (c = *pattern++) { + case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return (0); + return (*string == EOS ? 0 : FNM_NOMATCH); + case '?': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + ++string; + break; + case '*': + c = *pattern; + /* Collapse multiple stars. */ + while (c == '*') + c = *++pattern; + + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + else if (c == '/' && flags & FNM_PATHNAME) { + string = strchr(string, '/'); + if (string == NULL) + return (FNM_NOMATCH); + break; + } + + /* General case, use recursion. */ + while ((test = *string) != EOS) { + if (!fnmatch(pattern, string, + flags & ~FNM_PERIOD)) + return (0); + if (test == '/' && flags & FNM_PATHNAME) + break; + ++string; + } + return (FNM_NOMATCH); + case '[': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && flags & FNM_PATHNAME) + return (FNM_NOMATCH); + pattern = rangematch(pattern, *string, flags); + if (pattern == NULL) + return (FNM_NOMATCH); + ++string; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + c = *pattern++; + if (c == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + if (c == *string) + ; + else if ((flags & FNM_CASEFOLD) && + (tolower((unsigned char)c) == + tolower((unsigned char)*string))) + ; + else if ((flags & FNM_PREFIX_DIRS) && *string == EOS && + ((c == '/' && string != stringstart) || + (string == stringstart+1 && *stringstart == '/'))) + return (0); + else + return (FNM_NOMATCH); + string++; + break; + } + /* NOTREACHED */ +} + +static const char * +rangematch(const char *pattern, char test, int flags) +{ + int negate, ok; + char c, c2; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + negate = (*pattern == '!' || *pattern == '^'); + if (negate) + ++pattern; + + if (flags & FNM_CASEFOLD) + test = tolower((unsigned char)test); + + for (ok = 0; (c = *pattern++) != ']';) { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *pattern++; + if (c == EOS) + return (NULL); + + if (flags & FNM_CASEFOLD) + c = tolower((unsigned char)c); + + c2 = *(pattern + 1); + if (*pattern == '-' && c2 != EOS && c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = *pattern++; + if (c2 == EOS) + return (NULL); + + if (flags & FNM_CASEFOLD) + c2 = tolower((unsigned char)c2); + + if ((unsigned char)c <= (unsigned char)test && + (unsigned char)test <= (unsigned char)c2) + ok = 1; + } else if (c == test) + ok = 1; + } + return (ok == negate ? NULL : pattern); +} diff --git a/src/spdk/dpdk/lib/librte_eal/windows/getopt.c b/src/spdk/dpdk/lib/librte_eal/windows/getopt.c new file mode 100644 index 000000000..170c9b5e0 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/getopt.c @@ -0,0 +1,470 @@ +/* SPDX-License-Identifier: ISC AND BSD-2-Clause + * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/* + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + */ + +#include <getopt.h> + +#ifdef NEED_USUAL_GETOPT + +#include <string.h> +#include <stdlib.h> + +const char *optarg; /* argument associated with option */ +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ + +static void pass(void) {} +#define warnx(a, ...) pass() + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH ((int)'?') +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER 1 + +#define EMSG "" + +static const char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char **nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char **nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + const char *current_argv; + char *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + + has_equal = strchr(current_argv, '='); + if (has_equal != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return BADCH; + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return BADARG; + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return BADARG; + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return BADCH; + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return 0; + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char **nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + char *buf; + size_t len; + int optreset = 0; + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1) + posixly_correct = _dupenv_s(&buf, &len, "POSIXLY_CORRECT"); + if (!posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; + if (!posixly_correct) + free(buf); + /* + * reset if requested + */ + if (optind == 0) + optind = optreset = 1; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + place = nargv[optind]; + if (*place != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return INORDER; + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return optchar; + } + } + + optchar = (int)*place++; + oli = strchr(options, optchar); + if (optchar == (int)':' || + (optchar == (int)'-' && *place != '\0') || + oli == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return BADCH; + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) + ; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return BADARG; + } /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return optchar; + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return BADARG; + } + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return optchar; +} + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +getopt(int nargc, char *nargv[], const char *options) +{ + return getopt_internal(nargc, nargv, options, NULL, NULL, + FLAG_PERMUTE); +} + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char *nargv[], const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char *nargv[], const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} + +#endif /* NEED_USUAL_GETOPT */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/dirent.h b/src/spdk/dpdk/lib/librte_eal/windows/include/dirent.h new file mode 100644 index 000000000..869a59837 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/dirent.h @@ -0,0 +1,664 @@ +/* SPDX-License-Identifier: MIT + * Dirent interface for Microsoft Visual Studio + * Version 1.21 + * Copyright (C) 2006-2012 Toni Ronkko + * https://github.com/tronkko/dirent + */ + +#ifndef DIRENT_H +#define DIRENT_H + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> + +#include <stdio.h> +#include <stdarg.h> +#include <wchar.h> +#include <string.h> +#include <stdlib.h> +#include <malloc.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_CHR S_IFCHR + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +static _WDIR *_wopendir(const wchar_t *dirname); +static int _wclosedir(_WDIR *dirp); + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wclosedir _wclosedir + +/* Multi-byte character versions */ +struct dirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + +static DIR *opendir(const char *dirname); +static struct dirent *readdir(DIR *dirp); +static int closedir(DIR *dirp); + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno(int error); + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir(const wchar_t *dirname) +{ + _WDIR *dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR *)malloc(sizeof(struct _WDIR)); + if (dirp != NULL) { + DWORD n; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ + #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + n = wcslen(dirname); + #else + n = GetFullPathNameW(dirname, 0, NULL, NULL); + #endif + + /* Allocate room for absolute directory name and search + * pattern + */ + dirp->patt = (wchar_t *)malloc(sizeof(wchar_t) * n + 16); + if (dirp->patt) { + /* Convert relative directory name to an + * absolute one. This allows rewinddir() to + * function correctly even when current working + * directory is changed between opendir() + * and rewinddir(). + * + * Note that on WinRT there's no way to convert + * relative paths into absolute paths, so just + * assume its an absolute path. + */ + #if defined(WINAPI_FAMILY) && \ + (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + wcsncpy_s(dirp->patt, n + 1, dirname, n); + #else + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); + #endif + if (n > 0) { + wchar_t *p; + + /* Append search pattern \* to the directory + * name + */ + p = dirp->patt + n; + if (dirp->patt < p) { + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, + * e.g.c:\temp\ + */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path + * separator + */ + *p++ = '\\'; + } + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first + * entry + */ + if (dirent_first(dirp)) { + /* Directory stream opened successfully */ + error = 0; + } else { + /* Cannot retrieve first entry */ + error = 1; + dirent_set_errno(ENOENT); + } + + } else { + /* Cannot retrieve full path name */ + dirent_set_errno(ENOENT); + error = 1; + } + + } else { + /* Cannot allocate memory for search pattern */ + error = 1; + } + + } else { + /* Cannot allocate _WDIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + _wclosedir(dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Close directory stream opened by opendir() function. + * This invalidates the DIR structure as well as any directory + * entry read previously by _wreaddir(). + */ +static int +_wclosedir(_WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + /* Release search pattern */ + if (dirp->patt) { + free(dirp->patt); + dirp->patt = NULL; + } + + /* Release directory structure */ + free(dirp); + ok = /*success*/0; + + } else { + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; + } + return ok; +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first(_WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + } + return datap; +} + +/* Get next directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_next(_WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed + *or an error occurred + */ + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir(const char *dirname) +{ + struct DIR *dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR *)malloc(sizeof(struct DIR)); + if (dirp) { + wchar_t wname[PATH_MAX]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s(&n, wname, PATH_MAX, + dirname, PATH_MAX); + if (!error) { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir(wname); + if (dirp->wdirp) { + /* Directory stream opened */ + error = 0; + } else { + /* Failed to open directory stream */ + error = 1; + } + + } else { + /* + * Cannot convert file name to wide-character string. + * This occurs if the string contains invalid multi-byte + * sequences or the output buffer is too small to + * contain the resulting string. + */ + error = 1; + } + + } else { + /* Cannot allocate DIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + free(dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Read next directory entry. + * + * When working with text consoles, please note that file names + * returned by readdir() are represented in the default ANSI code + * page while any output toconsole is typically formatted on another + * code page. Thus, non-ASCII characters in file names will not usually + * display correctly on console. The problem can be fixed in two ways: + * (1) change the character set of console to 1252 using chcp utility + * and use Lucida Console font, or (2) use _cprintf function when + * writing to console. The _cprinf() will re-encode ANSI strings to the + * console code page so many non-ASCII characters will display correctly. + */ +static struct dirent* +readdir(DIR *dirp) +{ + WIN32_FIND_DATAW *datap; + struct dirent *entp; + + /* Read next directory entry */ + datap = dirent_next(dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s(&n, dirp->ent.d_name, + PATH_MAX, datap->cFileName, PATH_MAX); + + /* + * If the file name cannot be represented by a multi-byte + * string, then attempt to use old 8+3 file name. + * This allows traditional Unix-code to access some file + * names despite of unicode characters, although file names + * may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short + * file name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, + datap->cAlternateFileName, PATH_MAX); + } + + if (!error) { + DWORD attr; + + /* Initialize directory entry for return */ + entp = &dirp->ent; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) + entp->d_type = DT_CHR; + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + entp->d_type = DT_DIR; + else + entp->d_type = DT_REG; + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof(struct dirent); + + } else { + /* + * Cannot convert file name to multi-byte string so + * construct an erroneous directory entry and return + * that. Note that we cannot return NULL as that would + * stop the processing of directory entries completely. + */ + entp = &dirp->ent; + entp->d_name[0] = '?'; + entp->d_name[1] = '\0'; + entp->d_namlen = 1; + entp->d_type = DT_UNKNOWN; + entp->d_ino = 0; + entp->d_reclen = 0; + } + + } else { + /* No more directory entries */ + entp = NULL; + } + + return entp; +} + +/* + * Close directory stream. + */ +static int +closedir(DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir(dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free(dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + + #if defined(_MSC_VER) && _MSC_VER >= 1400 + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s(pReturnValue, wcstr, + sizeInWords, mbstr, count); + #else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs(wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) + n = sizeInWords - 1; + wcstr[n] = 0; + } + + /* Length of resuting multi-byte string WITH zero + *terminator + */ + if (pReturnValue) + *pReturnValue = n + 1; + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + #endif + + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + + #if defined(_MSC_VER) && _MSC_VER >= 1400 + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count); + #else + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string + * (or count the number of bytes needed) + */ + n = wcstombs(mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) + n = sizeInBytes - 1; + mbstr[n] = '\0'; + } + /* Length of resulting multi-bytes string WITH + *zero-terminator + */ + if (pReturnValue) + *pReturnValue = n + 1; + /* Success */ + error = 0; + } else { + /* Cannot convert string */ + error = 1; + } + #endif + + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno(int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + /* Microsoft Visual Studio 2005 and later */ + _set_errno(error); +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; +#endif +} + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/fnmatch.h b/src/spdk/dpdk/lib/librte_eal/windows/include/fnmatch.h new file mode 100644 index 000000000..142753c35 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/fnmatch.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef _FNMATCH_H_ +#define _FNMATCH_H_ + +/** + * This file is required to support the common code in eal_common_log.c + * as Microsoft libc does not contain fnmatch.h. This may be removed in + * future releases. + */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <rte_common.h> + +#define FNM_NOMATCH 1 + +#define FNM_NOESCAPE 0x01 +#define FNM_PATHNAME 0x02 +#define FNM_PERIOD 0x04 +#define FNM_LEADING_DIR 0x08 +#define FNM_CASEFOLD 0x10 +#define FNM_PREFIX_DIRS 0x20 + +/** + * This function is used for searhing a given string source + * with the given regular expression pattern. + * + * @param pattern + * regular expression notation decribing the pattern to match + * + * @param string + * source string to searcg for the pattern + * + * @param flag + * containing information about the pattern + * + * @return + * if the pattern is found then return 0 or else FNM_NOMATCH + */ +int fnmatch(const char *pattern, const char *string, int flags); + +#ifdef __cplusplus +} +#endif + +#endif /* _FNMATCH_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/getopt.h b/src/spdk/dpdk/lib/librte_eal/windows/include/getopt.h new file mode 100644 index 000000000..6f57af454 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/getopt.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-2-Clause + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + */ + +/** + * @file + * getopt compat. + * + * This module provides getopt() and getopt_long(). + */ + +#ifndef _USUAL_GETOPT_H_ +#define _USUAL_GETOPT_H_ + +#ifndef NEED_USUAL_GETOPT +#if !defined(HAVE_GETOPT_H) || !defined(HAVE_GETOPT) || \ + !defined(HAVE_GETOPT_LONG) +#define NEED_USUAL_GETOPT +#endif +#endif + +#ifndef NEED_USUAL_GETOPT + +/* Use system getopt */ +#ifdef RTE_TOOLCHAIN_GCC +#include_next <getopt.h> +#else +#include <getopt.h> +#endif + +#else /* NEED_USUAL_GETOPT */ + +/* avoid name collision */ +#define optarg usual_optarg +#define opterr usual_opterr +#define optind usual_optind +#define optopt usual_optopt +#define getopt(a, b, c) usual_getopt(a, b, c) +#define getopt_long(a, b, c, d, e) usual_getopt_long(a, b, c, d, e) + + +/** argument to current option, or NULL if it has none */ +extern const char *optarg; +/** Current position in arg string. Starts from 1. + * Setting to 0 resets state. + */ +extern int optind; +/** whether getopt() should print error messages on problems. Default: 1. */ +extern int opterr; +/** Option char which caused error */ +extern int optopt; + +/** long option takes no argument */ +#define no_argument 0 +/** long option requires argument */ +#define required_argument 1 +/** long option has optional argument */ +#define optional_argument 2 + +/** Long option description */ +struct option { + /** name of long option */ + const char *name; + + /** + * whether option takes an argument. + * One of no_argument, required_argument, and optional_argument. + */ + int has_arg; + + /** if not NULL, set *flag to val when option found */ + int *flag; + + /** if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +/** Compat: getopt */ +int getopt(int argc, char *argv[], const char *options); + +/** Compat: getopt_long */ +int getopt_long(int argc, char *argv[], const char *options, + const struct option *longopts, int *longindex); + +/** Compat: getopt_long_only */ +int getopt_long_only(int nargc, char *argv[], const char *options, + const struct option *long_options, int *idx); + + +#endif /* NEED_USUAL_GETOPT */ + +#endif /* !_USUAL_GETOPT_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/meson.build b/src/spdk/dpdk/lib/librte_eal/windows/include/meson.build new file mode 100644 index 000000000..5fb1962ac --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/meson.build @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2020 Mellanox Technologies, Ltd + +includes += include_directories('.') + +headers += files( + 'rte_os.h', + 'rte_windows.h', +) diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/pthread.h b/src/spdk/dpdk/lib/librte_eal/windows/include/pthread.h new file mode 100644 index 000000000..0bbed5c3b --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/pthread.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef _PTHREAD_H_ +#define _PTHREAD_H_ + +#include <stdint.h> + +/** + * This file is required to support the common code in eal_common_proc.c, + * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc + * does not contain pthread.h. This may be removed in future releases. + */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <windows.h> +#include <rte_common.h> + +#define PTHREAD_BARRIER_SERIAL_THREAD TRUE + +/* defining pthread_t type on Windows since there is no in Microsoft libc*/ +typedef uintptr_t pthread_t; + +/* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/ +typedef void *pthread_attr_t; + +typedef SYNCHRONIZATION_BARRIER pthread_barrier_t; + +#define pthread_barrier_init(barrier, attr, count) \ + InitializeSynchronizationBarrier(barrier, count, -1) +#define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \ + SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY) +#define pthread_barrier_destroy(barrier) \ + DeleteSynchronizationBarrier(barrier) +#define pthread_cancel(thread) TerminateThread((HANDLE) thread, 0) + +/* pthread function overrides */ +#define pthread_self() \ + ((pthread_t)GetCurrentThreadId()) +#define pthread_setaffinity_np(thread, size, cpuset) \ + eal_set_thread_affinity_mask(thread, (unsigned long *) cpuset) +#define pthread_getaffinity_np(thread, size, cpuset) \ + eal_get_thread_affinity_mask(thread, (unsigned long *) cpuset) +#define pthread_create(threadid, threadattr, threadfunc, args) \ + eal_create_thread(threadid, threadfunc, args) + +static inline int +eal_set_thread_affinity_mask(pthread_t threadid, unsigned long *cpuset) +{ + SetThreadAffinityMask((HANDLE) threadid, *cpuset); + return 0; +} + +static inline int +eal_get_thread_affinity_mask(pthread_t threadid, unsigned long *cpuset) +{ + /* Workaround for the lack of a GetThreadAffinityMask() + *API in Windows + */ + /* obtain previous mask by setting dummy mask */ + DWORD dwprevaffinitymask = + SetThreadAffinityMask((HANDLE) threadid, 0x1); + /* set it back! */ + SetThreadAffinityMask((HANDLE) threadid, dwprevaffinitymask); + *cpuset = dwprevaffinitymask; + return 0; +} + +static inline int +eal_create_thread(void *threadid, void *threadfunc, void *args) +{ + HANDLE hThread; + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc, + args, 0, (LPDWORD)threadid); + if (hThread) { + SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); + } + return ((hThread != NULL) ? 0 : E_FAIL); +} + +static inline int +pthread_join(__rte_unused pthread_t thread, + __rte_unused void **value_ptr) +{ + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _PTHREAD_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/regex.h b/src/spdk/dpdk/lib/librte_eal/windows/include/regex.h new file mode 100644 index 000000000..827f93841 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/regex.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef _REGEX_H_ +#define _REGEX_H_ + +/** + * This file is required to support the common code in eal_common_log.c + * as Microsoft libc does not contain regex.h. This may be removed in + * future releases. + */ +#ifdef __cplusplus +extern "C" { +#endif + +#define REG_NOMATCH 1 +#define REG_ESPACE 12 + +#include <rte_common.h> + +/* defining regex_t for Windows */ +typedef void *regex_t; +/* defining regmatch_t for Windows */ +typedef void *regmatch_t; + +/** + * The regcomp() function will compile the regular expression + * contained in the string pointed to by the pattern argument + * and place the results in the structure pointed to by preg. + * The cflags argument is the bitwise inclusive OR of zero or + * more of the flags + */ +static inline int regcomp(__rte_unused regex_t *preg, + __rte_unused const char *regex, __rte_unused int cflags) +{ + /* TODO */ + /* This is a stub, not the expected result */ + return REG_ESPACE; +} + +/** + * The regexec() function compares the null-terminated string + * specified by string with the compiled regular expression + * preg initialised by a previous call to regcomp(). If it finds + * a match, regexec() returns 0; otherwise it returns non-zero + * indicating either no match or an error. The eflags argument + * is the bitwise inclusive OR of zero or more of the flags. + */ +static inline int regexec(__rte_unused const regex_t *preg, + __rte_unused const char *string, __rte_unused size_t nmatch, + __rte_unused regmatch_t pmatch[], __rte_unused int eflags) +{ + /* TODO */ + /* This is a stub, not the expected result */ + return REG_NOMATCH; +} + +/** + * The regerror() function provides a mapping from error codes + * returned by regcomp() and regexec() to unspecified printable strings. + */ +static inline size_t regerror(__rte_unused int errcode, + __rte_unused const regex_t *preg, char *errbuf, + __rte_unused size_t errbuf_size) +{ + /* TODO */ + /* This is a stub, not the expected result */ + if (errbuf) { + *errbuf = '\0'; + return 1; + } + return 0; +} + +/** + * The regfree() function frees any memory allocated by regcomp() + * associated with preg. + */ +static inline void regfree(__rte_unused regex_t *preg) +{ + /* TODO */ + /* This is a stub, not the expected result */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* _REGEX_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/rte_os.h b/src/spdk/dpdk/lib/librte_eal/windows/include/rte_os.h new file mode 100644 index 000000000..510e39e03 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/rte_os.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2019 Intel Corporation + */ + +#ifndef _RTE_OS_H_ +#define _RTE_OS_H_ + +/** + * This is header should contain any function/macro definition + * which are not supported natively or named differently in the + * Windows OS. It must not include Windows-specific headers. + */ + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* limits.h replacement, value as in <windows.h> */ +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif + +#define strerror_r(a, b, c) strerror_s(b, c, a) + +/* strdup is deprecated in Microsoft libc and _strdup is preferred */ +#define strdup(str) _strdup(str) + +#define strtok_r(str, delim, saveptr) strtok_s(str, delim, saveptr) + +#define index(a, b) strchr(a, b) +#define rindex(a, b) strrchr(a, b) + +#define strncasecmp(s1, s2, count) _strnicmp(s1, s2, count) + +/* cpu_set macros implementation */ +#define RTE_CPU_AND(dst, src1, src2) CPU_AND(dst, src1, src2) +#define RTE_CPU_OR(dst, src1, src2) CPU_OR(dst, src1, src2) +#define RTE_CPU_FILL(set) CPU_FILL(set) +#define RTE_CPU_NOT(dst, src) CPU_NOT(dst, src) + +/* as in <windows.h> */ +typedef long long ssize_t; + +#ifndef RTE_TOOLCHAIN_GCC +static inline int +asprintf(char **buffer, const char *format, ...) +{ + int size, ret; + va_list arg; + + va_start(arg, format); + size = vsnprintf(NULL, 0, format, arg); + va_end(arg); + if (size < 0) + return -1; + size++; + + *buffer = malloc(size); + if (*buffer == NULL) + return -1; + + va_start(arg, format); + ret = vsnprintf(*buffer, size, format, arg); + va_end(arg); + if (ret != size - 1) { + free(*buffer); + return -1; + } + return ret; +} +#endif /* RTE_TOOLCHAIN_GCC */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_OS_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/rte_windows.h b/src/spdk/dpdk/lib/librte_eal/windows/include/rte_windows.h new file mode 100644 index 000000000..ed6e4c148 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/rte_windows.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2020 Dmitry Kozlyuk + */ + +#ifndef _RTE_WINDOWS_H_ +#define _RTE_WINDOWS_H_ + +/** + * @file Windows-specific facilities + * + * This file should be included by DPDK libraries and applications + * that need access to Windows API. It includes platform SDK headers + * in compatible order with proper options and defines error-handling macros. + */ + +/* Disable excessive libraries. */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +/* Must come first. */ +#include <windows.h> + +#include <basetsd.h> +#include <psapi.h> + +/* Have GUIDs defined. */ +#ifndef INITGUID +#define INITGUID +#endif +#include <initguid.h> + +/** + * Log GetLastError() with context, usually a Win32 API function and arguments. + */ +#define RTE_LOG_WIN32_ERR(...) \ + RTE_LOG(DEBUG, EAL, RTE_FMT("GetLastError()=%lu: " \ + RTE_FMT_HEAD(__VA_ARGS__,) "\n", GetLastError(), \ + RTE_FMT_TAIL(__VA_ARGS__,))) + +#endif /* _RTE_WINDOWS_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/sched.h b/src/spdk/dpdk/lib/librte_eal/windows/include/sched.h new file mode 100644 index 000000000..fbe07f742 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/sched.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef _SCHED_H_ +#define _SCHED_H_ + +/** + * This file is added to support the common code in eal_common_thread.c + * as Microsoft libc does not contain sched.h. This may be removed + * in future releases. + */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CPU_SETSIZE +#define CPU_SETSIZE RTE_MAX_LCORE +#endif + +#define _BITS_PER_SET (sizeof(long long) * 8) +#define _BIT_SET_MASK (_BITS_PER_SET - 1) + +#define _NUM_SETS(b) (((b) + _BIT_SET_MASK) / _BITS_PER_SET) +#define _WHICH_SET(b) ((b) / _BITS_PER_SET) +#define _WHICH_BIT(b) ((b) & (_BITS_PER_SET - 1)) + +typedef struct _rte_cpuset_s { + long long _bits[_NUM_SETS(CPU_SETSIZE)]; +} rte_cpuset_t; + +#define CPU_SET(b, s) ((s)->_bits[_WHICH_SET(b)] |= (1LL << _WHICH_BIT(b))) + +#define CPU_ZERO(s) \ + do { \ + unsigned int _i; \ + \ + for (_i = 0; _i < _NUM_SETS(CPU_SETSIZE); _i++) \ + (s)->_bits[_i] = 0LL; \ + } while (0) + +#define CPU_ISSET(b, s) (((s)->_bits[_WHICH_SET(b)] & \ + (1LL << _WHICH_BIT(b))) != 0LL) + +static inline int +count_cpu(rte_cpuset_t *s) +{ + unsigned int _i; + int count = 0; + + for (_i = 0; _i < _NUM_SETS(CPU_SETSIZE); _i++) + if (CPU_ISSET(_i, s) != 0LL) + count++; + return count; +} +#define CPU_COUNT(s) count_cpu(s) + +#define CPU_AND(dst, src1, src2) \ +do { \ + unsigned int _i; \ + \ + for (_i = 0; _i < _NUM_SETS(CPU_SETSIZE); _i++) \ + (dst)->_bits[_i] = (src1)->_bits[_i] & (src2)->_bits[_i]; \ +} while (0) + +#define CPU_OR(dst, src1, src2) \ +do { \ + unsigned int _i; \ + \ + for (_i = 0; _i < _NUM_SETS(CPU_SETSIZE); _i++) \ + (dst)->_bits[_i] = (src1)->_bits[_i] | (src2)->_bits[_i]; \ +} while (0) + +#define CPU_FILL(s) \ +do { \ + unsigned int _i; \ + for (_i = 0; _i < _NUM_SETS(CPU_SETSIZE); _i++) \ + (s)->_bits[_i] = -1LL; \ +} while (0) + +#define CPU_NOT(dst, src) \ +do { \ + unsigned int _i; \ + for (_i = 0; _i < _NUM_SETS(CPU_SETSIZE); _i++) \ + (dst)->_bits[_i] = (src)->_bits[_i] ^ -1LL; \ +} while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* _SCHED_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/sys/queue.h b/src/spdk/dpdk/lib/librte_eal/windows/include/sys/queue.h new file mode 100644 index 000000000..a65949a78 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/sys/queue.h @@ -0,0 +1,302 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines tail queues. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) + * + * TAILQ + * _HEAD + + * _CLASS_HEAD + + * _HEAD_INITIALIZER + + * _ENTRY + + * _CLASS_ENTRY + + * _INIT + + * _EMPTY + + * _FIRST + + * _NEXT + + * _PREV + + * _LAST + + * _LAST_FAST + + * _FOREACH + + * _FOREACH_FROM + + * _FOREACH_SAFE + + * _FOREACH_FROM_SAFE + + * _FOREACH_REVERSE + + * _FOREACH_REVERSE_FROM + + * _FOREACH_REVERSE_SAFE + + * _FOREACH_REVERSE_FROM_SAFE + + * _INSERT_HEAD + + * _INSERT_BEFORE + + * _INSERT_AFTER + + * _INSERT_TAIL + + * _CONCAT + + * _REMOVE_AFTER - + * _REMOVE_HEAD - + * _REMOVE + + * _SWAP + + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRACEBUF_INITIALIZER + +#define TRASHIT(x) +#define QMD_IS_TRASHED(x) 0 + +#define QMD_SAVELINK(name, link) + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field); \ + if (TAILQ_NEXT((listelm), field) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + TAILQ_NEXT((elm), field) = TAILQ_FIRST((head)); \ + if (TAILQ_FIRST((head)) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +/* + * The FAST function is fast in that it causes no data access other + * then the access to the head. The standard LAST function above + * will cause a data access of both the element you want and + * the previous element. FAST is very useful for instances when + * you may want to prefetch the last data element. + */ +#define TAILQ_LAST_FAST(head, type, field) \ + (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, \ + QUEUE_TYPEOF(type), field.tqe_next)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) * swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) * *swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + swap_first = (head1)->tqh_first; \ + if (swap_first != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + swap_first = (head2)->tqh_first; \ + if (swap_first != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_QUEUE_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/include/unistd.h b/src/spdk/dpdk/lib/librte_eal/windows/include/unistd.h new file mode 100644 index 000000000..757b7f3c5 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/include/unistd.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef _UNISTD_H_ +#define _UNISTD_H_ +/** + * This file is added to support common code in eal_common_lcore.c + * as Microsoft libc does not contain unistd.h. This may be removed + * in future releases. + */ +#endif /* _UNISTD_H_ */ diff --git a/src/spdk/dpdk/lib/librte_eal/windows/meson.build b/src/spdk/dpdk/lib/librte_eal/windows/meson.build new file mode 100644 index 000000000..adfc8b9b7 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_eal/windows/meson.build @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2019 Intel Corporation + +subdir('include') + +sources += files( + 'eal.c', + 'eal_debug.c', + 'eal_lcore.c', + 'eal_log.c', + 'eal_thread.c', + 'fnmatch.c', + 'getopt.c', +) |