All of lore.kernel.org
 help / color / mirror / Atom feed
From: Honnappa Nagarahalli <Honnappa.Nagarahalli@arm.com>
To: Konstantin Ananyev <konstantin.ananyev@intel.com>,
	"dev@dpdk.org" <dev@dpdk.org>
Cc: "david.marchand@redhat.com" <david.marchand@redhat.com>,
	"jielong.zjl@antfin.com" <jielong.zjl@antfin.com>,
	nd <nd@arm.com>,
	Honnappa Nagarahalli <Honnappa.Nagarahalli@arm.com>,
	nd <nd@arm.com>
Subject: Re: [dpdk-dev] [PATCH v5 2/9] ring: prepare ring to allow new sync schemes
Date: Sun, 19 Apr 2020 02:31:03 +0000	[thread overview]
Message-ID: <DBBPR08MB4646F43C7844F3F2D6B1200498D70@DBBPR08MB4646.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <20200418163225.17635-3-konstantin.ananyev@intel.com>

<snip>

> 
> To make these preparations two main things are done:
> - Change from *single* to *sync_type* to allow different
>   synchronisation schemes to be applied.
>   Mark *single* as deprecated in comments.
>   Add new functions to allow user to query ring sync types.
>   Replace direct access to *single* with appropriate function call.
> - Move actual rte_ring and related structures definitions into a
>   separate file: <rte_ring_core.h>. It allows to refer contents
>   of <rte_ring_elem.h> from <rte_ring.h> without introducing a
>   circular dependency.
> 
> Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
few nits inline, otherwise
Acked-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>

> ---
>  app/test/test_pdump.c           |   6 +-
>  lib/librte_pdump/rte_pdump.c    |   2 +-
>  lib/librte_port/rte_port_ring.c |  12 +--
>  lib/librte_ring/Makefile        |   1 +
>  lib/librte_ring/meson.build     |   1 +
>  lib/librte_ring/rte_ring.c      |   6 +-
>  lib/librte_ring/rte_ring.h      | 170 ++++++++++++++------------------
>  lib/librte_ring/rte_ring_core.h | 132 +++++++++++++++++++++++++
> lib/librte_ring/rte_ring_elem.h |  42 +++-----
>  9 files changed, 234 insertions(+), 138 deletions(-)  create mode 100644
> lib/librte_ring/rte_ring_core.h
> 
> diff --git a/app/test/test_pdump.c b/app/test/test_pdump.c index
> ad183184c..6a1180bcb 100644
> --- a/app/test/test_pdump.c
> +++ b/app/test/test_pdump.c
> @@ -57,8 +57,7 @@ run_pdump_client_tests(void)
>  	if (ret < 0)
>  		return -1;
>  	mp->flags = 0x0000;
> -	ring_client = rte_ring_create("SR0", RING_SIZE, rte_socket_id(),
> -				      RING_F_SP_ENQ | RING_F_SC_DEQ);
> +	ring_client = rte_ring_create("SR0", RING_SIZE, rte_socket_id(), 0);
>  	if (ring_client == NULL) {
>  		printf("rte_ring_create SR0 failed");
>  		return -1;
> @@ -71,9 +70,6 @@ run_pdump_client_tests(void)
>  	}
>  	rte_eth_dev_probing_finish(eth_dev);
> 
> -	ring_client->prod.single = 0;
> -	ring_client->cons.single = 0;
> -
>  	printf("\n***** flags = RTE_PDUMP_FLAG_TX *****\n");
> 
>  	for (itr = 0; itr < NUM_ITR; itr++) {
> diff --git a/lib/librte_pdump/rte_pdump.c b/lib/librte_pdump/rte_pdump.c
> index 8a01ac510..f96709f95 100644
> --- a/lib/librte_pdump/rte_pdump.c
> +++ b/lib/librte_pdump/rte_pdump.c
> @@ -380,7 +380,7 @@ pdump_validate_ring_mp(struct rte_ring *ring, struct
> rte_mempool *mp)
>  		rte_errno = EINVAL;
>  		return -1;
>  	}
> -	if (ring->prod.single || ring->cons.single) {
> +	if (rte_ring_is_prod_single(ring) || rte_ring_is_cons_single(ring)) {
>  		PDUMP_LOG(ERR, "ring with either SP or SC settings"
>  		" is not valid for pdump, should have MP and MC settings\n");
>  		rte_errno = EINVAL;
> diff --git a/lib/librte_port/rte_port_ring.c b/lib/librte_port/rte_port_ring.c
> index 47fcdd06a..52b2d8e55 100644
> --- a/lib/librte_port/rte_port_ring.c
> +++ b/lib/librte_port/rte_port_ring.c
> @@ -44,8 +44,8 @@ rte_port_ring_reader_create_internal(void *params, int
> socket_id,
>  	/* Check input parameters */
>  	if ((conf == NULL) ||
>  		(conf->ring == NULL) ||
> -		(conf->ring->cons.single && is_multi) ||
> -		(!(conf->ring->cons.single) && !is_multi)) {
> +		(rte_ring_is_cons_single(conf->ring) && is_multi) ||
> +		(!rte_ring_is_cons_single(conf->ring) && !is_multi)) {
>  		RTE_LOG(ERR, PORT, "%s: Invalid Parameters\n", __func__);
>  		return NULL;
>  	}
> @@ -171,8 +171,8 @@ rte_port_ring_writer_create_internal(void *params,
> int socket_id,
>  	/* Check input parameters */
>  	if ((conf == NULL) ||
>  		(conf->ring == NULL) ||
> -		(conf->ring->prod.single && is_multi) ||
> -		(!(conf->ring->prod.single) && !is_multi) ||
> +		(rte_ring_is_prod_single(conf->ring) && is_multi) ||
> +		(!rte_ring_is_prod_single(conf->ring) && !is_multi) ||
>  		(conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX)) {
>  		RTE_LOG(ERR, PORT, "%s: Invalid Parameters\n", __func__);
>  		return NULL;
> @@ -440,8 +440,8 @@ rte_port_ring_writer_nodrop_create_internal(void
> *params, int socket_id,
>  	/* Check input parameters */
>  	if ((conf == NULL) ||
>  		(conf->ring == NULL) ||
> -		(conf->ring->prod.single && is_multi) ||
> -		(!(conf->ring->prod.single) && !is_multi) ||
> +		(rte_ring_is_prod_single(conf->ring) && is_multi) ||
> +		(!rte_ring_is_prod_single(conf->ring) && !is_multi) ||
>  		(conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX)) {
>  		RTE_LOG(ERR, PORT, "%s: Invalid Parameters\n", __func__);
>  		return NULL;
> diff --git a/lib/librte_ring/Makefile b/lib/librte_ring/Makefile index
> 28368e6d1..6572768c9 100644
> --- a/lib/librte_ring/Makefile
> +++ b/lib/librte_ring/Makefile
> @@ -16,6 +16,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_RING) := rte_ring.c
> 
>  # install includes
>  SYMLINK-$(CONFIG_RTE_LIBRTE_RING)-include := rte_ring.h \
> +					rte_ring_core.h \
>  					rte_ring_elem.h \
>  					rte_ring_generic.h \
>  					rte_ring_c11_mem.h
> diff --git a/lib/librte_ring/meson.build b/lib/librte_ring/meson.build index
> 05402e4f0..c656781da 100644
> --- a/lib/librte_ring/meson.build
> +++ b/lib/librte_ring/meson.build
> @@ -3,6 +3,7 @@
> 
>  sources = files('rte_ring.c')
>  headers = files('rte_ring.h',
> +		'rte_ring_core.h',
>  		'rte_ring_elem.h',
>  		'rte_ring_c11_mem.h',
>  		'rte_ring_generic.h')
> diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c index
> 77e5de099..fa5733907 100644
> --- a/lib/librte_ring/rte_ring.c
> +++ b/lib/librte_ring/rte_ring.c
> @@ -106,8 +106,10 @@ rte_ring_init(struct rte_ring *r, const char *name,
> unsigned count,
>  	if (ret < 0 || ret >= (int)sizeof(r->name))
>  		return -ENAMETOOLONG;
>  	r->flags = flags;
> -	r->prod.single = (flags & RING_F_SP_ENQ) ? __IS_SP : __IS_MP;
> -	r->cons.single = (flags & RING_F_SC_DEQ) ? __IS_SC : __IS_MC;
> +	r->prod.sync_type = (flags & RING_F_SP_ENQ) ?
> +		RTE_RING_SYNC_ST : RTE_RING_SYNC_MT;
> +	r->cons.sync_type = (flags & RING_F_SC_DEQ) ?
> +		RTE_RING_SYNC_ST : RTE_RING_SYNC_MT;
> 
>  	if (flags & RING_F_EXACT_SZ) {
>  		r->size = rte_align32pow2(count + 1); diff --git
> a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h index
> 18fc5d845..35ee4491c 100644
> --- a/lib/librte_ring/rte_ring.h
> +++ b/lib/librte_ring/rte_ring.h
> @@ -36,91 +36,7 @@
>  extern "C" {
>  #endif
> 
> -#include <stdio.h>
> -#include <stdint.h>
> -#include <sys/queue.h>
> -#include <errno.h>
> -#include <rte_common.h>
> -#include <rte_config.h>
> -#include <rte_memory.h>
> -#include <rte_lcore.h>
> -#include <rte_atomic.h>
> -#include <rte_branch_prediction.h>
> -#include <rte_memzone.h>
> -#include <rte_pause.h>
> -
> -#define RTE_TAILQ_RING_NAME "RTE_RING"
> -
> -enum rte_ring_queue_behavior {
> -	RTE_RING_QUEUE_FIXED = 0, /* Enq/Deq a fixed number of items
> from a ring */
> -	RTE_RING_QUEUE_VARIABLE   /* Enq/Deq as many items as possible
> from ring */
> -};
> -
> -#define RTE_RING_MZ_PREFIX "RG_"
> -/** The maximum length of a ring name. */ -#define RTE_RING_NAMESIZE
> (RTE_MEMZONE_NAMESIZE - \
> -			   sizeof(RTE_RING_MZ_PREFIX) + 1)
> -
> -/* structure to hold a pair of head/tail values and other metadata */ -struct
> rte_ring_headtail {
> -	volatile uint32_t head;  /**< Prod/consumer head. */
> -	volatile uint32_t tail;  /**< Prod/consumer tail. */
> -	uint32_t single;         /**< True if single prod/cons */
> -};
> -
> -/**
> - * An RTE ring structure.
> - *
> - * The producer and the consumer have a head and a tail index. The
> particularity
> - * of these index is that they are not between 0 and size(ring). These indexes
> - * are between 0 and 2^32, and we mask their value when we access the
> ring[]
> - * field. Thanks to this assumption, we can do subtractions between 2 index
> - * values in a modulo-32bit base: that's why the overflow of the indexes is
> not
> - * a problem.
> - */
> -struct rte_ring {
> -	/*
> -	 * Note: this field kept the RTE_MEMZONE_NAMESIZE size due to ABI
> -	 * compatibility requirements, it could be changed to
> RTE_RING_NAMESIZE
> -	 * next time the ABI changes
> -	 */
> -	char name[RTE_MEMZONE_NAMESIZE] __rte_cache_aligned; /**<
> Name of the ring. */
> -	int flags;               /**< Flags supplied at creation. */
> -	const struct rte_memzone *memzone;
> -			/**< Memzone, if any, containing the rte_ring */
> -	uint32_t size;           /**< Size of ring. */
> -	uint32_t mask;           /**< Mask (size-1) of ring. */
> -	uint32_t capacity;       /**< Usable size of ring */
> -
> -	char pad0 __rte_cache_aligned; /**< empty cache line */
> -
> -	/** Ring producer status. */
> -	struct rte_ring_headtail prod __rte_cache_aligned;
> -	char pad1 __rte_cache_aligned; /**< empty cache line */
> -
> -	/** Ring consumer status. */
> -	struct rte_ring_headtail cons __rte_cache_aligned;
> -	char pad2 __rte_cache_aligned; /**< empty cache line */
> -};
> -
> -#define RING_F_SP_ENQ 0x0001 /**< The default enqueue is "single-
> producer". */ -#define RING_F_SC_DEQ 0x0002 /**< The default dequeue is
> "single-consumer". */
These do not appear in the API document anymore

> -/**
> - * Ring is to hold exactly requested number of entries.
> - * Without this flag set, the ring size requested must be a power of 2, and the
> - * usable space will be that size - 1. With the flag, the requested size will
> - * be rounded up to the next power of two, but the usable space will be
> exactly
> - * that requested. Worst case, if a power-of-2 size is requested, half the
> - * ring space will be wasted.
> - */
> -#define RING_F_EXACT_SZ 0x0004
> -#define RTE_RING_SZ_MASK  (0x7fffffffU) /**< Ring size mask */
> -
> -/* @internal defines for passing to the enqueue dequeue worker functions */
> -#define __IS_SP 1 -#define __IS_MP 0 -#define __IS_SC 1 -#define __IS_MC 0
> +#include <rte_ring_core.h>
> 
>  /**
>   * Calculate the memory size needed for a ring @@ -420,7 +336,7 @@
> rte_ring_mp_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
>  			 unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue(r, obj_table, n,
> RTE_RING_QUEUE_FIXED,
> -			__IS_MP, free_space);
> +			RTE_RING_SYNC_MT, free_space);
>  }
> 
>  /**
> @@ -443,9 +359,13 @@ rte_ring_sp_enqueue_bulk(struct rte_ring *r, void *
> const *obj_table,
>  			 unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue(r, obj_table, n,
> RTE_RING_QUEUE_FIXED,
> -			__IS_SP, free_space);
> +			RTE_RING_SYNC_ST, free_space);
>  }
> 
> +#ifdef ALLOW_EXPERIMENTAL_API
> +#include <rte_ring_elem.h>
> +#endif
> +
>  /**
>   * Enqueue several objects on a ring.
>   *
> @@ -470,7 +390,7 @@ rte_ring_enqueue_bulk(struct rte_ring *r, void *
> const *obj_table,
>  		      unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue(r, obj_table, n,
> RTE_RING_QUEUE_FIXED,
> -			r->prod.single, free_space);
> +			r->prod.sync_type, free_space);
>  }
> 
>  /**
> @@ -554,7 +474,7 @@ rte_ring_mc_dequeue_bulk(struct rte_ring *r, void
> **obj_table,
>  		unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue(r, obj_table, n,
> RTE_RING_QUEUE_FIXED,
> -			__IS_MC, available);
> +			RTE_RING_SYNC_MT, available);
>  }
> 
>  /**
> @@ -578,7 +498,7 @@ rte_ring_sc_dequeue_bulk(struct rte_ring *r, void
> **obj_table,
>  		unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue(r, obj_table, n,
> RTE_RING_QUEUE_FIXED,
> -			__IS_SC, available);
> +			RTE_RING_SYNC_ST, available);
>  }
> 
>  /**
> @@ -605,7 +525,7 @@ rte_ring_dequeue_bulk(struct rte_ring *r, void
> **obj_table, unsigned int n,
>  		unsigned int *available)
>  {
>  	return __rte_ring_do_dequeue(r, obj_table, n,
> RTE_RING_QUEUE_FIXED,
> -				r->cons.single, available);
> +				r->cons.sync_type, available);
>  }
> 
>  /**
> @@ -777,6 +697,62 @@ rte_ring_get_capacity(const struct rte_ring *r)
>  	return r->capacity;
>  }
> 
> +/**
> + * Return sync type used by producer in the ring.
> + *
> + * @param r
> + *   A pointer to the ring structure.
> + * @return
> + *   Producer sync type value.
> + */
> +static inline enum rte_ring_sync_type
> +rte_ring_get_prod_sync_type(const struct rte_ring *r) {
> +	return r->prod.sync_type;
> +}
> +
> +/**
> + * Check is the ring for single producer.
> + *
> + * @param r
> + *   A pointer to the ring structure.
> + * @return
> + *   true if ring is SP, zero otherwise.
> + */
> +static inline int
> +rte_ring_is_prod_single(const struct rte_ring *r) {
> +	return (rte_ring_get_prod_sync_type(r) == RTE_RING_SYNC_ST); }
> +
> +/**
> + * Return sync type used by consumer in the ring.
> + *
> + * @param r
> + *   A pointer to the ring structure.
> + * @return
> + *   Consumer sync type value.
> + */
> +static inline enum rte_ring_sync_type
> +rte_ring_get_cons_sync_type(const struct rte_ring *r) {
> +	return r->cons.sync_type;
> +}
> +
> +/**
> + * Check is the ring for single consumer.
> + *
> + * @param r
> + *   A pointer to the ring structure.
> + * @return
> + *   true if ring is SC, zero otherwise.
> + */
> +static inline int
> +rte_ring_is_cons_single(const struct rte_ring *r) {
> +	return (rte_ring_get_cons_sync_type(r) == RTE_RING_SYNC_ST); }
> +
>  /**
>   * Dump the status of all rings on the console
>   *
> @@ -820,7 +796,7 @@ rte_ring_mp_enqueue_burst(struct rte_ring *r, void *
> const *obj_table,
>  			 unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue(r, obj_table, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_MP, free_space);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT,
> free_space);
>  }
> 
>  /**
> @@ -843,7 +819,7 @@ rte_ring_sp_enqueue_burst(struct rte_ring *r, void *
> const *obj_table,
>  			 unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue(r, obj_table, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_SP, free_space);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST,
> free_space);
>  }
> 
>  /**
> @@ -870,7 +846,7 @@ rte_ring_enqueue_burst(struct rte_ring *r, void *
> const *obj_table,
>  		      unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue(r, obj_table, n,
> RTE_RING_QUEUE_VARIABLE,
> -			r->prod.single, free_space);
> +			r->prod.sync_type, free_space);
>  }
> 
>  /**
> @@ -898,7 +874,7 @@ rte_ring_mc_dequeue_burst(struct rte_ring *r, void
> **obj_table,
>  		unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue(r, obj_table, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_MC, available);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT,
> available);
>  }
> 
>  /**
> @@ -923,7 +899,7 @@ rte_ring_sc_dequeue_burst(struct rte_ring *r, void
> **obj_table,
>  		unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue(r, obj_table, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_SC, available);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST,
> available);
>  }
> 
>  /**
> @@ -951,7 +927,7 @@ rte_ring_dequeue_burst(struct rte_ring *r, void
> **obj_table,  {
>  	return __rte_ring_do_dequeue(r, obj_table, n,
>  				RTE_RING_QUEUE_VARIABLE,
> -				r->cons.single, available);
> +				r->cons.sync_type, available);
>  }
> 
>  #ifdef __cplusplus
> diff --git a/lib/librte_ring/rte_ring_core.h b/lib/librte_ring/rte_ring_core.h
I like this separation, thanks.

> new file mode 100644 index 000000000..d9cef763f
> --- /dev/null
> +++ b/lib/librte_ring/rte_ring_core.h
> @@ -0,0 +1,132 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 2010-2020 Intel Corporation
> + * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org
> + * All rights reserved.
> + * Derived from FreeBSD's bufring.h
> + * Used as BSD-3 Licensed with permission from Kip Macy.
> + */
> +
> +#ifndef _RTE_RING_CORE_H_
> +#define _RTE_RING_CORE_H_
> +
> +/**
> + * @file
> + * This file contains definion of RTE ring structure itself,
                                         ^^^^^^^ definition
> + * init flags and some related macros.
> + * For majority of DPDK entities, it is not recommended to include
> + * this file directly, use include <rte_ring.h> or <rte_ring_elem.h>
> + * instead.
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <sys/queue.h>
> +#include <errno.h>
> +#include <rte_common.h>
> +#include <rte_config.h>
> +#include <rte_memory.h>
> +#include <rte_lcore.h>
> +#include <rte_atomic.h>
> +#include <rte_branch_prediction.h>
> +#include <rte_memzone.h>
> +#include <rte_pause.h>
> +#include <rte_debug.h>
> +
> +#define RTE_TAILQ_RING_NAME "RTE_RING"
> +
> +/** enqueue/dequeue behavior types */
> +enum rte_ring_queue_behavior {
> +	/** Enq/Deq a fixed number of items from a ring */
> +	RTE_RING_QUEUE_FIXED = 0,
> +	/** Enq/Deq as many items as possible from ring */
> +	RTE_RING_QUEUE_VARIABLE
> +};
> +
> +#define RTE_RING_MZ_PREFIX "RG_"
> +/** The maximum length of a ring name. */ #define RTE_RING_NAMESIZE
> +(RTE_MEMZONE_NAMESIZE - \
> +			   sizeof(RTE_RING_MZ_PREFIX) + 1)
> +
> +/** prod/cons sync types */
> +enum rte_ring_sync_type {
> +	RTE_RING_SYNC_MT,     /**< multi-thread safe (default mode) */
> +	RTE_RING_SYNC_ST,     /**< single thread only */
> +};
> +
> +/**
> + * structures to hold a pair of head/tail values and other metadata.
> + * Depending on sync_type format of that structure might be different,
> + * but offset for *sync_type* and *tail* values should remain the same.
> + */
> +struct rte_ring_headtail {
> +	volatile uint32_t head;      /**< prod/consumer head. */
> +	volatile uint32_t tail;      /**< prod/consumer tail. */
> +	RTE_STD_C11
> +	union {
> +		/** sync type of prod/cons */
> +		enum rte_ring_sync_type sync_type;
> +		/** deprecated -  True if single prod/cons */
> +		uint32_t single;
> +	};
> +};
> +
> +/**
> + * An RTE ring structure.
> + *
> + * The producer and the consumer have a head and a tail index. The
> +particularity
> + * of these index is that they are not between 0 and size(ring). These
> +indexes
> + * are between 0 and 2^32, and we mask their value when we access the
> +ring[]
> + * field. Thanks to this assumption, we can do subtractions between 2
> +index
> + * values in a modulo-32bit base: that's why the overflow of the
> +indexes is not
> + * a problem.
> + */
> +struct rte_ring {
> +	/*
> +	 * Note: this field kept the RTE_MEMZONE_NAMESIZE size due to ABI
> +	 * compatibility requirements, it could be changed to
> RTE_RING_NAMESIZE
> +	 * next time the ABI changes
> +	 */
> +	char name[RTE_MEMZONE_NAMESIZE] __rte_cache_aligned;
> +	/**< Name of the ring. */
> +	int flags;               /**< Flags supplied at creation. */
> +	const struct rte_memzone *memzone;
> +			/**< Memzone, if any, containing the rte_ring */
> +	uint32_t size;           /**< Size of ring. */
> +	uint32_t mask;           /**< Mask (size-1) of ring. */
> +	uint32_t capacity;       /**< Usable size of ring */
> +
> +	char pad0 __rte_cache_aligned; /**< empty cache line */
> +
> +	/** Ring producer status. */
> +	struct rte_ring_headtail prod __rte_cache_aligned;
> +	char pad1 __rte_cache_aligned; /**< empty cache line */
> +
> +	/** Ring consumer status. */
> +	struct rte_ring_headtail cons __rte_cache_aligned;
> +	char pad2 __rte_cache_aligned; /**< empty cache line */ };
> +
> +#define RING_F_SP_ENQ 0x0001 /**< The default enqueue is
> +"single-producer". */ #define RING_F_SC_DEQ 0x0002 /**< The default
> +dequeue is "single-consumer". */
> +/**
> + * Ring is to hold exactly requested number of entries.
> + * Without this flag set, the ring size requested must be a power of 2,
> +and the
> + * usable space will be that size - 1. With the flag, the requested
> +size will
> + * be rounded up to the next power of two, but the usable space will be
> +exactly
> + * that requested. Worst case, if a power-of-2 size is requested, half
> +the
> + * ring space will be wasted.
> + */
> +#define RING_F_EXACT_SZ 0x0004
> +#define RTE_RING_SZ_MASK  (0x7fffffffU) /**< Ring size mask */
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_RING_CORE_H_ */
> diff --git a/lib/librte_ring/rte_ring_elem.h b/lib/librte_ring/rte_ring_elem.h
> index 663addc73..7406c0b0f 100644
> --- a/lib/librte_ring/rte_ring_elem.h
> +++ b/lib/librte_ring/rte_ring_elem.h
> @@ -20,21 +20,7 @@
>  extern "C" {
>  #endif
> 
> -#include <stdio.h>
> -#include <stdint.h>
> -#include <string.h>
> -#include <sys/queue.h>
> -#include <errno.h>
> -#include <rte_common.h>
> -#include <rte_config.h>
> -#include <rte_memory.h>
> -#include <rte_lcore.h>
> -#include <rte_atomic.h>
> -#include <rte_branch_prediction.h>
> -#include <rte_memzone.h>
> -#include <rte_pause.h>
> -
> -#include "rte_ring.h"
> +#include <rte_ring_core.h>
> 
>  /**
>   * @warning
> @@ -510,7 +496,7 @@ rte_ring_mp_enqueue_bulk_elem(struct rte_ring *r,
> const void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_FIXED, __IS_MP, free_space);
> +			RTE_RING_QUEUE_FIXED, RTE_RING_SYNC_MT,
> free_space);
>  }
> 
>  /**
> @@ -539,7 +525,7 @@ rte_ring_sp_enqueue_bulk_elem(struct rte_ring *r,
> const void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_FIXED, __IS_SP, free_space);
> +			RTE_RING_QUEUE_FIXED, RTE_RING_SYNC_ST,
> free_space);
>  }
> 
>  /**
> @@ -570,7 +556,7 @@ rte_ring_enqueue_bulk_elem(struct rte_ring *r, const
> void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_FIXED, r->prod.single, free_space);
> +			RTE_RING_QUEUE_FIXED, r->prod.sync_type,
> free_space);
>  }
> 
>  /**
> @@ -675,7 +661,7 @@ rte_ring_mc_dequeue_bulk_elem(struct rte_ring *r,
> void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
> -				RTE_RING_QUEUE_FIXED, __IS_MC, available);
> +				RTE_RING_QUEUE_FIXED,
> RTE_RING_SYNC_MT, available);
>  }
> 
>  /**
> @@ -703,7 +689,7 @@ rte_ring_sc_dequeue_bulk_elem(struct rte_ring *r,
> void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_FIXED, __IS_SC, available);
> +			RTE_RING_QUEUE_FIXED, RTE_RING_SYNC_ST,
> available);
>  }
> 
>  /**
> @@ -734,7 +720,7 @@ rte_ring_dequeue_bulk_elem(struct rte_ring *r, void
> *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_FIXED, r->cons.single, available);
> +			RTE_RING_QUEUE_FIXED, r->cons.sync_type,
> available);
>  }
> 
>  /**
> @@ -842,7 +828,7 @@ rte_ring_mp_enqueue_burst_elem(struct rte_ring *r,
> const void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_MP, free_space);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT,
> free_space);
>  }
> 
>  /**
> @@ -871,7 +857,7 @@ rte_ring_sp_enqueue_burst_elem(struct rte_ring *r,
> const void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_SP, free_space);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST,
> free_space);
>  }
> 
>  /**
> @@ -902,7 +888,7 @@ rte_ring_enqueue_burst_elem(struct rte_ring *r,
> const void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *free_space)  {
>  	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_VARIABLE, r->prod.single,
> free_space);
> +			RTE_RING_QUEUE_VARIABLE, r->prod.sync_type,
> free_space);
>  }
> 
>  /**
> @@ -934,7 +920,7 @@ rte_ring_mc_dequeue_burst_elem(struct rte_ring *r,
> void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_MC, available);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT,
> available);
>  }
> 
>  /**
> @@ -963,7 +949,7 @@ rte_ring_sc_dequeue_burst_elem(struct rte_ring *r,
> void *obj_table,
>  		unsigned int esize, unsigned int n, unsigned int *available)  {
>  	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
> -			RTE_RING_QUEUE_VARIABLE, __IS_SC, available);
> +			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST,
> available);
>  }
> 
>  /**
> @@ -995,9 +981,11 @@ rte_ring_dequeue_burst_elem(struct rte_ring *r,
> void *obj_table,  {
>  	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
>  				RTE_RING_QUEUE_VARIABLE,
> -				r->cons.single, available);
> +				r->cons.sync_type, available);
>  }
> 
> +#include <rte_ring.h>
> +
>  #ifdef __cplusplus
>  }
>  #endif
> --
> 2.17.1


  reply	other threads:[~2020-04-19  2:31 UTC|newest]

Thread overview: 146+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-24 11:35 [dpdk-dev] [RFC 0/6] New sync modes for ring Konstantin Ananyev
2020-02-24 11:35 ` [dpdk-dev] [RFC 1/6] test/ring: add contention stress test Konstantin Ananyev
2020-02-24 11:35 ` [dpdk-dev] [RFC 2/6] ring: rework ring layout to allow new sync schemes Konstantin Ananyev
2020-02-24 11:35 ` [dpdk-dev] [RFC 3/6] ring: introduce RTS ring mode Konstantin Ananyev
2020-02-24 11:35 ` [dpdk-dev] [RFC 4/6] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-02-24 11:35 ` [dpdk-dev] [RFC 5/6] ring: introduce HTS ring mode Konstantin Ananyev
2020-03-25 20:44   ` Honnappa Nagarahalli
2020-03-26 12:26     ` Ananyev, Konstantin
2020-02-24 11:35 ` [dpdk-dev] [RFC 6/6] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-02-24 16:59 ` [dpdk-dev] [RFC 0/6] New sync modes for ring Stephen Hemminger
2020-02-24 17:59   ` Jerin Jacob
2020-02-24 19:35     ` Stephen Hemminger
2020-02-24 20:52       ` Honnappa Nagarahalli
2020-02-25 11:45         ` Ananyev, Konstantin
2020-02-25 13:41       ` Ananyev, Konstantin
2020-02-26 16:53         ` Morten Brørup
2020-02-27 10:31         ` Jerin Jacob
2020-02-28  0:17           ` David Christensen
2020-03-20 16:45             ` Ananyev, Konstantin
2020-02-25  0:58     ` Honnappa Nagarahalli
2020-02-25 15:14       ` Ananyev, Konstantin
2020-03-25 20:43 ` Honnappa Nagarahalli
2020-03-26  1:50   ` Ananyev, Konstantin
2020-03-30 21:29     ` Honnappa Nagarahalli
2020-03-30 23:37       ` Honnappa Nagarahalli
2020-03-31 17:21         ` Ananyev, Konstantin
2020-03-31 16:43 ` [dpdk-dev] [PATCH v1 0/8] " Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 1/8] test/ring: add contention stress test Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 2/8] ring: prepare ring to allow new sync schemes Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 3/8] ring: introduce RTS ring mode Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 4/8] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 5/8] ring: introduce HTS ring mode Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 6/8] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 7/8] ring: introduce peek style API Konstantin Ananyev
2020-03-31 16:43   ` [dpdk-dev] [PATCH v1 8/8] test/ring: add stress test for MT peek API Konstantin Ananyev
2020-04-02 22:09   ` [dpdk-dev] [PATCH v2 0/9] New sync modes for ring Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 1/9] test/ring: add contention stress test Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 2/9] ring: prepare ring to allow new sync schemes Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 3/9] ring: introduce RTS ring mode Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 4/9] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 5/9] ring: introduce HTS ring mode Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 6/9] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 7/9] ring: introduce peek style API Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 8/9] test/ring: add stress test for MT peek API Konstantin Ananyev
2020-04-02 22:09     ` [dpdk-dev] [PATCH v2 9/9] ring: add C11 memory model for new sync modes Konstantin Ananyev
2020-04-03 17:42     ` [dpdk-dev] [PATCH v3 0/9] New sync modes for ring Konstantin Ananyev
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 1/9] test/ring: add contention stress test Konstantin Ananyev
2020-04-08  4:59         ` Honnappa Nagarahalli
2020-04-09 12:36           ` Ananyev, Konstantin
2020-04-09 13:00             ` Ananyev, Konstantin
2020-04-10 18:01               ` Honnappa Nagarahalli
2020-04-10 16:59             ` Honnappa Nagarahalli
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 2/9] ring: prepare ring to allow new sync schemes Konstantin Ananyev
2020-04-08  4:59         ` Honnappa Nagarahalli
2020-04-09 13:39           ` Ananyev, Konstantin
2020-04-10 20:15             ` Honnappa Nagarahalli
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 3/9] ring: introduce RTS ring mode Konstantin Ananyev
2020-04-04 17:27         ` Wang, Haiyue
2020-04-08  5:00         ` Honnappa Nagarahalli
2020-04-09 14:52           ` Ananyev, Konstantin
2020-04-10 23:10             ` Honnappa Nagarahalli
2020-04-13 14:29               ` David Marchand
2020-04-13 16:42                 ` Honnappa Nagarahalli
2020-04-14 13:47                   ` David Marchand
2020-04-14 15:57                     ` Honnappa Nagarahalli
2020-04-14 16:21                       ` Ananyev, Konstantin
2020-04-14 13:18               ` Ananyev, Konstantin
2020-04-14 15:58                 ` Honnappa Nagarahalli
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 4/9] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 5/9] ring: introduce HTS ring mode Konstantin Ananyev
2020-04-13 23:27         ` Honnappa Nagarahalli
2020-04-14 16:12           ` Ananyev, Konstantin
2020-04-14 17:06             ` Honnappa Nagarahalli
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 6/9] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 7/9] ring: introduce peek style API Konstantin Ananyev
2020-04-14  3:45         ` Honnappa Nagarahalli
2020-04-14 16:47           ` Ananyev, Konstantin
2020-04-14 17:30             ` Honnappa Nagarahalli
2020-04-14 22:24               ` Ananyev, Konstantin
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 8/9] test/ring: add stress test for MT peek API Konstantin Ananyev
2020-04-03 17:42       ` [dpdk-dev] [PATCH v3 9/9] ring: add C11 memory model for new sync modes Konstantin Ananyev
2020-04-04 14:16         ` [dpdk-dev] 回复:[PATCH " 周介龙
2020-04-14  4:28         ` [dpdk-dev] [PATCH " Honnappa Nagarahalli
2020-04-14 18:29           ` Ananyev, Konstantin
2020-04-15 20:28           ` Ananyev, Konstantin
2020-04-17 13:36       ` [dpdk-dev] [PATCH v4 0/9] New sync modes for ring Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 1/9] test/ring: add contention stress test Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 2/9] ring: prepare ring to allow new sync schemes Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 3/9] ring: introduce RTS ring mode Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 4/9] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 5/9] ring: introduce HTS ring mode Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 6/9] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 7/9] ring: introduce peek style API Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 8/9] test/ring: add stress test for MT peek API Konstantin Ananyev
2020-04-17 13:36         ` [dpdk-dev] [PATCH v4 9/9] test/ring: add functional tests for new sync modes Konstantin Ananyev
2020-04-18 16:32         ` [dpdk-dev] [PATCH v5 0/9] New sync modes for ring Konstantin Ananyev
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 1/9] test/ring: add contention stress test Konstantin Ananyev
2020-04-19  2:30             ` Honnappa Nagarahalli
2020-04-19  8:03               ` David Marchand
2020-04-19 11:47                 ` Ananyev, Konstantin
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 2/9] ring: prepare ring to allow new sync schemes Konstantin Ananyev
2020-04-19  2:31             ` Honnappa Nagarahalli [this message]
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 3/9] ring: introduce RTS ring mode Konstantin Ananyev
2020-04-19  2:31             ` Honnappa Nagarahalli
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 4/9] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-04-19  2:31             ` Honnappa Nagarahalli
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 5/9] ring: introduce HTS ring mode Konstantin Ananyev
2020-04-19  2:31             ` Honnappa Nagarahalli
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 6/9] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-04-19  2:31             ` Honnappa Nagarahalli
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 7/9] ring: introduce peek style API Konstantin Ananyev
2020-04-19  2:31             ` Honnappa Nagarahalli
2020-04-19 18:32               ` Ananyev, Konstantin
2020-04-19 19:12                 ` Ananyev, Konstantin
2020-04-19 21:14                   ` Honnappa Nagarahalli
2020-04-19 22:41                     ` Ananyev, Konstantin
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 8/9] test/ring: add stress test for MT peek API Konstantin Ananyev
2020-04-19  2:32             ` Honnappa Nagarahalli
2020-04-18 16:32           ` [dpdk-dev] [PATCH v5 9/9] test/ring: add functional tests for new sync modes Konstantin Ananyev
2020-04-19  2:32             ` Honnappa Nagarahalli
2020-04-19  2:32           ` [dpdk-dev] [PATCH v5 0/9] New sync modes for ring Honnappa Nagarahalli
2020-04-20 12:11           ` [dpdk-dev] [PATCH v6 00/10] " Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 01/10] test/ring: add contention stress test Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 02/10] ring: prepare ring to allow new sync schemes Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 03/10] ring: introduce RTS ring mode Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 04/10] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 05/10] ring: introduce HTS ring mode Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 06/10] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 07/10] ring: introduce peek style API Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 08/10] test/ring: add stress test for MT peek API Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 09/10] test/ring: add functional tests for new sync modes Konstantin Ananyev
2020-04-20 12:11             ` [dpdk-dev] [PATCH v6 10/10] doc: update ring guide Konstantin Ananyev
2020-04-20 13:47               ` David Marchand
2020-04-20 14:07                 ` Ananyev, Konstantin
2020-04-20 12:28             ` [dpdk-dev] [PATCH v7 00/10] New sync modes for ring Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 01/10] test/ring: add contention stress test Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 02/10] ring: prepare ring to allow new sync schemes Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 03/10] ring: introduce RTS ring mode Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 04/10] test/ring: add contention stress test for RTS ring Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 05/10] ring: introduce HTS ring mode Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 06/10] test/ring: add contention stress test for HTS ring Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 07/10] ring: introduce peek style API Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 08/10] test/ring: add stress test for MT peek API Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 09/10] test/ring: add functional tests for new sync modes Konstantin Ananyev
2020-04-20 12:28               ` [dpdk-dev] [PATCH v7 10/10] doc: update ring guide Konstantin Ananyev
2020-04-21 11:31               ` [dpdk-dev] [PATCH v7 00/10] New sync modes for ring David Marchand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DBBPR08MB4646F43C7844F3F2D6B1200498D70@DBBPR08MB4646.eurprd08.prod.outlook.com \
    --to=honnappa.nagarahalli@arm.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=jielong.zjl@antfin.com \
    --cc=konstantin.ananyev@intel.com \
    --cc=nd@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.