| 482 | } |
| 483 | |
| 484 | static int32_t |
| 485 | service_runner_func(void *arg) |
| 486 | { |
| 487 | RTE_SET_USED(arg); |
| 488 | uint8_t i; |
| 489 | const int lcore = rte_lcore_id(); |
| 490 | struct core_state *cs = &lcore_states[lcore]; |
| 491 | |
| 492 | rte_atomic_store_explicit(&cs->thread_active, 1, rte_memory_order_seq_cst); |
| 493 | |
| 494 | /* runstate act as the guard variable. Use load-acquire |
| 495 | * memory order here to synchronize with store-release |
| 496 | * in runstate update functions. |
| 497 | */ |
| 498 | while (rte_atomic_load_explicit(&cs->runstate, rte_memory_order_acquire) == |
| 499 | RUNSTATE_RUNNING) { |
| 500 | |
| 501 | const uint64_t service_mask = cs->service_mask; |
| 502 | uint8_t start_id; |
| 503 | uint8_t end_id; |
| 504 | |
| 505 | if (service_mask == 0) |
| 506 | continue; |
| 507 | |
| 508 | start_id = rte_ctz64(service_mask); |
| 509 | end_id = 64 - rte_clz64(service_mask); |
| 510 | |
| 511 | for (i = start_id; i < end_id; i++) { |
| 512 | /* return value ignored as no change to code flow */ |
| 513 | service_run(i, cs, service_mask, service_get(i), 1); |
| 514 | } |
| 515 | |
| 516 | rte_atomic_store_explicit(&cs->loops, cs->loops + 1, rte_memory_order_relaxed); |
| 517 | } |
| 518 | |
| 519 | /* Switch off this core for all services, to ensure that future |
| 520 | * calls to may_be_active() know this core is switched off. |
| 521 | */ |
| 522 | for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) |
| 523 | cs->service_active_on_lcore[i] = 0; |
| 524 | |
| 525 | /* Use SEQ CST memory ordering to avoid any re-ordering around |
| 526 | * this store, ensuring that once this store is visible, the service |
| 527 | * lcore thread really is done in service cores code. |
| 528 | */ |
| 529 | rte_atomic_store_explicit(&cs->thread_active, 0, rte_memory_order_seq_cst); |
| 530 | return 0; |
| 531 | } |
| 532 | |
| 533 | int32_t |
| 534 | rte_service_lcore_may_be_active(uint32_t lcore) |
nothing calls this directly
no test coverage detected