Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Ericsson AB
3 : : */
4 : :
5 : : #include <stdbool.h>
6 : : #include <stdint.h>
7 : :
8 : : #include <eal_export.h>
9 : : #include <rte_branch_prediction.h>
10 : : #include <rte_common.h>
11 : : #include <rte_lcore.h>
12 : : #include <rte_random.h>
13 : : #include <rte_service_component.h>
14 : :
15 : : #include "eventdev_pmd.h"
16 : :
17 : : #include <rte_dispatcher.h>
18 : :
19 : : #define EVD_MAX_PORTS_PER_LCORE 4
20 : : #define EVD_MAX_HANDLERS 32
21 : : #define EVD_MAX_FINALIZERS 16
22 : : #define EVD_AVG_PRIO_INTERVAL 2000
23 : : #define EVD_SERVICE_NAME "dispatcher"
24 : :
25 : : struct rte_dispatcher_lcore_port {
26 : : uint8_t port_id;
27 : : uint16_t batch_size;
28 : : uint64_t timeout;
29 : : };
30 : :
31 : : struct rte_dispatcher_handler {
32 : : int id;
33 : : rte_dispatcher_match_t match_fun;
34 : : void *match_data;
35 : : rte_dispatcher_process_t process_fun;
36 : : void *process_data;
37 : : };
38 : :
39 : : struct rte_dispatcher_finalizer {
40 : : int id;
41 : : rte_dispatcher_finalize_t finalize_fun;
42 : : void *finalize_data;
43 : : };
44 : :
45 : : struct __rte_cache_aligned rte_dispatcher_lcore {
46 : : uint8_t num_ports;
47 : : uint16_t num_handlers;
48 : : int32_t prio_count;
49 : : struct rte_dispatcher_lcore_port ports[EVD_MAX_PORTS_PER_LCORE];
50 : : struct rte_dispatcher_handler handlers[EVD_MAX_HANDLERS];
51 : : struct rte_dispatcher_stats stats;
52 : : RTE_CACHE_GUARD;
53 : : };
54 : :
55 : : struct rte_dispatcher {
56 : : uint8_t event_dev_id;
57 : : int socket_id;
58 : : uint32_t service_id;
59 : : struct rte_dispatcher_lcore lcores[RTE_MAX_LCORE];
60 : : uint16_t num_finalizers;
61 : : struct rte_dispatcher_finalizer finalizers[EVD_MAX_FINALIZERS];
62 : : };
63 : :
64 : : static int
65 : : evd_lookup_handler_idx(struct rte_dispatcher_lcore *lcore,
66 : : const struct rte_event *event)
67 : : {
68 : : uint16_t i;
69 : :
70 [ # # ]: 0 : for (i = 0; i < lcore->num_handlers; i++) {
71 : : struct rte_dispatcher_handler *handler =
72 : 0 : &lcore->handlers[i];
73 : :
74 [ # # ]: 0 : if (handler->match_fun(event, handler->match_data))
75 : : return i;
76 : : }
77 : :
78 : : return -1;
79 : : }
80 : :
81 : : static void
82 : 0 : evd_prioritize_handler(struct rte_dispatcher_lcore *lcore,
83 : : int handler_idx)
84 : : {
85 : : struct rte_dispatcher_handler tmp;
86 : :
87 [ # # ]: 0 : if (handler_idx == 0)
88 : : return;
89 : :
90 : : /* Let the lucky handler "bubble" up the list */
91 : :
92 : 0 : tmp = lcore->handlers[handler_idx - 1];
93 : 0 : lcore->handlers[handler_idx - 1] = lcore->handlers[handler_idx];
94 : 0 : lcore->handlers[handler_idx] = tmp;
95 : : }
96 : :
97 : : static inline void
98 : 0 : evd_consider_prioritize_handler(struct rte_dispatcher_lcore *lcore,
99 : : int handler_idx, uint16_t handler_events)
100 : : {
101 : 0 : lcore->prio_count -= handler_events;
102 : :
103 [ # # ]: 0 : if (unlikely(lcore->prio_count <= 0)) {
104 : 0 : evd_prioritize_handler(lcore, handler_idx);
105 : :
106 : : /*
107 : : * Randomize the interval in the unlikely case
108 : : * the traffic follow some very strict pattern.
109 : : */
110 : 0 : lcore->prio_count =
111 : 0 : rte_rand_max(EVD_AVG_PRIO_INTERVAL) +
112 : : EVD_AVG_PRIO_INTERVAL / 2;
113 : : }
114 : 0 : }
115 : :
116 : : static inline void
117 : 0 : evd_dispatch_events(struct rte_dispatcher *dispatcher,
118 : : struct rte_dispatcher_lcore *lcore,
119 : : struct rte_dispatcher_lcore_port *port,
120 : : struct rte_event *events, uint16_t num_events)
121 : 0 : {
122 : : int i;
123 : 0 : struct rte_event bursts[EVD_MAX_HANDLERS][num_events];
124 : 0 : uint16_t burst_lens[EVD_MAX_HANDLERS] = { 0 };
125 : : uint16_t drop_count = 0;
126 : : uint16_t dispatch_count;
127 : : uint16_t dispatched = 0;
128 : :
129 [ # # ]: 0 : for (i = 0; i < num_events; i++) {
130 : 0 : struct rte_event *event = &events[i];
131 : : int handler_idx;
132 : :
133 : : handler_idx = evd_lookup_handler_idx(lcore, event);
134 : :
135 [ # # ]: 0 : if (unlikely(handler_idx < 0)) {
136 : 0 : drop_count++;
137 : 0 : continue;
138 : : }
139 : :
140 : 0 : bursts[handler_idx][burst_lens[handler_idx]] = *event;
141 : 0 : burst_lens[handler_idx]++;
142 : : }
143 : :
144 : 0 : dispatch_count = num_events - drop_count;
145 : :
146 [ # # # # ]: 0 : for (i = 0; i < lcore->num_handlers &&
147 : 0 : dispatched < dispatch_count; i++) {
148 : : struct rte_dispatcher_handler *handler =
149 : : &lcore->handlers[i];
150 : 0 : uint16_t len = burst_lens[i];
151 : :
152 [ # # ]: 0 : if (len == 0)
153 : 0 : continue;
154 : :
155 : 0 : handler->process_fun(dispatcher->event_dev_id, port->port_id,
156 : 0 : bursts[i], len, handler->process_data);
157 : :
158 : 0 : dispatched += len;
159 : :
160 : : /*
161 : : * Safe, since any reshuffling will only involve
162 : : * already-processed handlers.
163 : : */
164 : 0 : evd_consider_prioritize_handler(lcore, i, len);
165 : : }
166 : :
167 : 0 : lcore->stats.ev_batch_count++;
168 : 0 : lcore->stats.ev_dispatch_count += dispatch_count;
169 : 0 : lcore->stats.ev_drop_count += drop_count;
170 : :
171 [ # # ]: 0 : for (i = 0; i < dispatcher->num_finalizers; i++) {
172 : : struct rte_dispatcher_finalizer *finalizer =
173 : : &dispatcher->finalizers[i];
174 : :
175 : 0 : finalizer->finalize_fun(dispatcher->event_dev_id,
176 : 0 : port->port_id,
177 : : finalizer->finalize_data);
178 : : }
179 : 0 : }
180 : :
181 : : static __rte_always_inline uint16_t
182 : : evd_port_dequeue(struct rte_dispatcher *dispatcher,
183 : : struct rte_dispatcher_lcore *lcore,
184 : : struct rte_dispatcher_lcore_port *port)
185 : 0 : {
186 : 0 : uint16_t batch_size = port->batch_size;
187 : 0 : struct rte_event events[batch_size];
188 : : uint16_t n;
189 : :
190 : 0 : n = rte_event_dequeue_burst(dispatcher->event_dev_id, port->port_id,
191 : : events, batch_size, port->timeout);
192 : :
193 [ # # ]: 0 : if (likely(n > 0))
194 : 0 : evd_dispatch_events(dispatcher, lcore, port, events, n);
195 : :
196 : 0 : lcore->stats.poll_count++;
197 : :
198 : : return n;
199 : : }
200 : :
201 : : static __rte_always_inline uint16_t
202 : : evd_lcore_process(struct rte_dispatcher *dispatcher,
203 : : struct rte_dispatcher_lcore *lcore)
204 : : {
205 : : uint16_t i;
206 : : uint16_t event_count = 0;
207 : :
208 [ # # ]: 0 : for (i = 0; i < lcore->num_ports; i++) {
209 : 0 : struct rte_dispatcher_lcore_port *port =
210 : 0 : &lcore->ports[i];
211 : :
212 : 0 : event_count += evd_port_dequeue(dispatcher, lcore, port);
213 : : }
214 : :
215 : : return event_count;
216 : : }
217 : :
218 : : static int32_t
219 : 0 : evd_process(void *userdata)
220 : : {
221 : : struct rte_dispatcher *dispatcher = userdata;
222 : : unsigned int lcore_id = rte_lcore_id();
223 : 0 : struct rte_dispatcher_lcore *lcore =
224 : : &dispatcher->lcores[lcore_id];
225 : : uint64_t event_count;
226 : :
227 : : event_count = evd_lcore_process(dispatcher, lcore);
228 : :
229 [ # # ]: 0 : if (unlikely(event_count == 0))
230 : 0 : return -EAGAIN;
231 : :
232 : : return 0;
233 : : }
234 : :
235 : : static int
236 : 0 : evd_service_register(struct rte_dispatcher *dispatcher)
237 : : {
238 : 0 : struct rte_service_spec service = {
239 : : .callback = evd_process,
240 : : .callback_userdata = dispatcher,
241 : : .capabilities = RTE_SERVICE_CAP_MT_SAFE,
242 : 0 : .socket_id = dispatcher->socket_id
243 : : };
244 : : int rc;
245 : :
246 : : snprintf(service.name, sizeof(service.name), EVD_SERVICE_NAME);
247 : :
248 : 0 : rc = rte_service_component_register(&service, &dispatcher->service_id);
249 [ # # ]: 0 : if (rc != 0)
250 : 0 : RTE_EDEV_LOG_ERR("Registration of dispatcher service "
251 : : "%s failed with error code %d",
252 : : service.name, rc);
253 : :
254 : 0 : return rc;
255 : : }
256 : :
257 : : static int
258 : 0 : evd_service_unregister(struct rte_dispatcher *dispatcher)
259 : : {
260 : : int rc;
261 : :
262 : 0 : rc = rte_service_component_unregister(dispatcher->service_id);
263 [ # # ]: 0 : if (rc != 0)
264 : 0 : RTE_EDEV_LOG_ERR("Unregistration of dispatcher service "
265 : : "failed with error code %d", rc);
266 : :
267 : 0 : return rc;
268 : : }
269 : :
270 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_create, 23.11)
271 : : struct rte_dispatcher *
272 : 0 : rte_dispatcher_create(uint8_t event_dev_id)
273 : : {
274 : : int socket_id;
275 : : struct rte_dispatcher *dispatcher;
276 : : int rc;
277 : :
278 : 0 : socket_id = rte_event_dev_socket_id(event_dev_id);
279 : :
280 : : dispatcher =
281 : 0 : rte_malloc_socket("dispatcher", sizeof(struct rte_dispatcher),
282 : : RTE_CACHE_LINE_SIZE, socket_id);
283 : :
284 [ # # ]: 0 : if (dispatcher == NULL) {
285 : 0 : RTE_EDEV_LOG_ERR("Unable to allocate memory for dispatcher");
286 : 0 : rte_errno = ENOMEM;
287 : 0 : return NULL;
288 : : }
289 : :
290 : 0 : *dispatcher = (struct rte_dispatcher) {
291 : : .event_dev_id = event_dev_id,
292 : : .socket_id = socket_id
293 : : };
294 : :
295 : 0 : rc = evd_service_register(dispatcher);
296 [ # # ]: 0 : if (rc < 0) {
297 : 0 : rte_free(dispatcher);
298 : 0 : rte_errno = -rc;
299 : 0 : return NULL;
300 : : }
301 : :
302 : : return dispatcher;
303 : : }
304 : :
305 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_free, 23.11)
306 : : int
307 : 0 : rte_dispatcher_free(struct rte_dispatcher *dispatcher)
308 : : {
309 : : int rc;
310 : :
311 [ # # ]: 0 : if (dispatcher == NULL)
312 : : return 0;
313 : :
314 : 0 : rc = evd_service_unregister(dispatcher);
315 [ # # ]: 0 : if (rc != 0)
316 : : return rc;
317 : :
318 : 0 : rte_free(dispatcher);
319 : :
320 : 0 : return 0;
321 : : }
322 : :
323 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_service_id_get, 23.11)
324 : : uint32_t
325 : 0 : rte_dispatcher_service_id_get(const struct rte_dispatcher *dispatcher)
326 : : {
327 : 0 : return dispatcher->service_id;
328 : : }
329 : :
330 : : static int
331 : : lcore_port_index(struct rte_dispatcher_lcore *lcore,
332 : : uint8_t event_port_id)
333 : : {
334 : : uint16_t i;
335 : :
336 [ # # # # ]: 0 : for (i = 0; i < lcore->num_ports; i++) {
337 : : struct rte_dispatcher_lcore_port *port =
338 : 0 : &lcore->ports[i];
339 : :
340 [ # # # # ]: 0 : if (port->port_id == event_port_id)
341 : : return i;
342 : : }
343 : :
344 : : return -1;
345 : : }
346 : :
347 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_bind_port_to_lcore, 23.11)
348 : : int
349 : 0 : rte_dispatcher_bind_port_to_lcore(struct rte_dispatcher *dispatcher,
350 : : uint8_t event_port_id, uint16_t batch_size, uint64_t timeout,
351 : : unsigned int lcore_id)
352 : : {
353 : : struct rte_dispatcher_lcore *lcore;
354 : : struct rte_dispatcher_lcore_port *port;
355 : :
356 : : lcore = &dispatcher->lcores[lcore_id];
357 : :
358 [ # # ]: 0 : if (lcore->num_ports == EVD_MAX_PORTS_PER_LCORE)
359 : : return -ENOMEM;
360 : :
361 [ # # ]: 0 : if (lcore_port_index(lcore, event_port_id) >= 0)
362 : : return -EEXIST;
363 : :
364 : 0 : port = &lcore->ports[lcore->num_ports];
365 : :
366 : 0 : *port = (struct rte_dispatcher_lcore_port) {
367 : : .port_id = event_port_id,
368 : : .batch_size = batch_size,
369 : : .timeout = timeout
370 : : };
371 : :
372 : 0 : lcore->num_ports++;
373 : :
374 : 0 : return 0;
375 : : }
376 : :
377 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_unbind_port_from_lcore, 23.11)
378 : : int
379 : 0 : rte_dispatcher_unbind_port_from_lcore(struct rte_dispatcher *dispatcher,
380 : : uint8_t event_port_id, unsigned int lcore_id)
381 : : {
382 : : struct rte_dispatcher_lcore *lcore;
383 : : int port_idx;
384 : : struct rte_dispatcher_lcore_port *port;
385 : : struct rte_dispatcher_lcore_port *last;
386 : :
387 : : lcore = &dispatcher->lcores[lcore_id];
388 : :
389 : : port_idx = lcore_port_index(lcore, event_port_id);
390 : :
391 [ # # ]: 0 : if (port_idx < 0)
392 : : return -ENOENT;
393 : :
394 : 0 : port = &lcore->ports[port_idx];
395 : 0 : last = &lcore->ports[lcore->num_ports - 1];
396 : :
397 [ # # ]: 0 : if (port != last)
398 : 0 : *port = *last;
399 : :
400 : 0 : lcore->num_ports--;
401 : :
402 : 0 : return 0;
403 : : }
404 : :
405 : : static struct rte_dispatcher_handler *
406 : : evd_lcore_get_handler_by_id(struct rte_dispatcher_lcore *lcore, int handler_id)
407 : : {
408 : : uint16_t i;
409 : :
410 [ # # # # ]: 0 : for (i = 0; i < lcore->num_handlers; i++) {
411 : 0 : struct rte_dispatcher_handler *handler =
412 : 0 : &lcore->handlers[i];
413 : :
414 [ # # # # ]: 0 : if (handler->id == handler_id)
415 : : return handler;
416 : : }
417 : :
418 : : return NULL;
419 : : }
420 : :
421 : : static int
422 : : evd_alloc_handler_id(struct rte_dispatcher *dispatcher)
423 : : {
424 : : int handler_id = 0;
425 : : struct rte_dispatcher_lcore *reference_lcore =
426 : : &dispatcher->lcores[0];
427 : :
428 : 0 : if (reference_lcore->num_handlers == EVD_MAX_HANDLERS)
429 : : return -1;
430 : :
431 [ # # ]: 0 : while (evd_lcore_get_handler_by_id(reference_lcore, handler_id) != NULL)
432 : 0 : handler_id++;
433 : :
434 : : return handler_id;
435 : : }
436 : :
437 : : static void
438 : : evd_lcore_install_handler(struct rte_dispatcher_lcore *lcore,
439 : : const struct rte_dispatcher_handler *handler)
440 : : {
441 : 0 : int handler_idx = lcore->num_handlers;
442 : :
443 : 0 : lcore->handlers[handler_idx] = *handler;
444 : 0 : lcore->num_handlers++;
445 : : }
446 : :
447 : : static void
448 : : evd_install_handler(struct rte_dispatcher *dispatcher,
449 : : const struct rte_dispatcher_handler *handler)
450 : : {
451 : : int i;
452 : :
453 [ # # ]: 0 : for (i = 0; i < RTE_MAX_LCORE; i++) {
454 : : struct rte_dispatcher_lcore *lcore =
455 : : &dispatcher->lcores[i];
456 : : evd_lcore_install_handler(lcore, handler);
457 : : }
458 : : }
459 : :
460 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_register, 23.11)
461 : : int
462 [ # # ]: 0 : rte_dispatcher_register(struct rte_dispatcher *dispatcher,
463 : : rte_dispatcher_match_t match_fun, void *match_data,
464 : : rte_dispatcher_process_t process_fun, void *process_data)
465 : : {
466 : : struct rte_dispatcher_handler handler = {
467 : : .match_fun = match_fun,
468 : : .match_data = match_data,
469 : : .process_fun = process_fun,
470 : : .process_data = process_data
471 : : };
472 : :
473 : : handler.id = evd_alloc_handler_id(dispatcher);
474 : :
475 [ # # ]: 0 : if (handler.id < 0)
476 : : return -ENOMEM;
477 : :
478 : : evd_install_handler(dispatcher, &handler);
479 : :
480 : : return handler.id;
481 : : }
482 : :
483 : : static int
484 : 0 : evd_lcore_uninstall_handler(struct rte_dispatcher_lcore *lcore,
485 : : int handler_id)
486 : : {
487 : : struct rte_dispatcher_handler *unreg_handler;
488 : : int handler_idx;
489 : : uint16_t last_idx;
490 : :
491 : : unreg_handler = evd_lcore_get_handler_by_id(lcore, handler_id);
492 : :
493 [ # # ]: 0 : if (unreg_handler == NULL) {
494 : 0 : RTE_EDEV_LOG_ERR("Invalid handler id %d", handler_id);
495 : 0 : return -EINVAL;
496 : : }
497 : :
498 : 0 : handler_idx = unreg_handler - &lcore->handlers[0];
499 : :
500 : 0 : last_idx = lcore->num_handlers - 1;
501 : :
502 [ # # ]: 0 : if (handler_idx != last_idx) {
503 : : /* move all handlers to maintain handler order */
504 : 0 : int n = last_idx - handler_idx;
505 : 0 : memmove(unreg_handler, unreg_handler + 1,
506 : : sizeof(struct rte_dispatcher_handler) * n);
507 : : }
508 : :
509 : 0 : lcore->num_handlers--;
510 : :
511 : 0 : return 0;
512 : : }
513 : :
514 : : static int
515 : : evd_uninstall_handler(struct rte_dispatcher *dispatcher, int handler_id)
516 : : {
517 : : unsigned int lcore_id;
518 : :
519 [ # # ]: 0 : for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
520 : 0 : struct rte_dispatcher_lcore *lcore =
521 : : &dispatcher->lcores[lcore_id];
522 : : int rc;
523 : :
524 : 0 : rc = evd_lcore_uninstall_handler(lcore, handler_id);
525 [ # # ]: 0 : if (rc < 0)
526 : : return rc;
527 : : }
528 : :
529 : : return 0;
530 : : }
531 : :
532 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_unregister, 23.11)
533 : : int
534 : 0 : rte_dispatcher_unregister(struct rte_dispatcher *dispatcher, int handler_id)
535 : : {
536 : 0 : return evd_uninstall_handler(dispatcher, handler_id);
537 : : }
538 : :
539 : : static struct rte_dispatcher_finalizer *
540 : : evd_get_finalizer_by_id(struct rte_dispatcher *dispatcher,
541 : : int handler_id)
542 : : {
543 : : int i;
544 : :
545 [ # # # # ]: 0 : for (i = 0; i < dispatcher->num_finalizers; i++) {
546 : 0 : struct rte_dispatcher_finalizer *finalizer =
547 : : &dispatcher->finalizers[i];
548 : :
549 [ # # # # ]: 0 : if (finalizer->id == handler_id)
550 : : return finalizer;
551 : : }
552 : :
553 : : return NULL;
554 : : }
555 : :
556 : : static int
557 : : evd_alloc_finalizer_id(struct rte_dispatcher *dispatcher)
558 : : {
559 : : int finalizer_id = 0;
560 : :
561 [ # # ]: 0 : while (evd_get_finalizer_by_id(dispatcher, finalizer_id) != NULL)
562 : 0 : finalizer_id++;
563 : :
564 : : return finalizer_id;
565 : : }
566 : :
567 : : static struct rte_dispatcher_finalizer *
568 : : evd_alloc_finalizer(struct rte_dispatcher *dispatcher)
569 : : {
570 : : int finalizer_idx;
571 : : struct rte_dispatcher_finalizer *finalizer;
572 : :
573 : 0 : if (dispatcher->num_finalizers == EVD_MAX_FINALIZERS)
574 : : return NULL;
575 : :
576 : 0 : finalizer_idx = dispatcher->num_finalizers;
577 : 0 : finalizer = &dispatcher->finalizers[finalizer_idx];
578 : :
579 : 0 : finalizer->id = evd_alloc_finalizer_id(dispatcher);
580 : :
581 : 0 : dispatcher->num_finalizers++;
582 : :
583 : : return finalizer;
584 : : }
585 : :
586 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_finalize_register, 23.11)
587 : : int
588 [ # # ]: 0 : rte_dispatcher_finalize_register(struct rte_dispatcher *dispatcher,
589 : : rte_dispatcher_finalize_t finalize_fun, void *finalize_data)
590 : : {
591 : : struct rte_dispatcher_finalizer *finalizer;
592 : :
593 : : finalizer = evd_alloc_finalizer(dispatcher);
594 : :
595 : : if (finalizer == NULL)
596 : : return -ENOMEM;
597 : :
598 : 0 : finalizer->finalize_fun = finalize_fun;
599 : 0 : finalizer->finalize_data = finalize_data;
600 : :
601 : 0 : return finalizer->id;
602 : : }
603 : :
604 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_finalize_unregister, 23.11)
605 : : int
606 : 0 : rte_dispatcher_finalize_unregister(struct rte_dispatcher *dispatcher,
607 : : int finalizer_id)
608 : : {
609 : : struct rte_dispatcher_finalizer *unreg_finalizer;
610 : : int finalizer_idx;
611 : : uint16_t last_idx;
612 : :
613 : : unreg_finalizer = evd_get_finalizer_by_id(dispatcher, finalizer_id);
614 : :
615 [ # # ]: 0 : if (unreg_finalizer == NULL) {
616 : 0 : RTE_EDEV_LOG_ERR("Invalid finalizer id %d", finalizer_id);
617 : 0 : return -EINVAL;
618 : : }
619 : :
620 : 0 : finalizer_idx = unreg_finalizer - &dispatcher->finalizers[0];
621 : :
622 : 0 : last_idx = dispatcher->num_finalizers - 1;
623 : :
624 [ # # ]: 0 : if (finalizer_idx != last_idx) {
625 : : /* move all finalizers to maintain order */
626 : 0 : int n = last_idx - finalizer_idx;
627 : 0 : memmove(unreg_finalizer, unreg_finalizer + 1,
628 : : sizeof(struct rte_dispatcher_finalizer) * n);
629 : : }
630 : :
631 : 0 : dispatcher->num_finalizers--;
632 : :
633 : 0 : return 0;
634 : : }
635 : :
636 : : static void
637 : 0 : evd_set_service_runstate(struct rte_dispatcher *dispatcher, int state)
638 : : {
639 : : int rc;
640 : :
641 : 0 : rc = rte_service_component_runstate_set(dispatcher->service_id,
642 : : state);
643 : : /*
644 : : * The only cause of a runstate_set() failure is an invalid
645 : : * service id, which in turns means the dispatcher instance's
646 : : * state is invalid.
647 : : */
648 [ # # ]: 0 : if (rc != 0)
649 : 0 : RTE_EDEV_LOG_ERR("Unexpected error %d occurred while setting "
650 : : "service component run state to %d", rc,
651 : : state);
652 : :
653 [ # # ]: 0 : RTE_VERIFY(rc == 0);
654 : 0 : }
655 : :
656 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_start, 23.11)
657 : : void
658 : 0 : rte_dispatcher_start(struct rte_dispatcher *dispatcher)
659 : : {
660 : 0 : evd_set_service_runstate(dispatcher, 1);
661 : 0 : }
662 : :
663 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_stop, 23.11)
664 : : void
665 : 0 : rte_dispatcher_stop(struct rte_dispatcher *dispatcher)
666 : : {
667 : 0 : evd_set_service_runstate(dispatcher, 0);
668 : 0 : }
669 : :
670 : : static void
671 : : evd_aggregate_stats(struct rte_dispatcher_stats *result,
672 : : const struct rte_dispatcher_stats *part)
673 : : {
674 : 0 : result->poll_count += part->poll_count;
675 : 0 : result->ev_batch_count += part->ev_batch_count;
676 : 0 : result->ev_dispatch_count += part->ev_dispatch_count;
677 : 0 : result->ev_drop_count += part->ev_drop_count;
678 : : }
679 : :
680 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_stats_get, 23.11)
681 : : void
682 : 0 : rte_dispatcher_stats_get(const struct rte_dispatcher *dispatcher,
683 : : struct rte_dispatcher_stats *stats)
684 : : {
685 : : unsigned int lcore_id;
686 : :
687 : 0 : *stats = (struct rte_dispatcher_stats) {};
688 : :
689 [ # # ]: 0 : for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
690 : : const struct rte_dispatcher_lcore *lcore =
691 : : &dispatcher->lcores[lcore_id];
692 : :
693 : : evd_aggregate_stats(stats, &lcore->stats);
694 : : }
695 : 0 : }
696 : :
697 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dispatcher_stats_reset, 23.11)
698 : : void
699 : 0 : rte_dispatcher_stats_reset(struct rte_dispatcher *dispatcher)
700 : : {
701 : : unsigned int lcore_id;
702 : :
703 [ # # ]: 0 : for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
704 : : struct rte_dispatcher_lcore *lcore =
705 : : &dispatcher->lcores[lcore_id];
706 : :
707 : 0 : lcore->stats = (struct rte_dispatcher_stats) {};
708 : : }
709 : 0 : }
|