/*
* Send a message to a worker lcore identified by worker_id to call a
* function f with argument arg. Once the execution is done, the
- * remote lcore switch in FINISHED state.
+ * remote lcore switches to WAIT state.
*/
int
rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned int worker_id)
int w2m = lcore_config[worker_id].pipe_worker2main[0];
int rc = -EBUSY;
- if (lcore_config[worker_id].state != WAIT)
+ /* Check if the worker is in 'WAIT' state. Use acquire order
+ * since 'state' variable is used as the guard variable.
+ */
+ if (__atomic_load_n(&lcore_config[worker_id].state,
+ __ATOMIC_ACQUIRE) != WAIT)
goto finish;
- lcore_config[worker_id].f = f;
lcore_config[worker_id].arg = arg;
+ /* Ensure that all the memory operations are completed
+ * before the worker thread starts running the function.
+ * Use worker thread function pointer as the guard variable.
+ */
+ __atomic_store_n(&lcore_config[worker_id].f, f, __ATOMIC_RELEASE);
/* send message */
n = 0;
/* read on our pipe to get commands */
while (1) {
+ lcore_function_t *f;
void *fct_arg;
/* wait command */
if (n <= 0)
rte_panic("cannot read on configuration pipe\n");
- lcore_config[lcore_id].state = RUNNING;
+ /* Set the state to 'RUNNING'. Use release order
+ * since 'state' variable is used as the guard variable.
+ */
+ __atomic_store_n(&lcore_config[lcore_id].state, RUNNING,
+ __ATOMIC_RELEASE);
/* send ack */
n = 0;
if (n < 0)
rte_panic("cannot write on configuration pipe\n");
- if (lcore_config[lcore_id].f == NULL)
- rte_panic("NULL function pointer\n");
+ /* Load 'f' with acquire order to ensure that
+ * the memory operations from the main thread
+ * are accessed only after update to 'f' is visible.
+ * Wait till the update to 'f' is visible to the worker.
+ */
+ while ((f = __atomic_load_n(&lcore_config[lcore_id].f,
+ __ATOMIC_ACQUIRE)) == NULL)
+ rte_pause();
/* call the function and store the return value */
fct_arg = lcore_config[lcore_id].arg;
- ret = lcore_config[lcore_id].f(fct_arg);
+ ret = f(fct_arg);
lcore_config[lcore_id].ret = ret;
lcore_config[lcore_id].f = NULL;
lcore_config[lcore_id].arg = NULL;
- rte_wmb();
- /* when a service core returns, it should go directly to WAIT
- * state, because the application will not lcore_wait() for it.
+ /* Store the state with release order to ensure that
+ * the memory operations from the worker thread
+ * are completed before the state is updated.
+ * Use 'state' as the guard variable.
*/
- if (lcore_config[lcore_id].core_role == ROLE_SERVICE)
- lcore_config[lcore_id].state = WAIT;
- else
- lcore_config[lcore_id].state = FINISHED;
+ __atomic_store_n(&lcore_config[lcore_id].state, WAIT,
+ __ATOMIC_RELEASE);
}
/* never reached */