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_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 rte_eal_wait_lcore(unsigned worker_id) 20 { 21 while (__atomic_load_n(&lcore_config[worker_id].state, 22 __ATOMIC_ACQUIRE) != WAIT) 23 rte_pause(); 24 25 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 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 if (__atomic_load_n(&lcore_config[worker_id].state, 42 __ATOMIC_ACQUIRE) != WAIT) 43 goto finish; 44 45 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 __atomic_store_n(&lcore_config[worker_id].f, f, __ATOMIC_RELEASE); 51 52 eal_thread_wake_worker(worker_id); 53 rc = 0; 54 55 finish: 56 rte_eal_trace_thread_remote_launch(f, arg, worker_id, rc); 57 return rc; 58 } 59 60 /* 61 * Check that every WORKER lcores are in WAIT state, then call 62 * rte_eal_remote_launch() for all of them. If call_main is true 63 * (set to CALL_MAIN), also call the function on the main lcore. 64 */ 65 int 66 rte_eal_mp_remote_launch(int (*f)(void *), void *arg, 67 enum rte_rmt_call_main_t call_main) 68 { 69 int lcore_id; 70 int main_lcore = rte_get_main_lcore(); 71 72 /* check state of lcores */ 73 RTE_LCORE_FOREACH_WORKER(lcore_id) { 74 if (lcore_config[lcore_id].state != WAIT) 75 return -EBUSY; 76 } 77 78 /* send messages to cores */ 79 RTE_LCORE_FOREACH_WORKER(lcore_id) { 80 rte_eal_remote_launch(f, arg, lcore_id); 81 } 82 83 if (call_main == CALL_MAIN) { 84 lcore_config[main_lcore].ret = f(arg); 85 lcore_config[main_lcore].state = WAIT; 86 } 87 88 return 0; 89 } 90 91 /* 92 * Return the state of the lcore identified by worker_id. 93 */ 94 enum rte_lcore_state_t 95 rte_eal_get_lcore_state(unsigned lcore_id) 96 { 97 return lcore_config[lcore_id].state; 98 } 99 100 /* 101 * Do a rte_eal_wait_lcore() for every lcore. The return values are 102 * ignored. 103 */ 104 void 105 rte_eal_mp_wait_lcore(void) 106 { 107 unsigned lcore_id; 108 109 RTE_LCORE_FOREACH_WORKER(lcore_id) { 110 rte_eal_wait_lcore(lcore_id); 111 } 112 } 113