From patchwork Fri Mar 1 07:18:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anand Rawat X-Patchwork-Id: 50700 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 5AAB54C94; Fri, 1 Mar 2019 08:18:56 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id A40A12BB5 for ; Fri, 1 Mar 2019 08:18:51 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Feb 2019 23:18:49 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,426,1544515200"; d="scan'208";a="120044714" Received: from anandraw-devbx.amr.corp.intel.com ([10.19.242.57]) by orsmga006.jf.intel.com with ESMTP; 28 Feb 2019 23:18:48 -0800 From: Anand Rawat To: dev@dpdk.org Date: Thu, 28 Feb 2019 23:18:45 -0800 Message-Id: <20190301071847.13376-5-anand.rawat@intel.com> X-Mailer: git-send-email 2.17.1.windows.2 In-Reply-To: <20190301071847.13376-1-anand.rawat@intel.com> References: <20190301071847.13376-1-anand.rawat@intel.com> Subject: [dpdk-dev] [PATCH 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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: Kadam, Pallavi Reviewed-by: Jeffrey B Shaw Reviewed-by: Ranjit Menon --- lib/librte_eal/common/meson.build | 43 ++--- lib/librte_eal/winapp/eal/eal.c | 70 ++++++++- lib/librte_eal/winapp/eal/eal_debug.c | 13 +- lib/librte_eal/winapp/eal/eal_lcore.c | 82 ++++++++-- lib/librte_eal/winapp/eal/eal_thread.c | 147 +++++++++++++++++- .../winapp/eal/include/exec-env/regex.h | 2 + .../winapp/eal/include/exec-env/rte_windows.h | 21 +++ lib/librte_eal/winapp/eal/meson.build | 6 +- 8 files changed, 343 insertions(+), 41 deletions(-) diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build index 68ce11222..6ad5d2fb1 100644 --- a/lib/librte_eal/common/meson.build +++ b/lib/librte_eal/common/meson.build @@ -5,8 +5,13 @@ 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 +19,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 +48,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)) common_sources += eal_common_arch_sources @@ -55,39 +71,26 @@ if host_machine.system() != 'windows' 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', diff --git a/lib/librte_eal/winapp/eal/eal.c b/lib/librte_eal/winapp/eal/eal.c index 134452a77..1c6923e20 100644 --- a/lib/librte_eal/winapp/eal/eal.c +++ b/lib/librte_eal/winapp/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/winapp/eal/eal_debug.c b/lib/librte_eal/winapp/eal/eal_debug.c index 868808ca9..72e5cb97e 100644 --- a/lib/librte_eal/winapp/eal/eal_debug.c +++ b/lib/librte_eal/winapp/eal/eal_debug.c @@ -2,10 +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/winapp/eal/eal_lcore.c b/lib/librte_eal/winapp/eal/eal_lcore.c index 46418f38f..db9da6039 100644 --- a/lib/librte_eal/winapp/eal/eal_lcore.c +++ b/lib/librte_eal/winapp/eal/eal_lcore.c @@ -2,25 +2,89 @@ * Copyright(c) 2019 Intel Corporation */ -#include "rte_common.h" +#include +#include - /* Get the cpu core id value */ -unsigned -eal_cpu_core_id(unsigned lcore_id) +/* global data structure that contains the CPU map */ +static struct _win_cpu_map { + unsigned numTotalProcessors; + unsigned numProcessorSockets; + unsigned numProcessorCores; + unsigned reserved; + struct _win_lcore_map { + uint8_t socketid; + uint8_t coreid; + } win_lcore_map[RTE_MAX_LCORE]; +} win_cpu_map = { 0 }; + + +void +eal_create_cpu_map() { - return lcore_id; + win_cpu_map.numTotalProcessors = + GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); + + LOGICAL_PROCESSOR_RELATIONSHIP lprocRel; + DWORD lprocInfoSize = 0; + BOOL bHyperThreadingEnabled = FALSE; + + /* First get the processor package information */ + lprocRel = RelationProcessorPackage; + /* Determine the size of buffer we need (pass NULL) */ + GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize); + win_cpu_map.numProcessorSockets = lprocInfoSize / 48; + + lprocInfoSize = 0; + /* Next get the processor core information */ + lprocRel = RelationProcessorCore; + GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize); + win_cpu_map.numProcessorCores = lprocInfoSize / 48; + + if (win_cpu_map.numTotalProcessors > win_cpu_map.numProcessorCores) + bHyperThreadingEnabled = TRUE; + + /* Distribute the socket and core ids appropriately + * across the logical cores. For now, split the cores + * equally across the sockets - might need to revisit this later + */ + unsigned lcore = 0; + for (unsigned socket = 0; socket < + win_cpu_map.numProcessorSockets; ++socket) { + for (unsigned core = 0; core < (win_cpu_map.numProcessorCores / + win_cpu_map.numProcessorSockets); ++core) { + win_cpu_map.win_lcore_map[lcore] + .socketid = socket; + win_cpu_map.win_lcore_map[lcore] + .coreid = core; + lcore++; + if (bHyperThreadingEnabled) { + win_cpu_map.win_lcore_map[lcore] + .socketid = socket; + win_cpu_map.win_lcore_map[lcore] + .coreid = core; + lcore++; + } + } + } } /* Check if a cpu is present by the presence of the cpu information for it */ int -eal_cpu_detected(unsigned lcore_id __rte_unused) +eal_cpu_detected(unsigned lcore_id) { - return 1; + return (lcore_id < win_cpu_map.numTotalProcessors); } /* Get CPU socket id (NUMA node) for a logical core */ unsigned -eal_cpu_socket_id(unsigned cpu_id __rte_unused) +eal_cpu_socket_id(unsigned lcore_id) +{ + return win_cpu_map.win_lcore_map[lcore_id].socketid; +} + +/* Get the cpu core id value */ +unsigned +eal_cpu_core_id(unsigned lcore_id) { - return 0; + return win_cpu_map.win_lcore_map[lcore_id].coreid; } diff --git a/lib/librte_eal/winapp/eal/eal_thread.c b/lib/librte_eal/winapp/eal/eal_thread.c index 222bd8f4d..27fd00705 100644 --- a/lib/librte_eal/winapp/eal/eal_thread.c +++ b/lib/librte_eal/winapp/eal/eal_thread.c @@ -1,15 +1,152 @@ /* 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, _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 +rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned 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 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 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 __rte_unused) +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/winapp/eal/include/exec-env/regex.h b/lib/librte_eal/winapp/eal/include/exec-env/regex.h index 5a167833f..482101b3c 100644 --- a/lib/librte_eal/winapp/eal/include/exec-env/regex.h +++ b/lib/librte_eal/winapp/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/winapp/eal/include/exec-env/rte_windows.h b/lib/librte_eal/winapp/eal/include/exec-env/rte_windows.h index 8e4dc72bb..b9831ee6f 100644 --- a/lib/librte_eal/winapp/eal/include/exec-env/rte_windows.h +++ b/lib/librte_eal/winapp/eal/include/exec-env/rte_windows.h @@ -9,13 +9,34 @@ 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); + +void +eal_create_cpu_map(); + #ifdef __cplusplus } #endif diff --git a/lib/librte_eal/winapp/eal/meson.build b/lib/librte_eal/winapp/eal/meson.build index 487055f80..10a8d034d 100644 --- a/lib/librte_eal/winapp/eal/meson.build +++ b/lib/librte_eal/winapp/eal/meson.build @@ -1,13 +1,13 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2019 Intel Corporation -eal_inc += include_directories('include/exec-env') +eal_inc += include_directories('include','include/exec-env') install_subdir('include/exec-env', install_dir: get_option('includedir')) env_objs = [] env_headers = [] -env_sources = files('eal.c', - 'eal_debug.c', +env_sources = files('eal_debug.c', 'eal_lcore.c', 'eal_thread.c', + 'eal.c' ) \ No newline at end of file