te_smp_mb() is removed by this series, leaving the barrier test with
one case instead of two. Drop the use type enum and the barrier
selector wrapper.
Convert the Peterson lock to explicit atomic accesses with relaxed
ordering, leaving rte_atomic_thread_fence(rte_memory_order_seq_cst)
as the only thing preventing store-load reordering.
Run it on both x86 and arm boxes, both passed.
Other arch maintainers, pls review, test.
Acked-by: Konstantin Ananyev <[email protected]>
Tested-by: Konstantin Ananyev <[email protected]>
Signed-off-by: Stephen Hemminger <[email protected]>
---
app/test/test_barrier.c
<https://inbox.dpdk.org/dev/[email protected]/#Z31app:test:test_barrier.c>
| 105 +++++++++++++---------------------------
1 file changed, 34 insertions(+), 71 deletions(-)
diff
<https://inbox.dpdk.org/dev/[email protected]/#iZ31app:test:test_barrier.c>
--git a/app/test/test_barrier.c b/app/test/test_barrier.c index
925a88b68a..cb876d8fda 100644 --- a/app/test/test_barrier.c +++
b/app/test/test_barrier.c @@ -2,51 +2,41 @@ * Copyright(c) 2010-2018 Intel Corporation
*/
- /* - * This is a simple functional test for rte_smp_mb()
implementation. - * I.E. make sure that LOAD and STORE operations that
precede the - * rte_smp_mb() call are globally visible across the
lcores - * before the LOAD and STORE operations that follows it. - *
The test uses simple implementation of Peterson's lock algorithm - *
(https://en.wikipedia.org/wiki/Peterson%27s_algorithm) - * for two
execution units to make sure that rte_smp_mb() prevents - * store-load
reordering to happen. - * Also when executed on a single lcore could
be used as a approximate - * estimation of number of cycles particular
implementation of rte_smp_mb() - * will take. - */ +/* + * Functional
test for rte_atomic_thread_fence(rte_memory_order_seq_cst). + * I.E.
make sure that LOAD and STORE operations that precede the fence + *
are globally visible across the lcores before the LOAD and STORE + *
operations that follow it. + * The test uses a simple implementation
of Peterson's lock algorithm + *
(https://en.wikipedia.org/wiki/Peterson%27s_algorithm) + * for two
execution units, since that algorithm only works if + * store-load
reordering is prevented. + * Also when executed on a single lcore it
can be used as an approximate + * estimate of the number of cycles a
sequentially consistent fence takes. + */
+#include <errno.h> #include <stdio.h>
-#include <string.h> #include <stdint.h>
+#include <stdlib.h> #include <inttypes.h>
-#include <rte_memory.h> -#include <rte_per_lcore.h> #include <rte_launch.h>
#include <rte_eal.h>
#include <rte_lcore.h>
#include <rte_pause.h>
#include <rte_random.h>
#include <rte_cycles.h>
-#include <rte_vect.h> -#include <rte_debug.h> +#include
<rte_stdatomic.h>
#include "test.h"
#define ADD_MAX 8
#define ITER_MAX 0x1000000
-enum plock_use_type { - USE_MB, - USE_SMP_MB, - USE_NUM -}; - struct plock {
- volatile uint32_t flag[2]; - volatile uint32_t victim; - enum
plock_use_type utype; + RTE_ATOMIC(uint32_t) flag[2]; +
RTE_ATOMIC(uint32_t) victim; };
/*
@@ -69,19 +59,11 @@ struct lcore_plock_test { uint32_t lc; /*
given lcore id */
};
-static inline void -store_load_barrier(uint32_t utype) -{ - if (utype
== USE_MB) - rte_mb(); - else if (utype == USE_SMP_MB) - rte_smp_mb();
- else - RTE_VERIFY(0); -} - /*
* Peterson lock implementation.
+ * The stores below are relaxed on purpose: the sequentially
consistent + * fence is the only thing keeping them ahead of the loads
in the spin + * loop, so a broken fence shows up as two lcores in the
critical section. */
static void
plock_lock(struct plock *l, uint32_t self)
@@ -90,29 +72,22 @@ plock_lock(struct plock *l, uint32_t self)
other = self ^ 1;
- l->flag[self] = 1; - rte_smp_wmb(); - l->victim = self; +
rte_atomic_store_explicit(&l->flag[self], 1,
rte_memory_order_relaxed); + rte_atomic_store_explicit(&l->victim,
self, rte_memory_order_relaxed);
- store_load_barrier(l->utype); +
rte_atomic_thread_fence(rte_memory_order_seq_cst);
- while (l->flag[other] == 1 && l->victim == self) + while
(rte_atomic_load_explicit(&l->flag[other], rte_memory_order_relaxed)
== 1 && + rte_atomic_load_explicit(&l->victim,
rte_memory_order_relaxed) == self) rte_pause();
- rte_smp_rmb(); -}
-static void -plock_unlock(struct plock *l, uint32_t self) -{ -
rte_smp_wmb(); - l->flag[self] = 0; +
rte_atomic_thread_fence(rte_memory_order_acquire); }
static void
-plock_reset(struct plock *l, enum plock_use_type utype)
+plock_unlock(struct plock *l, uint32_t self) {
- memset(l, 0, sizeof(*l)); - l->utype = utype; +
rte_atomic_store_explicit(&l->flag[self], 0, rte_memory_order_release); }
/*
@@ -186,7 +161,7 @@ plock_test1_lcore(void *data) * and local data are the
same.
*/
static int
-plock_test(uint64_t iter, enum plock_use_type utype)
+plock_test(uint64_t iter) {
int32_t rc;
uint32_t i, lc, n;
@@ -201,8 +176,7 @@ plock_test(uint64_t iter, enum plock_use_type utype)
lpt = calloc(n, sizeof(*lpt));
sum = calloc(n + 1, sizeof(*sum));
- printf("%s(iter=%" PRIu64 ", utype=%u) started on %u lcores\n", -
__func__, iter, utype, n); + printf("%s(iter=%" PRIu64 ") started on
%u lcores\n", __func__, iter, n);
if (pt == NULL || lpt == NULL || sum == NULL) {
printf("%s: failed to allocate memory for %u lcores\n",
@@ -213,9 +187,6 @@ plock_test(uint64_t iter, enum plock_use_type utype)
return -ENOMEM;
}
- for (i = 0; i != n + 1; i++) - plock_reset(&pt[i].lock, utype); - i = 0;
RTE_LCORE_FOREACH(lc) {
@@ -263,26 +234,18 @@ plock_test(uint64_t iter, enum plock_use_type
utype) free(lpt);
free(sum);
- printf("%s(utype=%u) returns %d\n", __func__, utype, rc); +
printf("%s returns %d\n", __func__, rc); return rc;
}
static int
test_barrier(void)
{
- int32_t i, ret, rc[USE_NUM]; - - for (i = 0; i != RTE_DIM(rc); i++)
- rc[i] = plock_test(ITER_MAX, i); + int rc = plock_test(ITER_MAX);
- ret = 0; - for (i = 0; i != RTE_DIM(rc); i++) { - printf("%s for
utype=%d %s\n", - __func__, i, rc[i] == 0 ? "passed" : "failed"); -
ret |= rc[i]; - } + printf("%s %s\n", __func__, rc == 0 ? "passed" :
"failed");
- return ret; + return rc; }
REGISTER_PERF_TEST(barrier_autotest, test_barrier);
--
2.53.0