[dpdk-dev] [PATCH v3 9/9] ring: add C11 memory model for new sync modes

Ananyev, Konstantin konstantin.ananyev at intel.com
Tue Apr 14 20:29:38 CEST 2020


> <snip>
> 
> >  /**
> >   * @internal Enqueue several objects on the RTS ring.
> > diff --git a/lib/librte_ring/rte_ring_rts_c11_mem.h
> > b/lib/librte_ring/rte_ring_rts_c11_mem.h
> > new file mode 100644
> > index 000000000..b72901497
> > --- /dev/null
> > +++ b/lib/librte_ring/rte_ring_rts_c11_mem.h
> > @@ -0,0 +1,198 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + *
> > + * Copyright (c) 2010-2017 Intel Corporation
> > + * Copyright (c) 2007-2009 Kip Macy kmacy at freebsd.org
> > + * All rights reserved.
> > + * Derived from FreeBSD's bufring.h
> > + * Used as BSD-3 Licensed with permission from Kip Macy.
> > + */
> > +
> > +#ifndef _RTE_RING_RTS_C11_MEM_H_
> > +#define _RTE_RING_RTS_C11_MEM_H_
> > +
> > +/**
> > + * @file rte_ring_rts_c11_mem.h
> > + * It is not recommended to include this file directly,
> > + * include <rte_ring.h> instead.
> > + * Contains internal helper functions for Relaxed Tail Sync (RTS) ring mode.
> > + * For more information please refer to <rte_ring_rts.h>.
> > + */
> > +
> > +/**
> > + * @internal This function updates tail values.
> > + */
> > +static __rte_always_inline void
> > +__rte_ring_rts_update_tail(struct rte_ring_rts_headtail *ht) {
> > +	union rte_ring_ht_poscnt h, ot, nt;
> > +
> > +	/*
> > +	 * If there are other enqueues/dequeues in progress that
> > +	 * might preceded us, then don't update tail with new value.
> > +	 */
> > +
> > +	ot.raw = __atomic_load_n(&ht->tail.raw, __ATOMIC_ACQUIRE);
> This can be RELAXED. This thread is reading the value that it updated earlier, so it should be able to see the value it updated.

It serves as a hoist barrier, to make sure that we read tail before head (see below).
 
> > +
> > +	do {
> > +		/* on 32-bit systems we have to do atomic read here */
> > +		h.raw = __atomic_load_n(&ht->head.raw,
> > __ATOMIC_RELAXED);
> > +
> > +		nt.raw = ot.raw;
> > +		if (++nt.val.cnt == h.val.cnt)
> > +			nt.val.pos = h.val.pos;
> > +
> > +	} while (__atomic_compare_exchange_n(&ht->tail.raw, &ot.raw,
> > nt.raw,
> > +			0, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE) == 0); }
> > +
> > +/**
> > + * @internal This function waits till head/tail distance wouldn't
> > + * exceed pre-defined max value.
> > + */
> > +static __rte_always_inline void
> > +__rte_ring_rts_head_wait(const struct rte_ring_rts_headtail *ht,
> > +	union rte_ring_ht_poscnt *h)
> > +{
> > +	uint32_t max;
> > +
> > +	max = ht->htd_max;
> > +	h->raw = __atomic_load_n(&ht->head.raw, __ATOMIC_ACQUIRE);
> > +
> > +	while (h->val.pos - ht->tail.val.pos > max) {
> > +		rte_pause();
> > +		h->raw = __atomic_load_n(&ht->head.raw,
> > __ATOMIC_ACQUIRE);
> > +	}
> > +}
> > +



More information about the dev mailing list