DPDK patches and discussions
 help / color / mirror / Atom feed
From: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
To: dev@dpdk.org
Cc: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>,
	Harman Kalra <hkalra@marvell.com>,
	Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>,
	Dmitry Malloy <dmitrym@microsoft.com>,
	Pallavi Kadam <pallavi.kadam@intel.com>
Subject: [dpdk-dev] [PATCH 1/2] eal/windows: add interrupt thread skeleton
Date: Fri, 11 Sep 2020 03:22:06 +0300	[thread overview]
Message-ID: <20200911002207.31813-2-dmitry.kozliuk@gmail.com> (raw)
In-Reply-To: <20200911002207.31813-1-dmitry.kozliuk@gmail.com>

Windows interrupt support is based on IO completion ports (IOCP).
Interrupt thread would send the devices requests to notify about
interrupts and then wait for any request completion. Add skeleton code
of this model without any hardware support.

Another way to wake up the interrupt thread is APC (asynchronous procedure
call), scheduled by any other thread via eal_intr_thread_schedule().
This internal API is intended for alarm implementation.

Signed-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 lib/librte_eal/include/rte_eal_interrupts.h | 14 ++-
 lib/librte_eal/rte_eal_exports.def          |  1 +
 lib/librte_eal/windows/eal.c                |  5 ++
 lib/librte_eal/windows/eal_interrupts.c     | 99 +++++++++++++++++++++
 lib/librte_eal/windows/eal_windows.h        | 12 +++
 lib/librte_eal/windows/include/pthread.h    |  7 ++
 lib/librte_eal/windows/meson.build          |  1 +
 7 files changed, 136 insertions(+), 3 deletions(-)
 create mode 100644 lib/librte_eal/windows/eal_interrupts.c

diff --git a/lib/librte_eal/include/rte_eal_interrupts.h b/lib/librte_eal/include/rte_eal_interrupts.h
index b1e8a2934..b80edfc65 100644
--- a/lib/librte_eal/include/rte_eal_interrupts.h
+++ b/lib/librte_eal/include/rte_eal_interrupts.h
@@ -69,10 +69,18 @@ struct rte_epoll_event {
 struct rte_intr_handle {
 	RTE_STD_C11
 	union {
-		int vfio_dev_fd;  /**< VFIO device file descriptor */
-		int uio_cfg_fd;  /**< UIO cfg file desc for uio_pci_generic */
+		struct {
+			RTE_STD_C11
+			union {
+				/** VFIO device file descriptor */
+				int vfio_dev_fd;
+				/** UIO cfg file desc for uio_pci_generic */
+				int uio_cfg_fd;
+			};
+			int fd;	/**< interrupt event file descriptor */
+		};
+		void *handle; /**< device driver handle (Windows) */
 	};
-	int fd;	 /**< interrupt event file descriptor */
 	enum rte_intr_handle_type type;  /**< handle type */
 	uint32_t max_intr;             /**< max interrupt requested */
 	uint32_t nb_efd;               /**< number of available efd(event fd) */
diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def
index f54ed74a5..9baca0110 100644
--- a/lib/librte_eal/rte_eal_exports.def
+++ b/lib/librte_eal/rte_eal_exports.def
@@ -72,6 +72,7 @@ EXPORTS
 	rte_vlog
 	rte_realloc
 	rte_strscpy
+	rte_thread_is_intr
 	rte_zmalloc
 	rte_zmalloc_socket
 
diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c
index bc48f27ab..141f22adb 100644
--- a/lib/librte_eal/windows/eal.c
+++ b/lib/librte_eal/windows/eal.c
@@ -344,6 +344,11 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
+	if (rte_eal_intr_init() < 0) {
+		rte_eal_init_alert("Cannot init interrupt-handling thread");
+		return -1;
+	}
+
 	if (rte_eal_timer_init() < 0) {
 		rte_eal_init_alert("Cannot init TSC timer");
 		rte_errno = EFAULT;
diff --git a/lib/librte_eal/windows/eal_interrupts.c b/lib/librte_eal/windows/eal_interrupts.c
new file mode 100644
index 000000000..d9bc5afc7
--- /dev/null
+++ b/lib/librte_eal/windows/eal_interrupts.c
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Dmitry Kozlyuk
+ */
+
+#include <rte_interrupts.h>
+
+#include "eal_private.h"
+#include "eal_windows.h"
+
+static pthread_t intr_thread;
+
+static HANDLE intr_iocp;
+
+static void
+eal_intr_process(const OVERLAPPED_ENTRY *event)
+{
+	RTE_SET_USED(event);
+}
+
+static void *
+eal_intr_thread_main(LPVOID arg __rte_unused)
+{
+	while (1) {
+		OVERLAPPED_ENTRY events[16];
+		ULONG event_count, i;
+		BOOL result;
+
+		result = GetQueuedCompletionStatusEx(
+			intr_iocp, events, RTE_DIM(events), &event_count,
+			INFINITE, /* no timeout */
+			TRUE);    /* alertable wait for alarm APCs */
+
+		if (!result) {
+			DWORD error = GetLastError();
+			if (error != WAIT_IO_COMPLETION) {
+				RTE_LOG_WIN32_ERR("GetQueuedCompletionStatusEx()");
+				RTE_LOG(ERR, EAL, "Failed waiting for interrupts\n");
+				break;
+			}
+
+			/* No I/O events, all work is done in completed APCs. */
+			continue;
+		}
+
+		for (i = 0; i < event_count; i++)
+			eal_intr_process(&events[i]);
+	}
+
+	CloseHandle(intr_iocp);
+	intr_iocp = NULL;
+	return NULL;
+}
+
+int
+rte_eal_intr_init(void)
+{
+	int ret = 0;
+
+	intr_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
+	if (intr_iocp == NULL) {
+		RTE_LOG_WIN32_ERR("CreateIoCompletionPort()");
+		RTE_LOG(ERR, EAL, "Cannot create interrupt IOCP\n");
+		return -1;
+	}
+
+	ret = rte_ctrl_thread_create(&intr_thread, "eal-intr-thread", NULL,
+			eal_intr_thread_main, NULL);
+	if (ret != 0) {
+		rte_errno = -ret;
+		RTE_LOG(ERR, EAL, "Cannot create interrupt thread\n");
+	}
+
+	return ret;
+}
+
+int
+rte_thread_is_intr(void)
+{
+	return pthread_equal(intr_thread, pthread_self());
+}
+
+int
+eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
+{
+	HANDLE handle;
+
+	handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
+	if (handle == NULL) {
+		RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
+		return -ENOENT;
+	}
+
+	if (!QueueUserAPC((PAPCFUNC)(ULONG_PTR)func, handle, (ULONG_PTR)arg)) {
+		RTE_LOG_WIN32_ERR("QueueUserAPC()");
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/lib/librte_eal/windows/eal_windows.h b/lib/librte_eal/windows/eal_windows.h
index d48ee0a12..478accc1b 100644
--- a/lib/librte_eal/windows/eal_windows.h
+++ b/lib/librte_eal/windows/eal_windows.h
@@ -55,6 +55,18 @@ int eal_thread_create(pthread_t *thread);
  */
 unsigned int eal_socket_numa_node(unsigned int socket_id);
 
+/**
+ * Schedule code for execution in the interrupt thread.
+ *
+ * @param func
+ *  Function to call.
+ * @param arg
+ *  Argument to the called function.
+ * @return
+ *  0 on success, netagive error code on failure.
+ */
+int eal_intr_thread_schedule(void (*func)(void *arg), void *arg);
+
 /**
  * Open virt2phys driver interface device.
  *
diff --git a/lib/librte_eal/windows/include/pthread.h b/lib/librte_eal/windows/include/pthread.h
index 99013dc94..a4ab4d094 100644
--- a/lib/librte_eal/windows/include/pthread.h
+++ b/lib/librte_eal/windows/include/pthread.h
@@ -42,6 +42,13 @@ typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
 #define pthread_self() \
 	((pthread_t)GetCurrentThreadId())
 
+
+static inline int
+pthread_equal(pthread_t t1, pthread_t t2)
+{
+	return t1 == t2;
+}
+
 static inline int
 pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
 			rte_cpuset_t *cpuset)
diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build
index 08c888e01..b690bc6b0 100644
--- a/lib/librte_eal/windows/meson.build
+++ b/lib/librte_eal/windows/meson.build
@@ -8,6 +8,7 @@ sources += files(
 	'eal_debug.c',
 	'eal_file.c',
 	'eal_hugepages.c',
+	'eal_interrupts.c',
 	'eal_lcore.c',
 	'eal_log.c',
 	'eal_memalloc.c',
-- 
2.25.4


  reply	other threads:[~2020-09-11  0:22 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-11  0:22 [dpdk-dev] [PATCH 0/2] eal/windows: implement alarms Dmitry Kozlyuk
2020-09-11  0:22 ` Dmitry Kozlyuk [this message]
2020-09-25  1:19   ` [dpdk-dev] [PATCH 1/2] eal/windows: add interrupt thread skeleton Narcisa Ana Maria Vasile
2020-09-25  6:28     ` Dmitry Kozlyuk
2020-09-11  0:22 ` [dpdk-dev] [PATCH 2/2] eal/windows: implement alarm API Dmitry Kozlyuk
2020-09-21 19:08   ` [dpdk-dev] [EXTERNAL] " Khoa To
2020-09-24 21:38     ` Dmitry Kozlyuk
2020-09-25  2:19       ` Khoa To
2020-09-25 23:32 ` [dpdk-dev] [PATCH v2 0/2] eal/windows: implement alarms Dmitry Kozlyuk
2020-09-25 23:32   ` [dpdk-dev] [PATCH v2 1/2] eal/windows: add interrupt thread skeleton Dmitry Kozlyuk
2020-09-25 23:40     ` Narcisa Ana Maria Vasile
2020-09-25 23:32   ` [dpdk-dev] [PATCH v2 2/2] eal/windows: implement alarm API Dmitry Kozlyuk
2020-09-25 23:41     ` Narcisa Ana Maria Vasile
2020-10-14 21:36       ` Thomas Monjalon

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=20200911002207.31813-2-dmitry.kozliuk@gmail.com \
    --to=dmitry.kozliuk@gmail.com \
    --cc=dev@dpdk.org \
    --cc=dmitrym@microsoft.com \
    --cc=hkalra@marvell.com \
    --cc=navasile@linux.microsoft.com \
    --cc=pallavi.kadam@intel.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).