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