All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anand Rawat <anand.rawat@intel.com>
To: dev@dpdk.org
Subject: [PATCH 4/6] eal: add minimum viable code for eal on windows
Date: Thu, 28 Feb 2019 23:18:45 -0800	[thread overview]
Message-ID: <20190301071847.13376-5-anand.rawat@intel.com> (raw)
In-Reply-To: <20190301071847.13376-1-anand.rawat@intel.com>

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 <anand.rawat@intel.com>
Signed-off-by: Kadam, Pallavi <pallavi.kadam@intel.com>
Reviewed-by: Jeffrey B Shaw <jeffrey.b.shaw@intel.com>
Reviewed-by: Ranjit Menon <ranjit.menon@intel.com>
---
 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 <io.h>
+#include <fcntl.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_errno.h>
+#include <rte_lcore.h>
+#include <eal_thread.h>
+#include <eal_private.h>
+
+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 <stdarg.h>
+#include <rte_log.h>
 
 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 <stdint.h>
+#include <rte_windows.h>
 
- /* 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 <windows.h>
+#include <io.h>
+#include <rte_windows.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 "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 <windows.h>
+
 #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
-- 
2.17.1.windows.2

  parent reply	other threads:[~2019-03-01  7:18 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-01  7:18 [PATCH 0/6] HelloWorld example for Windows Anand Rawat
2019-03-01  7:18 ` [PATCH 1/6] eal: eal stub to add windows support Anand Rawat
2019-03-01 14:03   ` Thomas Monjalon
2019-03-01 14:17     ` Bruce Richardson
2019-03-01 14:30       ` Thomas Monjalon
2019-03-01 15:19       ` Luca Boccassi
2019-03-01  7:18 ` [PATCH 2/6] eal: Add header files to support windows Anand Rawat
2019-03-01  7:18 ` [PATCH 3/6] eal: Add headers for compatibility with windows environment Anand Rawat
2019-03-01  7:18 ` Anand Rawat [this message]
2019-03-01  7:18 ` [PATCH 5/6] examples: Add meson changes for windows Anand Rawat
2019-03-01  7:18 ` [PATCH 6/6] doc: add documention " Anand Rawat
2019-03-01 19:02   ` Stephen Hemminger
2019-03-02  2:41     ` Ranjit Menon
2019-03-06  8:33       ` Thomas Monjalon
2019-03-01 13:47 ` [PATCH 0/6] HelloWorld example for Windows Bruce Richardson
2019-03-04 10:13   ` David Marchand
2019-03-04 10:14     ` David Marchand
2019-03-05 23:43     ` Anand Rawat

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190301071847.13376-5-anand.rawat@intel.com \
    --to=anand.rawat@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.