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