From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from dpdk.org (dpdk.org [92.243.14.124])
	by inbox.dpdk.org (Postfix) with ESMTP id C65B9A0577;
	Tue, 14 Apr 2020 05:45:25 +0200 (CEST)
Received: from [92.243.14.124] (localhost [127.0.0.1])
	by dpdk.org (Postfix) with ESMTP id 054671C05C;
	Tue, 14 Apr 2020 05:45:25 +0200 (CEST)
Received: from EUR04-DB3-obe.outbound.protection.outlook.com
 (mail-eopbgr60062.outbound.protection.outlook.com [40.107.6.62])
 by dpdk.org (Postfix) with ESMTP id F15BD1C039
 for <dev@dpdk.org>; Tue, 14 Apr 2020 05:45:23 +0200 (CEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; 
 s=selector2-armh-onmicrosoft-com;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=tK5dsnillMEWHVc0P+Z400VLhX4OFGmXlSRay80H0Sg=;
 b=0QRcItANZH0HyhElbPgBFBca6ZEGbkvXMzOnIcqlaN0YOvrG8WpNe+bCJsNPoTqA18OK1BuzKoTKX2s8unEYwmahtyqwUSHsPM9JTdvYlHxjp5srwtcHUyxKYMXosnI3odM/X7FM5CB6kgRspCXLNaGWEEQc5w1sEXELWMjFBuE=
Received: from DB6PR0501CA0041.eurprd05.prod.outlook.com (2603:10a6:4:67::27)
 by DBBPR08MB4348.eurprd08.prod.outlook.com (2603:10a6:10:cc::10) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2900.26; Tue, 14 Apr
 2020 03:45:22 +0000
Received: from DB5EUR03FT046.eop-EUR03.prod.protection.outlook.com
 (2603:10a6:4:67:cafe::a1) by DB6PR0501CA0041.outlook.office365.com
 (2603:10a6:4:67::27) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2900.17 via Frontend
 Transport; Tue, 14 Apr 2020 03:45:22 +0000
Authentication-Results: spf=pass (sender IP is 63.35.35.123)
 smtp.mailfrom=arm.com; dpdk.org; dkim=pass (signature was verified)
 header.d=armh.onmicrosoft.com;dpdk.org; dmarc=bestguesspass action=none
 header.from=arm.com;
Received-SPF: Pass (protection.outlook.com: domain of arm.com designates
 63.35.35.123 as permitted sender) receiver=protection.outlook.com;
 client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com;
Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by
 DB5EUR03FT046.mail.protection.outlook.com (10.152.21.230) with
 Microsoft SMTP
 Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.2900.18 via Frontend Transport; Tue, 14 Apr 2020 03:45:22 +0000
Received: ("Tessian outbound af37c2b81632:v50");
 Tue, 14 Apr 2020 03:45:22 +0000
X-CR-MTA-TID: 64aa7808
Received: from ce018ca2c0ab.2
 by 64aa7808-outbound-1.mta.getcheckrecipient.com id
 ADD07542-28A6-4462-8C13-900BE281CEC3.1; 
 Tue, 14 Apr 2020 03:45:17 +0000
Received: from EUR04-HE1-obe.outbound.protection.outlook.com
 by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id ce018ca2c0ab.2
 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384);
 Tue, 14 Apr 2020 03:45:17 +0000
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=BYop0K4MDoN79I5DdaqE07iMGm2OQMV+UMaBNsJZIN9whbUBe+KmOo6rh/NWxLKUlsPw6OI6byqdr/lRRebjSz8QggXfyuT8xIsmQHKoWJmjflcKj9aByBAcFH6ZX3Ka/FSH5DHATjeEmGYkp1RARDalnCfp1rAsOqk3FOv+91OpvfnhupuLJDqR+gtwQB/VATqzEZf67ICNkLiMVPBw+42v6wZ4yYO245YHsD4avTS5GGSUp6+xm7Hmfo3lD4lGSsIZxRbcqOcK9fS82ILGH2JToS/I7Cz1B7gftAp/gusYTbEFluEKS1t6jXvJ+AFIBMuflb+EI4O9t24OERBq3A==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; 
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=tK5dsnillMEWHVc0P+Z400VLhX4OFGmXlSRay80H0Sg=;
 b=keO6xxBVGEb1U4Q2RMAM2h0ODbpaFvnGGiW0GpGipzxBUcE22DARIHLOoB2q+6LmXaj1o/Wein/bLyDqcpHdEzqn6zYeRW2z73e2lPUjD7toszHzSM5UsE0z+Yz0Q5BNqQ+4F0sZ58XtrXRdE09x+nGCIWDyv3+aYggb/WNFtIgfWEUvH2qPb/r+s8EwN2kYT99D64X6SL1m2gnavNVWfoT2sRV+C23T6eBIIuRhN7Yx0DoEVQeTdqNfQ0gyvQzsOmmjuqL9a5Rn5PUS+SEVcitxXIh/tDZv40gcXA3xVm0zH/FddBdGPJnWO/uFdudMRdbB6WFfBSERN1nBnjCD/Q==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
 smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass
 header.d=arm.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; 
 s=selector2-armh-onmicrosoft-com;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=tK5dsnillMEWHVc0P+Z400VLhX4OFGmXlSRay80H0Sg=;
 b=0QRcItANZH0HyhElbPgBFBca6ZEGbkvXMzOnIcqlaN0YOvrG8WpNe+bCJsNPoTqA18OK1BuzKoTKX2s8unEYwmahtyqwUSHsPM9JTdvYlHxjp5srwtcHUyxKYMXosnI3odM/X7FM5CB6kgRspCXLNaGWEEQc5w1sEXELWMjFBuE=
Received: from DBBPR08MB4646.eurprd08.prod.outlook.com (2603:10a6:10:f5::16)
 by DBBPR08MB4677.eurprd08.prod.outlook.com (2603:10a6:10:f1::22) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2900.24; Tue, 14 Apr
 2020 03:45:14 +0000
Received: from DBBPR08MB4646.eurprd08.prod.outlook.com
 ([fe80::1870:afc4:b90f:609d]) by DBBPR08MB4646.eurprd08.prod.outlook.com
 ([fe80::1870:afc4:b90f:609d%5]) with mapi id 15.20.2900.028; Tue, 14 Apr 2020
 03:45:14 +0000
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>
Thread-Topic: [PATCH v3 7/9] ring: introduce peek style API
Thread-Index: AQHWCd9cfoGjgBmDwE6GtYzbMvcpp6h3xDiA
Date: Tue, 14 Apr 2020 03:45:14 +0000
Message-ID: <DBBPR08MB46469564CBBABD78EA7F8F5698DA0@DBBPR08MB4646.eurprd08.prod.outlook.com>
References: <20200402220959.29885-1-konstantin.ananyev@intel.com>
 <20200403174235.23308-1-konstantin.ananyev@intel.com>
 <20200403174235.23308-8-konstantin.ananyev@intel.com>
In-Reply-To: <20200403174235.23308-8-konstantin.ananyev@intel.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-ts-tracking-id: 74a42b23-7d50-4c74-9409-c3e72a39b322.0
x-checkrecipientchecked: true
Authentication-Results-Original: spf=none (sender IP is )
 smtp.mailfrom=Honnappa.Nagarahalli@arm.com; 
x-originating-ip: [70.113.25.165]
x-ms-publictraffictype: Email
X-MS-Office365-Filtering-HT: Tenant
X-MS-Office365-Filtering-Correlation-Id: 36e0f147-545c-42d9-1720-08d7e02642b2
x-ms-traffictypediagnostic: DBBPR08MB4677:|DBBPR08MB4677:|DBBPR08MB4348:
x-ms-exchange-transport-forked: True
X-Microsoft-Antispam-PRVS: <DBBPR08MB4348B53137DBA2ED3156AB2598DA0@DBBPR08MB4348.eurprd08.prod.outlook.com>
x-checkrecipientrouted: true
nodisclaimer: true
x-ms-oob-tlc-oobclassifiers: OLM:9508;OLM:9508;
x-forefront-prvs: 0373D94D15
X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en;
 SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DBBPR08MB4646.eurprd08.prod.outlook.com;
 PTR:; CAT:NONE; SFTY:;
 SFS:(10009020)(4636009)(136003)(396003)(39860400002)(376002)(346002)(366004)(55016002)(26005)(8676002)(2906002)(33656002)(9686003)(81156014)(8936002)(4326008)(76116006)(110136005)(316002)(54906003)(66946007)(66446008)(64756008)(66476007)(6506007)(478600001)(186003)(71200400001)(7696005)(30864003)(66556008)(86362001)(5660300002)(52536014);
 DIR:OUT; SFP:1101; 
received-spf: None (protection.outlook.com: arm.com does not designate
 permitted sender hosts)
X-MS-Exchange-SenderADCheck: 1
X-Microsoft-Antispam-Untrusted: BCL:0;
X-Microsoft-Antispam-Message-Info-Original: Zk8liykgatn9Xm9nvcIa0z/ZPouBPalSOMSCH88/BOuXnPmWrqRxpElWYRou25XGR77gv7GygBLJrF9gcHxDy/FLmrbOwrAaJKOWKcVGNcikqVcmYO6ZmwE3rJMYkJdFo+xuhQHNiIlCXI4BoPtvUQsWXJXyV97/sxgKt1u0aGon2HkdYzS9JMy6cy5Ea0u4i6qIYC17asT7hu9MLKPkWghgnKv9ASWDSnX0L4LCS1Tijsa9jcCtQANA7ehJAEDWtRzqI5I23QxWqt+hbprxnEpMrYZFHoFq0LgDQSWoA26l2yIn02FVh8YpVyeIxV5DRHTE2iUNOCCy2Z2ULM9D+V6TAiGzwWRqUakPPUUsSPms/Vj2QKyjQeKFg65FkR05XtW26cI2ZRqGl0NM5dRrqELHadL//iook4EjY6QVPC3sFRwcstlaftwGQ6uoejdC
x-ms-exchange-antispam-messagedata: 0Cgpr1Lr8eZXjtmxVBQ07EMLlcs8+p5sY4BJNts77Y6EgwO/1KW/7JmfOu7gybeOgKfwlKBHicUjQYPhyJcxY6HfU9N1jF4OtEpmNGoukriC0v0W0xTwvqqxUU619DEdoIhySQit4ibWidA5llIc7g==
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4677
Original-Authentication-Results: spf=none (sender IP is )
 smtp.mailfrom=Honnappa.Nagarahalli@arm.com; 
X-EOPAttributedMessage: 0
X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB5EUR03FT046.eop-EUR03.prod.protection.outlook.com
X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:;
 IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com;
 PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFTY:;
 SFS:(10009020)(4636009)(396003)(136003)(39860400002)(376002)(346002)(46966005)(316002)(70206006)(30864003)(9686003)(55016002)(336012)(70586007)(5660300002)(81166007)(86362001)(356005)(47076004)(8936002)(33656002)(81156014)(26826003)(186003)(2906002)(4326008)(52536014)(54906003)(6506007)(8676002)(82740400003)(7696005)(26005)(110136005)(478600001);
 DIR:OUT; SFP:1101; 
X-MS-Office365-Filtering-Correlation-Id-Prvs: c9baa1a1-f6a0-4f23-86a2-08d7e0263dc1
X-Forefront-PRVS: 0373D94D15
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: TIceXtd9MKhJt4+ZkfQOFfeA2S5PjzMqGMBi85bt4M6SK6yQvc5d1SZQu4WV/jIcDQHdeMvxD4fbIZzAQ/QU7lQStI5yp+qGaTv6lkKuewTsdUFKvO2t9Z3kRa9rDdzKlbdRyoZ+gLPopSUm4f4hfjaYstyMV36L1VR2gfbNjdX/QLgLVnDNam85YVqnNXkUPwm531sJdyXtlhldm6yKGnuQk8Kr1iES87uD2RglLkUpS/dI4OhB89tbJBcE2Um9drw7vWFPVl4Hd+qOWRTilKByQGKGMdF0hyUjcbJzdvE5BIl4SqYiq0ELvkSSRorJy5xInpshVhgCybXxAdCbIoMOVk7Ztjm9UHI7FZBEKL53gcDfe5SnAtmsr3qOXMqfX1WXUPgHXll4Aw5C8gWswHxHysHCzEO9okPbdqUGFabxNMJMg5ZYDa1UG7nQuPKENc4P9IeRo5xVBCzm+0w0P2q1drDjsuqVfyNduVEq4dF8NbbY9m1YX5EZvKZQvqR+V5lvnv4unB8GATgJrUmGMQ==
X-OriginatorOrg: arm.com
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 14 Apr 2020 03:45:22.8481 (UTC)
X-MS-Exchange-CrossTenant-Network-Message-Id: 36e0f147-545c-42d9-1720-08d7e02642b2
X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d
X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123];
 Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com]
X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4348
Subject: Re: [dpdk-dev] [PATCH v3 7/9] ring: introduce peek style API
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org
Sender: "dev" <dev-bounces@dpdk.org>

<snip>

>=20
> For rings with producer/consumer in RTE_RING_SYNC_ST,
> RTE_RING_SYNC_MT_HTS mode, provide an ability to split enqueue/dequeue
> operation into two phases:
>       - enqueue/dequeue start
>       - enqueue/dequeue finish
> That allows user to inspect objects in the ring without removing them fro=
m it
> (aka MT safe peek).
>=20
> Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---
>  lib/librte_ring/Makefile               |   1 +
>  lib/librte_ring/meson.build            |   1 +
>  lib/librte_ring/rte_ring_c11_mem.h     |  44 +++
>  lib/librte_ring/rte_ring_elem.h        |   4 +
>  lib/librte_ring/rte_ring_generic.h     |  48 ++++
>  lib/librte_ring/rte_ring_hts_generic.h |  47 ++-
>  lib/librte_ring/rte_ring_peek.h        | 379 +++++++++++++++++++++++++
>  7 files changed, 519 insertions(+), 5 deletions(-)  create mode 100644
> lib/librte_ring/rte_ring_peek.h
>=20
> diff --git a/lib/librte_ring/Makefile b/lib/librte_ring/Makefile index
> 6fe500f0d..5f8662737 100644
> --- a/lib/librte_ring/Makefile
> +++ b/lib/librte_ring/Makefile
> @@ -22,6 +22,7 @@ SYMLINK-$(CONFIG_RTE_LIBRTE_RING)-include :=3D
> rte_ring.h \
>  					rte_ring_hts.h \
>  					rte_ring_hts_elem.h \
>  					rte_ring_hts_generic.h \
> +					rte_ring_peek.h \
>  					rte_ring_rts.h \
>  					rte_ring_rts_elem.h \
>  					rte_ring_rts_generic.h
> diff --git a/lib/librte_ring/meson.build b/lib/librte_ring/meson.build in=
dex
> 8e86e037a..f5f84dc6e 100644
> --- a/lib/librte_ring/meson.build
> +++ b/lib/librte_ring/meson.build
> @@ -9,6 +9,7 @@ headers =3D files('rte_ring.h',
>  		'rte_ring_hts.h',
>  		'rte_ring_hts_elem.h',
>  		'rte_ring_hts_generic.h',
> +		'rte_ring_peek.h',
>  		'rte_ring_rts.h',
>  		'rte_ring_rts_elem.h',
>  		'rte_ring_rts_generic.h')
> diff --git a/lib/librte_ring/rte_ring_c11_mem.h
> b/lib/librte_ring/rte_ring_c11_mem.h
> index 0fb73a337..bb3096721 100644
> --- a/lib/librte_ring/rte_ring_c11_mem.h
> +++ b/lib/librte_ring/rte_ring_c11_mem.h
> @@ -10,6 +10,50 @@
>  #ifndef _RTE_RING_C11_MEM_H_
>  #define _RTE_RING_C11_MEM_H_
>=20
> +/**
> + * @internal get current tail value.
> + * This function should be used only for single thread producer/consumer=
.
> + * Check that user didn't request to move tail above the head.
Do we need this check? This could be a data path function, we could documen=
t a warning and leave it to the users to provide the correct value.

> + * In that situation:
> + * - return zero, that will cause abort any pending changes and
> + *   return head to its previous position.
> + * - throw an assert in debug mode.
> + */
> +static __rte_always_inline uint32_t
> +__rte_ring_st_get_tail(struct rte_ring_headtail *ht, uint32_t *tail,
> +	uint32_t num)
> +{
> +	uint32_t h, n, t;
> +
> +	h =3D ht->head;
> +	t =3D ht->tail;
> +	n =3D h - t;
> +
> +	RTE_ASSERT(n >=3D num);
> +	num =3D (n >=3D num) ? num : 0;
> +
> +	*tail =3D h;
> +	return num;
> +}
> +
> +/**
> + * @internal set new values for head and tail.
> + * This function should be used only for single thread producer/consumer=
.
> + * Should be used only in conjunction with __rte_ring_st_get_tail.
> + */
> +static __rte_always_inline void
> +__rte_ring_st_set_head_tail(struct rte_ring_headtail *ht, uint32_t tail,
> +	uint32_t num, uint32_t enqueue)
> +{
> +	uint32_t pos;
> +
> +	RTE_SET_USED(enqueue);
> +
> +	pos =3D tail + num;
> +	ht->head =3D pos;
> +	__atomic_store_n(&ht->tail, pos, __ATOMIC_RELEASE); }
> +
>  static __rte_always_inline void
>  update_tail(struct rte_ring_headtail *ht, uint32_t old_val, uint32_t new=
_val,
>  		uint32_t single, uint32_t enqueue)
> diff --git a/lib/librte_ring/rte_ring_elem.h b/lib/librte_ring/rte_ring_e=
lem.h
> index 010a564c1..5bf7c1c1b 100644
> --- a/lib/librte_ring/rte_ring_elem.h
> +++ b/lib/librte_ring/rte_ring_elem.h
> @@ -1083,6 +1083,10 @@ rte_ring_dequeue_burst_elem(struct rte_ring *r,
> void *obj_table,
>  	return 0;
>  }
>=20
> +#ifdef ALLOW_EXPERIMENTAL_API
> +#include <rte_ring_peek.h>
> +#endif
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/lib/librte_ring/rte_ring_generic.h
> b/lib/librte_ring/rte_ring_generic.h
> index 953cdbbd5..9f5fdf13b 100644
> --- a/lib/librte_ring/rte_ring_generic.h
> +++ b/lib/librte_ring/rte_ring_generic.h
> @@ -10,6 +10,54 @@
>  #ifndef _RTE_RING_GENERIC_H_
>  #define _RTE_RING_GENERIC_H_
>=20
> +/**
> + * @internal get current tail value.
> + * This function should be used only for single thread producer/consumer=
.
> + * Check that user didn't request to move tail above the head.
> + * In that situation:
> + * - return zero, that will cause abort any pending changes and
> + *   return head to its previous position.
> + * - throw an assert in debug mode.
> + */
> +static __rte_always_inline uint32_t
> +__rte_ring_st_get_tail(struct rte_ring_headtail *ht, uint32_t *tail,
> +	uint32_t num)
> +{
> +	uint32_t h, n, t;
> +
> +	h =3D ht->head;
> +	t =3D ht->tail;
> +	n =3D h - t;
> +
> +	RTE_ASSERT(n >=3D num);
> +	num =3D (n >=3D num) ? num : 0;
> +
> +	*tail =3D h;
> +	return num;
> +}
> +
> +/**
> + * @internal set new values for head and tail.
> + * This function should be used only for single thread producer/consumer=
.
> + * Should be used only in conjunction with __rte_ring_st_get_tail.
> + */
> +static __rte_always_inline void
> +__rte_ring_st_set_head_tail(struct rte_ring_headtail *ht, uint32_t tail,
> +	uint32_t num, uint32_t enqueue)
> +{
> +	uint32_t pos;
> +
> +	pos =3D tail + num;
> +
> +	if (enqueue)
> +		rte_smp_wmb();
> +	else
> +		rte_smp_rmb();
> +
> +	ht->head =3D pos;
> +	ht->tail =3D pos;
> +}
> +
>  static __rte_always_inline void
>  update_tail(struct rte_ring_headtail *ht, uint32_t old_val, uint32_t new=
_val,
>  		uint32_t single, uint32_t enqueue)
> diff --git a/lib/librte_ring/rte_ring_hts_generic.h
> b/lib/librte_ring/rte_ring_hts_generic.h
> index da08f1d94..8e699c006 100644
> --- a/lib/librte_ring/rte_ring_hts_generic.h
> +++ b/lib/librte_ring/rte_ring_hts_generic.h
> @@ -18,9 +18,38 @@
>   * For more information please refer to <rte_ring_hts.h>.
>   */
>=20
> +/**
> + * @internal get current tail value.
> + * Check that user didn't request to move tail above the head.
> + * In that situation:
> + * - return zero, that will cause abort any pending changes and
> + *   return head to its previous position.
> + * - throw an assert in debug mode.
> + */
> +static __rte_always_inline uint32_t
> +__rte_ring_hts_get_tail(struct rte_ring_hts_headtail *ht, uint32_t *tail=
,
> +	uint32_t num)
> +{
> +	uint32_t n;
> +	union rte_ring_ht_pos p;
> +
> +	p.raw =3D rte_atomic64_read((rte_atomic64_t *)(uintptr_t)&ht-
> >ht.raw);
> +	n =3D p.pos.head - p.pos.tail;
> +
> +	RTE_ASSERT(n >=3D num);
> +	num =3D (n >=3D num) ? num : 0;
> +
> +	*tail =3D p.pos.tail;
> +	return num;
> +}
> +
> +/**
> + * @internal set new values for head and tail as one atomic 64 bit opera=
tion.
> + * Should be used only in conjunction with __rte_ring_hts_get_tail.
> + */
>  static __rte_always_inline void
> -__rte_ring_hts_update_tail(struct rte_ring_hts_headtail *ht, uint32_t nu=
m,
> -	uint32_t enqueue)
> +__rte_ring_hts_set_head_tail(struct rte_ring_hts_headtail *ht, uint32_t =
tail,
> +	uint32_t num, uint32_t enqueue)
>  {
>  	union rte_ring_ht_pos p;
>=20
> @@ -29,14 +58,22 @@ __rte_ring_hts_update_tail(struct
> rte_ring_hts_headtail *ht, uint32_t num,
>  	else
>  		rte_smp_rmb();
>=20
> -	p.raw =3D rte_atomic64_read((rte_atomic64_t *)(uintptr_t)&ht-
> >ht.raw);
> -
> -	p.pos.head =3D p.pos.tail + num;
> +	p.pos.head =3D tail + num;
>  	p.pos.tail =3D p.pos.head;
>=20
>  	rte_atomic64_set((rte_atomic64_t *)(uintptr_t)&ht->ht.raw, p.raw);  }
>=20
> +static __rte_always_inline void
> +__rte_ring_hts_update_tail(struct rte_ring_hts_headtail *ht, uint32_t nu=
m,
> +	uint32_t enqueue)
> +{
> +	uint32_t tail;
> +
> +	num =3D __rte_ring_hts_get_tail(ht, &tail, num);
> +	__rte_ring_hts_set_head_tail(ht, tail, num, enqueue); }
> +
>  /**
>   * @internal waits till tail will become equal to head.
>   * Means no writer/reader is active for that ring.
> diff --git a/lib/librte_ring/rte_ring_peek.h b/lib/librte_ring/rte_ring_p=
eek.h
> new file mode 100644 index 000000000..baefd2f7b
> --- /dev/null
> +++ b/lib/librte_ring/rte_ring_peek.h
> @@ -0,0 +1,379 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 2010-2017 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_PEEK_H_
> +#define _RTE_RING_PEEK_H_
> +
> +/**
> + * @file
> + * @b EXPERIMENTAL: this API may change without prior notice
> + * It is not recommended to include this file directly.
> + * Please include <rte_ring_elem.h> instead.
> + *
> + * Ring Peek AP
                            ^^^ API
> + * Introduction of rte_ring with serialized producer/consumer (HTS sync
> +mode)
> + * makes possible to split public enqueue/dequeue API into two phases:
> + * - enqueue/dequeue start
> + * - enqueue/dequeue finish
> + * That allows user to inspect objects in the ring without removing
> +them
> + * from it (aka MT safe peek).
> + * Note that right now this new API is avaialble only for two sync modes=
:
> + * 1) Single Producer/Single Consumer (RTE_RING_SYNC_ST)
> + * 2) Serialized Producer/Serialized Consumer (RTE_RING_SYNC_MT_HTS).
> + * It is a user responsibility to create/init ring with appropriate
> +sync
> + * modes selected.
> + * As an example:
> + * // read 1 elem from the ring:
> + * n =3D rte_ring_hts_dequeue_bulk_start(ring, &obj, 1, NULL);
> + * if (n !=3D 0) {
> + *    //examine object
> + *    if (object_examine(obj) =3D=3D KEEP)
> + *       //decided to keep it in the ring.
> + *       rte_ring_hts_dequeue_finish(ring, 0);
> + *    else
> + *       //decided to remove it from the ring.
> + *       rte_ring_hts_dequeue_finish(ring, n);
> + * }
> + * Note that between _start_ and _finish_ the ring is sort of locked -
                                                                           =
       ^^^^^^^^^^^^^^^^^^^^ - 'locked' can mean different to different peop=
le, may be remove this, the next sentence anyway has the description
> + * none other thread can proceed with enqueue(/dequeue) operation till
          ^^^^ no
> + * _finish_ will complete.
                         ^^^^^^^^^^^ completes
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +

<snip>

> +
> +/**
> + * Start to enqueue several objects on the ring.
> + * Note that no actual objects are put in the queue by this function,
> + * it just reserves for user such ability.
> + * User has to call appropriate enqueue_finish() to copy objects into
> +the
> + * queue and complete given enqueue operation.
> + *
> + * @param r
> + *   A pointer to the ring structure.
> + * @param n
> + *   The number of objects to add in the ring from the obj_table.
> + * @param free_space
> + *   if non-NULL, returns the amount of space in the ring after the
> + *   enqueue operation has finished.
> + * @return
> + *   The number of objects that can be enqueued, either 0 or n
> + */
> +__rte_experimental
> +static __rte_always_inline unsigned int
> +rte_ring_enqueue_bulk_start(struct rte_ring *r, unsigned int n,
> +		unsigned int *free_space)
If one wants to use _elem_ APIs for ring peek, a combination of legacy API =
(format) and a _elem_ API is required.
For ex:
rte_ring_enqueue_bulk_start
rte_ring_enqueue_elem_finish

I understand why you have done this. I think this is getting somewhat too i=
nconsistent.

> +{
> +	return __rte_ring_do_enqueue_start(r, n, RTE_RING_QUEUE_FIXED,
> +			free_space);
> +}
> +

<snip>

> +
> +/**
> + * Start to dequeue several objects from the ring.
> + * Note that user has to call appropriate dequeue_finish()
> + * to complete given dequeue operation and actually remove objects the r=
ing.
> + *
> + * @param r
> + *   A pointer to the ring structure.
> + * @param obj_table
> + *   A pointer to a table of void * pointers (objects) that will be fill=
ed.
> + * @param esize
> + *   The size of ring element, in bytes. It must be a multiple of 4.
> + *   This must be the same value used while creating the ring. Otherwise
> + *   the results are undefined.
> + * @param n
> + *   The number of objects to dequeue from the ring to the obj_table.
> + * @param available
> + *   If non-NULL, returns the number of remaining ring entries after the
> + *   dequeue has finished.
> + * @return
> + *   Actual number of objects dequeued.
> + */
> +__rte_experimental
> +static __rte_always_inline unsigned int
> +rte_ring_dequeue_bulk_start(struct rte_ring *r, void **obj_table,
> +		unsigned int n, unsigned int *available) {
Should this in a separate file? (similar to rte_ring.h and rte_ring_elem.h)

> +	return rte_ring_dequeue_bulk_elem_start(r, obj_table,
> sizeof(uintptr_t),
> +		n, available);
> +}
> +
> +/**
> + * Start to dequeue several objects from the ring.
> + * Note that user has to call appropriate dequeue_finish()
> + * to complete given dequeue operation and actually remove objects the r=
ing.
> + *
> + * @param r
> + *   A pointer to the ring structure.
> + * @param obj_table
> + *   A pointer to a table of void * pointers (objects) that will be fill=
ed.
Minor, update this to indicate generic objects. Can be copied from rte_ring=
_elem.h.

> + * @param esize
> + *   The size of ring element, in bytes. It must be a multiple of 4.
> + *   This must be the same value used while creating the ring. Otherwise
> + *   the results are undefined.
> + * @param n
> + *   The number of objects to dequeue from the ring to the obj_table.
> + * @param available
> + *   If non-NULL, returns the number of remaining ring entries after the
> + *   dequeue has finished.
> + * @return
> + *   The actual number of objects dequeued.
> + */
> +__rte_experimental
> +static __rte_always_inline unsigned int
> +rte_ring_dequeue_burst_elem_start(struct rte_ring *r, void **obj_table,
> +		unsigned int esize, unsigned int n, unsigned int *available) {
> +	return __rte_ring_do_dequeue_start(r, obj_table, esize, n,
> +			RTE_RING_QUEUE_VARIABLE, available); }
> +

<snip>

> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_RING_PEEK_H_ */
> --
> 2.17.1