Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2010-2014 Intel Corporation 3 : : */ 4 : : 5 : : #include <errno.h> 6 : : 7 : : #include <eal_trace_internal.h> 8 : : #include <rte_launch.h> 9 : : #include <rte_pause.h> 10 : : #include <rte_lcore.h> 11 : : 12 : : #include "eal_private.h" 13 : : #include "eal_thread.h" 14 : : 15 : : /* 16 : : * Wait until a lcore finished its job. 17 : : */ 18 : : int 19 : 348 : rte_eal_wait_lcore(unsigned worker_id) 20 : : { 21 : 348 : while (rte_atomic_load_explicit(&lcore_config[worker_id].state, 22 [ + + ]: 132967264 : rte_memory_order_acquire) != WAIT) 23 : : rte_pause(); 24 : : 25 : 348 : return lcore_config[worker_id].ret; 26 : : } 27 : : 28 : : /* 29 : : * Send a message to a worker lcore identified by worker_id to call a 30 : : * function f with argument arg. Once the execution is done, the 31 : : * remote lcore switches to WAIT state. 32 : : */ 33 : : int 34 : 193 : rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned int worker_id) 35 : : { 36 : : int rc = -EBUSY; 37 : : 38 : : /* Check if the worker is in 'WAIT' state. Use acquire order 39 : : * since 'state' variable is used as the guard variable. 40 : : */ 41 [ - + ]: 193 : if (rte_atomic_load_explicit(&lcore_config[worker_id].state, 42 : : rte_memory_order_acquire) != WAIT) 43 : 0 : goto finish; 44 : : 45 : 193 : lcore_config[worker_id].arg = arg; 46 : : /* Ensure that all the memory operations are completed 47 : : * before the worker thread starts running the function. 48 : : * Use worker thread function as the guard variable. 49 : : */ 50 : 193 : rte_atomic_store_explicit(&lcore_config[worker_id].f, f, rte_memory_order_release); 51 : : 52 : 193 : rc = eal_thread_wake_worker(worker_id); 53 : : 54 [ + + ]: 193 : finish: 55 : 193 : rte_eal_trace_thread_remote_launch(f, arg, worker_id, rc); 56 : 193 : return rc; 57 : : } 58 : : 59 : : /* 60 : : * Check that every WORKER lcores are in WAIT state, then call 61 : : * rte_eal_remote_launch() for all of them. If call_main is true 62 : : * (set to CALL_MAIN), also call the function on the main lcore. 63 : : */ 64 : : int 65 : 207 : rte_eal_mp_remote_launch(int (*f)(void *), void *arg, 66 : : enum rte_rmt_call_main_t call_main) 67 : : { 68 : : int lcore_id; 69 : 207 : int main_lcore = rte_get_main_lcore(); 70 : : 71 : : /* check state of lcores */ 72 [ + + ]: 361 : RTE_LCORE_FOREACH_WORKER(lcore_id) { 73 [ + + ]: 155 : if (lcore_config[lcore_id].state != WAIT) 74 : : return -EBUSY; 75 : : } 76 : : 77 : : /* send messages to cores */ 78 [ + + ]: 360 : RTE_LCORE_FOREACH_WORKER(lcore_id) { 79 : 154 : rte_eal_remote_launch(f, arg, lcore_id); 80 : : } 81 : : 82 [ + + ]: 206 : if (call_main == CALL_MAIN) { 83 : 6 : lcore_config[main_lcore].ret = f(arg); 84 : 6 : lcore_config[main_lcore].state = WAIT; 85 : : } 86 : : 87 : : return 0; 88 : : } 89 : : 90 : : /* 91 : : * Return the state of the lcore identified by worker_id. 92 : : */ 93 : : enum rte_lcore_state_t 94 : 6 : rte_eal_get_lcore_state(unsigned lcore_id) 95 : : { 96 : 6 : return lcore_config[lcore_id].state; 97 : : } 98 : : 99 : : /* 100 : : * Do a rte_eal_wait_lcore() for every lcore. The return values are 101 : : * ignored. 102 : : */ 103 : : void 104 : 429 : rte_eal_mp_wait_lcore(void) 105 : : { 106 : : unsigned lcore_id; 107 : : 108 [ + + ]: 754 : RTE_LCORE_FOREACH_WORKER(lcore_id) { 109 : 325 : rte_eal_wait_lcore(lcore_id); 110 : : } 111 : 429 : }