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