From patchwork Fri Sep 25 23:32:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Kozlyuk X-Patchwork-Id: 78877 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4FFF2A04BB; Sat, 26 Sep 2020 01:33:18 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 855201EA0D; Sat, 26 Sep 2020 01:33:00 +0200 (CEST) Received: from mail-lj1-f195.google.com (mail-lj1-f195.google.com [209.85.208.195]) by dpdk.org (Postfix) with ESMTP id BA9BE1DE7D for ; Sat, 26 Sep 2020 01:32:54 +0200 (CEST) Received: by mail-lj1-f195.google.com with SMTP id n25so3784397ljj.4 for ; Fri, 25 Sep 2020 16:32:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bfVOx5c6G7gqEgB2stcpP23riJ35U+wP8ZUZ0qyR0ic=; b=u2FP+Y21LKpIzBR3p3SVAKFIjcPKWakVK+J2yjWgrId8mdgK4JUwoZ+84lCnQ5SqBD alkWJcG/a9h8vUSeJG/C+J8bRmhA3KrIBo2g+SSxwwLIpkTpuGjbn41htw6iJwf7qSGc AFVNtT9iDWR4LiIS51VCU0vV3lMrAr8s8ZMCAuoU1beS5y6GHyYnfq+8ih33k++OWMWl WqqdrgTr5Tt2hmiv63g4Cy+m7PfHpiEcQ7dfqx0tvqb0FuY/DrZmJySF+bslVZo6oBfv noEK2Fc1AxTQmgqogfZ7mqwDI4IkTQIbpbrNJQ1gocgvVNB7wu1QpZ1/bHd3VQOdoMnd 8JpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bfVOx5c6G7gqEgB2stcpP23riJ35U+wP8ZUZ0qyR0ic=; b=YONBLOfsQPMhTxx6NLqKWBbb2eco1kvg7JvVTeSobLFMpISkHU6avLnDxJ0fF8WMo1 rjhHOn99agWNa2l+F2RiH7rUuDtSoozdbdwH/LXqfPJNXeuQpj32VpwSMvm+g1sOBrP/ cxTeyQYmounhUeEJcvxg6g3HZAXtatvgvKrZEPGodmhVpptW+mkhdcmyWWppmm5mR85D Yer/SHnjL05Wp2zR/QEKK6lScZSPe9Oa0Ji1NA9ylcO3JiH6QEZfV9GWuueNg7mfZ10c Arcz9hCjOIsZzidts3DE+WifHeX/H03f22GxkuCJ9sRLbdPbyBHgh1aig2MfhadMYTdm lXxQ== X-Gm-Message-State: AOAM533Mhe3hnCdtw2ZCn93eKU8TmPqxuZN6pocoptyn/1U1P/YXUo87 OhGOJk/6Ao4Qb0AxAHjdsSIZvUmmusUxvefz X-Google-Smtp-Source: ABdhPJzH1aYal1wqhzvtnAmyFMA7bLOlU0pqaFffeGjvLnfciUlL97ix5qGKDlD5jTFOr9R2km5ebw== X-Received: by 2002:a2e:2ac3:: with SMTP id q186mr2104235ljq.419.1601076772994; Fri, 25 Sep 2020 16:32:52 -0700 (PDT) Received: from localhost.localdomain (broadband-37-110-65-23.ip.moscow.rt.ru. [37.110.65.23]) by smtp.gmail.com with ESMTPSA id v14sm394511lfe.79.2020.09.25.16.32.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Sep 2020 16:32:52 -0700 (PDT) From: Dmitry Kozlyuk To: dev@dpdk.org Cc: Khoa To , Dmitry Kozlyuk , Harman Kalra , Narcisa Ana Maria Vasile , Dmitry Malloy , Pallavi Kadam Date: Sat, 26 Sep 2020 02:32:42 +0300 Message-Id: <20200925233243.7302-2-dmitry.kozliuk@gmail.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200925233243.7302-1-dmitry.kozliuk@gmail.com> References: <20200911002207.31813-1-dmitry.kozliuk@gmail.com> <20200925233243.7302-1-dmitry.kozliuk@gmail.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v2 1/2] eal/windows: add interrupt thread skeleton 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" 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 Acked-by: Narcisa Vasile --- 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 | 94 +++++++++++++++++++++ lib/librte_eal/windows/eal_windows.h | 12 +++ lib/librte_eal/windows/include/pthread.h | 7 ++ 6 files changed, 130 insertions(+), 3 deletions(-) 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 cda3e0c79..dd8adfa23 100644 --- a/lib/librte_eal/rte_eal_exports.def +++ b/lib/librte_eal/rte_eal_exports.def @@ -70,6 +70,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 index d3ecdaccb..6c64a48f3 100644 --- a/lib/librte_eal/windows/eal_interrupts.c +++ b/lib/librte_eal/windows/eal_interrupts.c @@ -4,6 +4,81 @@ #include +#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 rte_intr_rx_ctl(__rte_unused struct rte_intr_handle *intr_handle, __rte_unused int epfd, __rte_unused int op, @@ -11,3 +86,22 @@ rte_intr_rx_ctl(__rte_unused struct rte_intr_handle *intr_handle, { return -ENOTSUP; } + +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)