9cde02b00329002f1a2d06764cf2b220dc96099a
[dpdk.git] / lib / eal / windows / eal_interrupts.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 Mellanox Technologies, Ltd
3  */
4
5 #include <rte_interrupts.h>
6
7 #include "eal_private.h"
8 #include "eal_windows.h"
9
10 static pthread_t intr_thread;
11
12 static HANDLE intr_iocp;
13
14 static void
15 eal_intr_process(const OVERLAPPED_ENTRY *event)
16 {
17         RTE_SET_USED(event);
18 }
19
20 static void *
21 eal_intr_thread_main(LPVOID arg __rte_unused)
22 {
23         while (1) {
24                 OVERLAPPED_ENTRY events[16];
25                 ULONG event_count, i;
26                 BOOL result;
27
28                 result = GetQueuedCompletionStatusEx(
29                         intr_iocp, events, RTE_DIM(events), &event_count,
30                         INFINITE, /* no timeout */
31                         TRUE);    /* alertable wait for alarm APCs */
32
33                 if (!result) {
34                         DWORD error = GetLastError();
35                         if (error != WAIT_IO_COMPLETION) {
36                                 RTE_LOG_WIN32_ERR("GetQueuedCompletionStatusEx()");
37                                 RTE_LOG(ERR, EAL, "Failed waiting for interrupts\n");
38                                 break;
39                         }
40
41                         /* No I/O events, all work is done in completed APCs. */
42                         continue;
43                 }
44
45                 for (i = 0; i < event_count; i++)
46                         eal_intr_process(&events[i]);
47         }
48
49         intr_thread = 0;
50
51         CloseHandle(intr_iocp);
52         intr_iocp = NULL;
53
54         return NULL;
55 }
56
57 int
58 rte_eal_intr_init(void)
59 {
60         int ret = 0;
61
62         intr_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
63         if (intr_iocp == NULL) {
64                 RTE_LOG_WIN32_ERR("CreateIoCompletionPort()");
65                 RTE_LOG(ERR, EAL, "Cannot create interrupt IOCP\n");
66                 return -1;
67         }
68
69         ret = rte_ctrl_thread_create(&intr_thread, "eal-intr-thread", NULL,
70                         eal_intr_thread_main, NULL);
71         if (ret != 0) {
72                 rte_errno = -ret;
73                 RTE_LOG(ERR, EAL, "Cannot create interrupt thread\n");
74         }
75
76         return ret;
77 }
78
79 int
80 rte_thread_is_intr(void)
81 {
82         return pthread_equal(intr_thread, pthread_self());
83 }
84
85 int
86 rte_intr_rx_ctl(__rte_unused struct rte_intr_handle *intr_handle,
87                 __rte_unused int epfd, __rte_unused int op,
88                 __rte_unused unsigned int vec, __rte_unused void *data)
89 {
90         return -ENOTSUP;
91 }
92
93 int
94 eal_intr_thread_schedule(void (*func)(void *arg), void *arg)
95 {
96         HANDLE handle;
97
98         handle = OpenThread(THREAD_ALL_ACCESS, FALSE, intr_thread);
99         if (handle == NULL) {
100                 RTE_LOG_WIN32_ERR("OpenThread(%llu)", intr_thread);
101                 return -ENOENT;
102         }
103
104         if (!QueueUserAPC((PAPCFUNC)(ULONG_PTR)func, handle, (ULONG_PTR)arg)) {
105                 RTE_LOG_WIN32_ERR("QueueUserAPC()");
106                 return -EINVAL;
107         }
108
109         return 0;
110 }
111
112 int
113 rte_intr_callback_register(
114         __rte_unused const struct rte_intr_handle *intr_handle,
115         __rte_unused rte_intr_callback_fn cb, __rte_unused void *cb_arg)
116 {
117         return -ENOTSUP;
118 }
119
120 int
121 rte_intr_callback_unregister_pending(
122         __rte_unused const struct rte_intr_handle *intr_handle,
123         __rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg,
124         __rte_unused rte_intr_unregister_callback_fn ucb_fn)
125 {
126         return -ENOTSUP;
127 }
128
129 int
130 rte_intr_callback_unregister(
131         __rte_unused const struct rte_intr_handle *intr_handle,
132         __rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg)
133 {
134         return 0;
135 }
136
137 int
138 rte_intr_callback_unregister_sync(
139         __rte_unused const struct rte_intr_handle *intr_handle,
140         __rte_unused rte_intr_callback_fn cb_fn, __rte_unused void *cb_arg)
141 {
142         return 0;
143 }
144
145 int
146 rte_intr_enable(__rte_unused const struct rte_intr_handle *intr_handle)
147 {
148         return -ENOTSUP;
149 }
150
151 int
152 rte_intr_ack(__rte_unused const struct rte_intr_handle *intr_handle)
153 {
154         return -ENOTSUP;
155 }
156
157 int
158 rte_intr_disable(__rte_unused const struct rte_intr_handle *intr_handle)
159 {
160         return -ENOTSUP;
161 }
162
163 int
164 rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
165 {
166         RTE_SET_USED(intr_handle);
167         RTE_SET_USED(nb_efd);
168
169         return 0;
170 }
171
172 void
173 rte_intr_efd_disable(struct rte_intr_handle *intr_handle)
174 {
175         RTE_SET_USED(intr_handle);
176 }
177
178 int
179 rte_intr_dp_is_en(struct rte_intr_handle *intr_handle)
180 {
181         RTE_SET_USED(intr_handle);
182
183         return 0;
184 }
185
186 int
187 rte_intr_allow_others(struct rte_intr_handle *intr_handle)
188 {
189         RTE_SET_USED(intr_handle);
190
191         return 1;
192 }
193
194 int
195 rte_intr_cap_multiple(struct rte_intr_handle *intr_handle)
196 {
197         RTE_SET_USED(intr_handle);
198
199         return 0;
200 }
201
202 int
203 rte_epoll_wait(int epfd, struct rte_epoll_event *events,
204                 int maxevents, int timeout)
205 {
206         RTE_SET_USED(epfd);
207         RTE_SET_USED(events);
208         RTE_SET_USED(maxevents);
209         RTE_SET_USED(timeout);
210
211         return -ENOTSUP;
212 }
213
214 int
215 rte_epoll_wait_interruptible(int epfd, struct rte_epoll_event *events,
216                              int maxevents, int timeout)
217 {
218         RTE_SET_USED(epfd);
219         RTE_SET_USED(events);
220         RTE_SET_USED(maxevents);
221         RTE_SET_USED(timeout);
222
223         return -ENOTSUP;
224 }
225
226 int
227 rte_epoll_ctl(int epfd, int op, int fd, struct rte_epoll_event *event)
228 {
229         RTE_SET_USED(epfd);
230         RTE_SET_USED(op);
231         RTE_SET_USED(fd);
232         RTE_SET_USED(event);
233
234         return -ENOTSUP;
235 }
236
237 int
238 rte_intr_tls_epfd(void)
239 {
240         return -ENOTSUP;
241 }
242
243 void
244 rte_intr_free_epoll_fd(struct rte_intr_handle *intr_handle)
245 {
246         RTE_SET_USED(intr_handle);
247 }