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 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 rc = eal_thread_wake_worker(worker_id); 53 54 finish: 55 rte_eal_trace_thread_remote_launch(f, arg, worker_id, rc); 56 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 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 int main_lcore = rte_get_main_lcore(); 70 71 /* check state of lcores */ 72 RTE_LCORE_FOREACH_WORKER(lcore_id) { 73 if (lcore_config[lcore_id].state != WAIT) 74 return -EBUSY; 75 } 76 77 /* send messages to cores */ 78 RTE_LCORE_FOREACH_WORKER(lcore_id) { 79 rte_eal_remote_launch(f, arg, lcore_id); 80 } 81 82 if (call_main == CALL_MAIN) { 83 lcore_config[main_lcore].ret = f(arg); 84 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 rte_eal_get_lcore_state(unsigned lcore_id) 95 { 96 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 rte_eal_mp_wait_lcore(void) 105 { 106 unsigned lcore_id; 107 108 RTE_LCORE_FOREACH_WORKER(lcore_id) { 109 rte_eal_wait_lcore(lcore_id); 110 } 111 } 112