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.nagaraha...@arm.com>
---
 lib/librte_eal/common/eal_common_launch.c |  8 ++++----
 lib/librte_eal/freebsd/eal_thread.c       | 10 ++++++++--
 lib/librte_eal/linux/eal_thread.c         | 17 ++++++++++++-----
 lib/librte_eal/windows/eal_thread.c       |  9 +++++++--
 4 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_launch.c 
b/lib/librte_eal/common/eal_common_launch.c
index 78fd94026..9cc71801a 100644
--- a/lib/librte_eal/common/eal_common_launch.c
+++ b/lib/librte_eal/common/eal_common_launch.c
@@ -23,14 +23,14 @@
 int
 rte_eal_wait_lcore(unsigned worker_id)
 {
-       if (lcore_config[worker_id].state == WAIT)
+       if (__atomic_load_n(&lcore_config[worker_id].state,
+                                       __ATOMIC_ACQUIRE) == WAIT)
                return 0;
 
-       while (lcore_config[worker_id].state != WAIT)
+       while (__atomic_load_n(&lcore_config[worker_id].state,
+                                       __ATOMIC_ACQUIRE) != WAIT)
                rte_pause();
 
-       rte_rmb();
-
        return lcore_config[worker_id].ret;
 }
 
diff --git a/lib/librte_eal/freebsd/eal_thread.c 
b/lib/librte_eal/freebsd/eal_thread.c
index 6d6f1e2fd..58c8502de 100644
--- a/lib/librte_eal/freebsd/eal_thread.c
+++ b/lib/librte_eal/freebsd/eal_thread.c
@@ -139,8 +139,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 */
diff --git a/lib/librte_eal/linux/eal_thread.c 
b/lib/librte_eal/linux/eal_thread.c
index 7b9463df3..eab6fa652 100644
--- a/lib/librte_eal/linux/eal_thread.c
+++ b/lib/librte_eal/linux/eal_thread.c
@@ -39,13 +39,14 @@ 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)
+       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 +116,8 @@ eal_thread_loop(__rte_unused void *arg)
                if (n <= 0)
                        rte_panic("cannot read on configuration pipe\n");
 
-               lcore_config[lcore_id].state = RUNNING;
+               __atomic_store_n(&lcore_config[lcore_id].state, RUNNING,
+                                       __ATOMIC_RELEASE);
 
                /* send ack */
                n = 0;
@@ -139,9 +141,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 */
diff --git a/lib/librte_eal/windows/eal_thread.c 
b/lib/librte_eal/windows/eal_thread.c
index 35d059a30..fb1ec4b4f 100644
--- a/lib/librte_eal/windows/eal_thread.c
+++ b/lib/librte_eal/windows/eal_thread.c
@@ -123,9 +123,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);
        }
 }
 
-- 
2.17.1

Reply via email to