From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id C36294C94 for ; Wed, 6 Mar 2019 05:16:37 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Mar 2019 20:16:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,446,1544515200"; d="scan'208";a="304752074" Received: from anandraw-devbx.amr.corp.intel.com ([10.19.242.57]) by orsmga005.jf.intel.com with ESMTP; 05 Mar 2019 20:16:35 -0800 From: Anand Rawat To: dev@dpdk.org Cc: pallavi.kadam@intel.com, ranjit.menon@intel.com, jeffrey.b.shaw@intel.com, thomas@monjalon.net Date: Tue, 5 Mar 2019 20:16:32 -0800 Message-Id: <20190306041634.12976-5-anand.rawat@intel.com> X-Mailer: git-send-email 2.17.1.windows.2 In-Reply-To: <20190306041634.12976-1-anand.rawat@intel.com> References: <20190306041634.12976-1-anand.rawat@intel.com> Subject: [dpdk-dev] [PATCH v2 4/6] eal: add minimum viable code for eal on windows X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Mar 2019 04:16:38 -0000 Add windows specific logic for eal.c, eal_lcore.c, eal_debug.c and eal_thread.c. Update meson logic to build eal on windows. Signed-off-by: Anand Rawat Signed-off-by: Pallavi Kadam Reviewed-by: Jeff Shaw Reviewed-by: Ranjit Menon --- lib/librte_eal/common/meson.build | 94 +++++------ lib/librte_eal/windows/eal/eal.c | 70 ++++++++- lib/librte_eal/windows/eal/eal_debug.c | 12 +- lib/librte_eal/windows/eal/eal_lcore.c | 97 ++++++++++-- lib/librte_eal/windows/eal/eal_thread.c | 146 +++++++++++++++++- .../windows/eal/include/exec-env/regex.h | 2 + .../eal/include/exec-env/rte_windows.h | 24 +++ 7 files changed, 379 insertions(+), 66 deletions(-) diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build index c010e8737..759516e2a 100644 --- a/lib/librte_eal/common/meson.build +++ b/lib/librte_eal/common/meson.build @@ -5,8 +5,14 @@ eal_inc += include_directories('.', 'include', join_paths('include/arch', arch_subdir)) common_objs = [] -common_sources = [] common_headers = [] + +common_sources = files( + 'eal_common_errno.c', + 'eal_common_launch.c', + 'eal_common_lcore.c', + 'eal_common_log.c' + ) if host_machine.system() != 'windows' common_sources = files( 'eal_common_bus.c', @@ -14,13 +20,9 @@ if host_machine.system() != 'windows' 'eal_common_class.c', 'eal_common_devargs.c', 'eal_common_dev.c', - 'eal_common_errno.c', 'eal_common_fbarray.c', 'eal_common_hexdump.c', 'eal_common_hypervisor.c', - 'eal_common_launch.c', - 'eal_common_lcore.c', - 'eal_common_log.c', 'eal_common_memalloc.c', 'eal_common_memory.c', 'eal_common_memzone.c', @@ -47,7 +49,22 @@ endif eal_common_arch_sources = [] eal_common_arch_objs = [] -common_headers += files('include/rte_common.h') +common_headers += files( + 'include/rte_branch_prediction.h', + 'include/rte_bus.h', + 'include/rte_common.h', + 'include/rte_debug.h', + 'include/rte_dev.h', + 'include/rte_eal.h', + 'include/rte_errno.h', + 'include/rte_launch.h', + 'include/rte_lcore.h', + 'include/rte_log.h', + 'include/rte_memory.h', + 'include/rte_pci_dev_feature_defs.h', + 'include/rte_per_lcore.h', + 'include/rte_string_fns.h' + ) if host_machine.system() != 'windows' subdir(join_paths('arch', arch_subdir)) endif @@ -55,45 +72,32 @@ common_sources += eal_common_arch_sources common_objs += eal_common_arch_objs common_headers += files( - 'include/rte_alarm.h', - 'include/rte_branch_prediction.h', - 'include/rte_bus.h', - 'include/rte_bitmap.h', - 'include/rte_class.h', - 'include/rte_compat.h', - 'include/rte_debug.h', - 'include/rte_devargs.h', - 'include/rte_dev.h', - 'include/rte_eal.h', - 'include/rte_eal_memconfig.h', - 'include/rte_eal_interrupts.h', - 'include/rte_errno.h', - 'include/rte_fbarray.h', - 'include/rte_hexdump.h', - 'include/rte_hypervisor.h', - 'include/rte_interrupts.h', - 'include/rte_keepalive.h', - 'include/rte_launch.h', - 'include/rte_lcore.h', - 'include/rte_log.h', - 'include/rte_malloc.h', - 'include/rte_malloc_heap.h', - 'include/rte_memory.h', - 'include/rte_memzone.h', - 'include/rte_option.h', - 'include/rte_pci_dev_feature_defs.h', - 'include/rte_pci_dev_features.h', - 'include/rte_per_lcore.h', - 'include/rte_random.h', - 'include/rte_reciprocal.h', - 'include/rte_service.h', - 'include/rte_service_component.h', - 'include/rte_string_fns.h', - 'include/rte_tailq.h', - 'include/rte_time.h', - 'include/rte_uuid.h', - 'include/rte_version.h' -) + 'include/rte_alarm.h', + 'include/rte_bitmap.h', + 'include/rte_class.h', + 'include/rte_compat.h', + 'include/rte_devargs.h', + 'include/rte_eal_memconfig.h', + 'include/rte_eal_interrupts.h', + 'include/rte_fbarray.h', + 'include/rte_hexdump.h', + 'include/rte_hypervisor.h', + 'include/rte_interrupts.h', + 'include/rte_keepalive.h', + 'include/rte_malloc.h', + 'include/rte_malloc_heap.h', + 'include/rte_memzone.h', + 'include/rte_option.h', + 'include/rte_pci_dev_features.h', + 'include/rte_random.h', + 'include/rte_reciprocal.h', + 'include/rte_service.h', + 'include/rte_service_component.h', + 'include/rte_tailq.h', + 'include/rte_time.h', + 'include/rte_uuid.h', + 'include/rte_version.h' + ) # special case install the generic headers, since they go in a subdir generic_headers = files( diff --git a/lib/librte_eal/windows/eal/eal.c b/lib/librte_eal/windows/eal/eal.c index 134452a77..1c6923e20 100644 --- a/lib/librte_eal/windows/eal/eal.c +++ b/lib/librte_eal/windows/eal/eal.c @@ -2,10 +2,78 @@ * Copyright(c) 2019 Intel Corporation */ -#include "rte_common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static struct rte_config rte_config; +struct lcore_config lcore_config[RTE_MAX_LCORE]; + +struct rte_config * +rte_eal_get_configuration(void) +{ + return &rte_config; +} + +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); +} int rte_eal_init(int argc __rte_unused, char **argv __rte_unused) { + int i; + + /* 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; + } + + 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 0; } diff --git a/lib/librte_eal/windows/eal/eal_debug.c b/lib/librte_eal/windows/eal/eal_debug.c index 012eeccfa..72e5cb97e 100644 --- a/lib/librte_eal/windows/eal/eal_debug.c +++ b/lib/librte_eal/windows/eal/eal_debug.c @@ -2,11 +2,17 @@ * Copyright(c) 2019 Intel Corporation */ -#include "rte_common.h" +#include +#include void -__rte_panic(const char *funcname __rte_unused, - const char *format __rte_unused, ...) +__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/lib/librte_eal/windows/eal/eal_lcore.c b/lib/librte_eal/windows/eal/eal_lcore.c index be7adeb18..7d73c9358 100644 --- a/lib/librte_eal/windows/eal/eal_lcore.c +++ b/lib/librte_eal/windows/eal/eal_lcore.c @@ -2,25 +2,98 @@ * Copyright(c) 2019 Intel Corporation */ -#include "rte_common.h" +#include +#include - /* Get the cpu core id value */ -unsigned int -eal_cpu_core_id(unsigned int lcore_id) +/* 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() { - return lcore_id; + 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 */ +/* + * Check if a cpu is present by the presence of the cpu information for it + */ int -eal_cpu_detected(unsigned int lcore_id __rte_unused) +eal_cpu_detected(unsigned int lcore_id) { - return 1; + return (lcore_id < wcpu_map.total_procs); } -/* Get CPU socket id (NUMA node) for a logical core */ -unsigned int -eal_cpu_socket_id(unsigned int cpu_id __rte_unused) +/* + * 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 the cpu core id value + */ +unsigned +eal_cpu_core_id(unsigned int lcore_id) { - return 0; + return wcpu_map.wlcore_map[lcore_id].core_id; } diff --git a/lib/librte_eal/windows/eal/eal_thread.c b/lib/librte_eal/windows/eal/eal_thread.c index 222bd8f4d..200ce0156 100644 --- a/lib/librte_eal/windows/eal/eal_thread.c +++ b/lib/librte_eal/windows/eal/eal_thread.c @@ -1,15 +1,151 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2019 Intel Corporation */ -#include +#include +#include +#include +#include +#include +#include +#include -#include "rte_common.h" +#include "eal_thread.h" -typedef uintptr_t eal_thread_t; +RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY; +/* + * 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 -eal_thread_create(eal_thread_t *thread __rte_unused) +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 eal_thread_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; + eal_thread_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; + } +} + +int +eal_thread_create(eal_thread_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; } diff --git a/lib/librte_eal/windows/eal/include/exec-env/regex.h b/lib/librte_eal/windows/eal/include/exec-env/regex.h index efd3f1ecd..512e5723e 100644 --- a/lib/librte_eal/windows/eal/include/exec-env/regex.h +++ b/lib/librte_eal/windows/eal/include/exec-env/regex.h @@ -12,6 +12,8 @@ extern "C" { #define REG_NOMATCH 1 #define REG_ESPACE 12 +#include "rte_common.h" + typedef void *regex_t; typedef void *regmatch_t; diff --git a/lib/librte_eal/windows/eal/include/exec-env/rte_windows.h b/lib/librte_eal/windows/eal/include/exec-env/rte_windows.h index 8e4dc72bb..9f1a9ad62 100644 --- a/lib/librte_eal/windows/eal/include/exec-env/rte_windows.h +++ b/lib/librte_eal/windows/eal/include/exec-env/rte_windows.h @@ -9,13 +9,37 @@ extern "C" { #endif +#include + #define __extension__ #define __thread __declspec(thread) #define strerror_r(a, b, c) strerror_s(b, c, a) +#define strdup(str) _strdup(str) + typedef void *ssize_t; +typedef uintptr_t eal_thread_t; + +/** + * Create a thread. + * This function is private to EAL. + * + * @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(eal_thread_t *thread); + +/** + * Create a map of processors and cores on the system. + * This function is private to EAL. + * + */ +void eal_create_cpu_map(void); + #ifdef __cplusplus } #endif -- 2.17.1.windows.2