1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Mellanox Technologies, Ltd
5 #include <rte_interrupts.h>
7 #include "eal_private.h"
8 #include "eal_windows.h"
10 #define IOCP_KEY_SHUTDOWN UINT32_MAX
12 static pthread_t intr_thread;
14 static HANDLE intr_iocp;
15 static HANDLE intr_thread_handle;
18 eal_intr_process(const OVERLAPPED_ENTRY *event)
24 eal_intr_thread_handle_init(void)
26 DWORD thread_id = GetCurrentThreadId();
28 intr_thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
29 if (intr_thread_handle == NULL) {
30 RTE_LOG_WIN32_ERR("OpenThread(%lu)", thread_id);
37 eal_intr_thread_main(LPVOID arg __rte_unused)
39 bool finished = false;
41 if (eal_intr_thread_handle_init() < 0) {
42 RTE_LOG(ERR, EAL, "Cannot open interrupt thread handle\n");
47 OVERLAPPED_ENTRY events[16];
51 result = GetQueuedCompletionStatusEx(
52 intr_iocp, events, RTE_DIM(events), &event_count,
53 INFINITE, /* no timeout */
54 TRUE); /* alertable wait for alarm APCs */
57 DWORD error = GetLastError();
58 if (error != WAIT_IO_COMPLETION) {
59 RTE_LOG_WIN32_ERR("GetQueuedCompletionStatusEx()");
60 RTE_LOG(ERR, EAL, "Failed waiting for interrupts\n");
64 /* No I/O events, all work is done in completed APCs. */
68 for (i = 0; i < event_count; i++) {
69 if (events[i].lpCompletionKey == IOCP_KEY_SHUTDOWN) {
73 eal_intr_process(&events[i]);
77 CloseHandle(intr_thread_handle);
78 intr_thread_handle = NULL;
83 CloseHandle(intr_iocp);
90 rte_eal_intr_init(void)
94 intr_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
95 if (intr_iocp == NULL) {
96 RTE_LOG_WIN32_ERR("CreateIoCompletionPort()");
97 RTE_LOG(ERR, EAL, "Cannot create interrupt IOCP\n");
101 ret = rte_ctrl_thread_create(&intr_thread, "eal-intr-thread", NULL,
102 eal_intr_thread_main, NULL);
105 RTE_LOG(ERR, EAL, "Cannot create interrupt thread\n");
112 rte_thread_is_intr(void)
114 return pthread_equal(intr_thread, pthread_self());
118 rte_intr_rx_ctl(__rte_unused struct rte_intr_handle *intr_handle,
119 __rte_unused int epfd, __rte_unused int op,
120 __rte_unused unsigned int vec, __rte_unused void *data)
126 eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
128 if (!QueueUserAPC((PAPCFUNC)(ULONG_PTR)func,
129 intr_thread_handle, (ULONG_PTR)arg)) {
130 RTE_LOG_WIN32_ERR("QueueUserAPC()");
138 eal_intr_thread_cancel(void)
140 if (!PostQueuedCompletionStatus(
141 intr_iocp, 0, IOCP_KEY_SHUTDOWN, NULL)) {
142 RTE_LOG_WIN32_ERR("PostQueuedCompletionStatus()");
143 RTE_LOG(ERR, EAL, "Cannot cancel interrupt thread\n");
147 WaitForSingleObject(intr_thread_handle, INFINITE);
151 rte_intr_callback_register(
152 __rte_unused const struct rte_intr_handle *intr_handle,
153 __rte_unused rte_intr_callback_fn cb, __rte_unused void *cb_arg)
159 rte_intr_callback_unregister_pending(
160 __rte_unused const struct rte_intr_handle *intr_handle,
161 __rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg,
162 __rte_unused rte_intr_unregister_callback_fn ucb_fn)
168 rte_intr_callback_unregister(
169 __rte_unused const struct rte_intr_handle *intr_handle,
170 __rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg)
176 rte_intr_callback_unregister_sync(
177 __rte_unused const struct rte_intr_handle *intr_handle,
178 __rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg)
184 rte_intr_enable(__rte_unused const struct rte_intr_handle *intr_handle)
190 rte_intr_ack(__rte_unused const struct rte_intr_handle *intr_handle)
196 rte_intr_disable(__rte_unused const struct rte_intr_handle *intr_handle)
202 rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
204 RTE_SET_USED(intr_handle);
205 RTE_SET_USED(nb_efd);
211 rte_intr_efd_disable(struct rte_intr_handle *intr_handle)
213 RTE_SET_USED(intr_handle);
217 rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
219 RTE_SET_USED(intr_handle);
225 rte_intr_allow_others(struct rte_intr_handle *intr_handle)
227 RTE_SET_USED(intr_handle);
233 rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
235 RTE_SET_USED(intr_handle);
241 rte_epoll_wait(int epfd, struct rte_epoll_event *events,
242 int maxevents, int timeout)
245 RTE_SET_USED(events);
246 RTE_SET_USED(maxevents);
247 RTE_SET_USED(timeout);
253 rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
254 int maxevents, int timeout)
257 RTE_SET_USED(events);
258 RTE_SET_USED(maxevents);
259 RTE_SET_USED(timeout);
265 rte_epoll_ctl(int epfd, int op, int fd, struct rte_epoll_event *event)
276 rte_intr_tls_epfd(void)
282 rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
284 RTE_SET_USED(intr_handle);