[v2,5/6] eal: ensure memory operations are visible to main
Checks
Commit Message
Ensure that the memory operations in worker thread, that happen
before it returns the status of the assigned function, are
visible to the main thread.
Signed-off-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>
Reviewed-by: Feifei Wang <feifei.wang@arm.com>
---
lib/eal/common/eal_common_launch.c | 2 --
lib/eal/freebsd/eal_thread.c | 22 ++++++++++++++++++----
lib/eal/linux/eal_thread.c | 23 ++++++++++++++++++-----
lib/eal/windows/eal_thread.c | 21 +++++++++++++++++----
4 files changed, 53 insertions(+), 15 deletions(-)
@@ -27,8 +27,6 @@ rte_eal_wait_lcore(unsigned worker_id)
__ATOMIC_ACQUIRE) != WAIT)
rte_pause();
- rte_rmb();
-
return lcore_config[worker_id].ret;
}
@@ -39,7 +39,11 @@ rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned 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].arg = arg;
@@ -115,7 +119,11 @@ eal_thread_loop(__rte_unused void *arg)
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;
@@ -139,8 +147,14 @@ eal_thread_loop(__rte_unused void *arg)
lcore_config[lcore_id].ret = ret;
lcore_config[lcore_id].f = NULL;
lcore_config[lcore_id].arg = NULL;
- rte_wmb();
- lcore_config[lcore_id].state = WAIT;
+
+ /* 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.
+ */
+ __atomic_store_n(&lcore_config[lcore_id].state, WAIT,
+ __ATOMIC_RELEASE);
}
/* never reached */
@@ -39,13 +39,17 @@ 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].arg = arg;
/* Ensure that all the memory operations are completed
* before the worker thread starts running the function.
- * Use worker thread function as the guard variable.
+ * Use worker thread function pointer as the guard variable.
*/
__atomic_store_n(&lcore_config[worker_id].f, f, __ATOMIC_RELEASE);
@@ -115,7 +119,11 @@ eal_thread_loop(__rte_unused void *arg)
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;
@@ -139,9 +147,14 @@ eal_thread_loop(__rte_unused void *arg)
lcore_config[lcore_id].ret = ret;
lcore_config[lcore_id].f = NULL;
lcore_config[lcore_id].arg = NULL;
- rte_wmb();
- lcore_config[lcore_id].state = WAIT;
+ /* 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.
+ */
+ __atomic_store_n(&lcore_config[lcore_id].state, WAIT,
+ __ATOMIC_RELEASE);
}
/* never reached */
@@ -29,7 +29,11 @@ rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned int worker_id)
int m2w = lcore_config[worker_id].pipe_main2worker[1];
int w2m = lcore_config[worker_id].pipe_worker2main[0];
- 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)
return -EBUSY;
lcore_config[worker_id].arg = arg;
@@ -99,7 +103,11 @@ eal_thread_loop(void *arg __rte_unused)
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;
@@ -123,9 +131,14 @@ eal_thread_loop(void *arg __rte_unused)
lcore_config[lcore_id].ret = ret;
lcore_config[lcore_id].f = NULL;
lcore_config[lcore_id].arg = NULL;
- rte_wmb();
- lcore_config[lcore_id].state = WAIT;
+ /* 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.
+ */
+ __atomic_store_n(&lcore_config[lcore_id].state, WAIT,
+ __ATOMIC_RELEASE);
}
}