From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0D86BA0561; Mon, 20 Apr 2020 01:22:31 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id BA6371C23D; Mon, 20 Apr 2020 01:22:30 +0200 (CEST) Received: from EUR02-HE1-obe.outbound.protection.outlook.com (mail-eopbgr10083.outbound.protection.outlook.com [40.107.1.83]) by dpdk.org (Postfix) with ESMTP id 35CB71C23A for ; Mon, 20 Apr 2020 01:22:29 +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=3WzDVTGd6JVvWnDX44w4QC9xtlZS5L+VL9K6w6Ou0S4=; b=u0Nqz1d4FpxcUNt2Gdwb5aVUPKwpWvq4AE6UqeZXVuDADdLX+RHWqv5+0KhkZ5UDE/6EERLi7vZbEKQepLMhghI25j8aYCAZxHg6J7NYT+yIING95fmkvrHEX9ek++n2yMSna1pqBc+RhFjGX8rMqqr4W0KAuoCIIcXFbCcz9Qk= Received: from DB8PR06CA0056.eurprd06.prod.outlook.com (2603:10a6:10:120::30) by VI1PR08MB4079.eurprd08.prod.outlook.com (2603:10a6:803:e4::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2921.29; Sun, 19 Apr 2020 23:22:27 +0000 Received: from DB5EUR03FT045.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:120:cafe::1) by DB8PR06CA0056.outlook.office365.com (2603:10a6:10:120::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2921.27 via Frontend Transport; Sun, 19 Apr 2020 23:22:27 +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 DB5EUR03FT045.mail.protection.outlook.com (10.152.21.164) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2900.18 via Frontend Transport; Sun, 19 Apr 2020 23:22:27 +0000 Received: ("Tessian outbound 43fc5cd677c4:v53"); Sun, 19 Apr 2020 23:22:27 +0000 X-CR-MTA-TID: 64aa7808 Received: from 4042454cc562.2 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 219AA0E8-9191-4EE3-B4E0-1C32EA2EB561.1; Sun, 19 Apr 2020 23:22:21 +0000 Received: from EUR01-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 4042454cc562.2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Sun, 19 Apr 2020 23:22:21 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZNH1VZRUB6QQHb/719sutPXFn7Gvs5SkyfS6NtGxlkRQBe1Ne44a+QeEi0JKJaADEE+C3sDOvBHJFcudKw30cc6AE8Np4RUoQqPmvu0L0FZYy2+5taNsq0tBAc3R+vBfT67dFQOUT144FwE7d+SxtjTzFvZ4l+M4bXbIKsv59DN3K2cMlco3ZRtmuf99OtELX8LBjHMTtFPc0wrcJIyP68jsirqtUvrZ0Kq4yKdZir1FCDGRqH2+tn+QBTuTMWcMOv/Jsdx14rGbwLvAZ7NQPCW8gk6QA/egYfyxHk4EEFKiEDoeMnvF5WPfty7XmxH8uyqVHCsws71KFYcXO4xjaw== 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=3WzDVTGd6JVvWnDX44w4QC9xtlZS5L+VL9K6w6Ou0S4=; b=QMszA+CGnP4J8VKVyLrsneNVGbPNp+8Wv27/qjbHvG9fCQoR6SyX00oNTLBYIddCDSvRlyP+iO476Dlta7/KAwb6ApcfrkJqV6k8AsFAtRsBxV0h7jqIwUXgCtUC/EWBjwW8Zk11v9j0d6xi028GUFELwyYDNLqemWL+x+s6b6GbpJ74LQ333SbvYGGCcc2Dx2cUkrY8km3Y796WYN/hZcqvo+N98rx2biUxfJSI0VXSkZyIDLxr1M6dQ31PhpCtClHBYg4fSWVa+tyhThpHkR5W0cOsZoDDC7nmaNVMSdrlDYm5JruR+ztrtOQTGvMgxN8BuDVw91CxrBwEAQsFtg== 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=3WzDVTGd6JVvWnDX44w4QC9xtlZS5L+VL9K6w6Ou0S4=; b=u0Nqz1d4FpxcUNt2Gdwb5aVUPKwpWvq4AE6UqeZXVuDADdLX+RHWqv5+0KhkZ5UDE/6EERLi7vZbEKQepLMhghI25j8aYCAZxHg6J7NYT+yIING95fmkvrHEX9ek++n2yMSna1pqBc+RhFjGX8rMqqr4W0KAuoCIIcXFbCcz9Qk= Received: from DBBPR08MB4646.eurprd08.prod.outlook.com (2603:10a6:10:f5::16) by DBBPR08MB4760.eurprd08.prod.outlook.com (2603:10a6:10:f6::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2921.29; Sun, 19 Apr 2020 23:22:19 +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.2921.027; Sun, 19 Apr 2020 23:22:19 +0000 From: Honnappa Nagarahalli To: "Ananyev, Konstantin" , "stephen@networkplumber.org" , "Medvedkin, Vladimir" CC: "dev@dpdk.org" , Ruifeng Wang , Dharmik Thakkar , nd , Honnappa Nagarahalli , nd Thread-Topic: [PATCH v4 1/4] lib/rcu: add resource reclamation APIs Thread-Index: AQHWDQN3u1nOnYQWOkOS92Qwvm5NKaiBBeRA Date: Sun, 19 Apr 2020 23:22:19 +0000 Message-ID: References: <20191001062917.35578-1-honnappa.nagarahalli@arm.com> <20200403184142.7729-1-honnappa.nagarahalli@arm.com> <20200403184142.7729-2-honnappa.nagarahalli@arm.com> In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ts-tracking-id: a852d1b4-cdc1-4571-8520-fad80cec3b94.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: d9c316c1-4fd6-4db2-963b-08d7e4b88636 x-ms-traffictypediagnostic: DBBPR08MB4760:|DBBPR08MB4760:|VI1PR08MB4079: x-ms-exchange-transport-forked: True X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true nodisclaimer: true x-ms-oob-tlc-oobclassifiers: OLM:3968;OLM:3968; x-forefront-prvs: 0378F1E47A 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)(39850400004)(396003)(376002)(366004)(136003)(346002)(86362001)(316002)(110136005)(8936002)(4326008)(54906003)(478600001)(30864003)(6506007)(7696005)(186003)(71200400001)(52536014)(66476007)(66946007)(66556008)(8676002)(66446008)(64756008)(76116006)(26005)(55016002)(5660300002)(9686003)(2906002)(81156014)(33656002)(60764002)(579004); 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: ISsBmR0N3xreQuWYc3buS/OlGbl45FMxpb9kTcg80y8ZIgccnx8lSlRHSBiOOwrwnbr1gporPJ73d3cJ7Ec8ekUpJn9yZMyuzAE9nVUZ5OZfpGlElgRv3FCP1r9FlrPOtMl9jislN4IVYH5roh7WOMMLiKrSqOk3msUW1TlXON+M+RvZW1DkdIznPAD0ydKLN0L7jP2JbTMNqS3cKco6uhFfuw2yXSP1kPnU3/lMEcGajLq+xPswEQRqIb5XfriMo0CClVFcoKQULvchHLJUDuKfWM/9Pi0Gsgn9LSiIL0dCqrClbIpxHmSCvZXd3DdWAaEGs8avFyf6MBQEdVaj9zh1ZJn00+ZQgM2UsIOMpd2rryG8NrSuPHsaXgru/YQr8/STT/d0rYTkGCQcjWPRlaCgIp5xGDzSy8iN1XFpQLRjESGSHJYXKQORVwnhtjOuHYefvdJ+92H8uD8d19/r8dyHChNY4UsmhFl7he0CAw6l+qxxEeoAURPW7dZNUsbG x-ms-exchange-antispam-messagedata: e5v0VkfwGSdObcCG8zUDLbFnOlzX1r41FwwZ161afMCJjUR3OrGIBKHYFPlpsXCov1zmroK8XM0Ctyvzl4Jv0kf0P2wO8K22Aers7Vt+puJnOyzZ76egtnGgrfnHhJN81Tq/3lErkWsBwjMzvmK6EA== Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB4760 Original-Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Honnappa.Nagarahalli@arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB5EUR03FT045.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)(39850400004)(346002)(376002)(136003)(396003)(46966005)(82740400003)(54906003)(81166007)(7696005)(4326008)(26005)(316002)(110136005)(356005)(6506007)(47076004)(336012)(9686003)(186003)(86362001)(70586007)(52536014)(55016002)(30864003)(478600001)(8676002)(5660300002)(70206006)(33656002)(2906002)(8936002)(81156014)(60764002); DIR:OUT; SFP:1101; X-MS-Office365-Filtering-Correlation-Id-Prvs: 13f9541e-55b3-465a-c682-08d7e4b8817c X-Forefront-PRVS: 0378F1E47A X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: b/v1/mU6hhALkYbumpzbGX4mlSjIZ189np8b1U5zbsrt8eUQ/mMHtZ/EX1dRkTs0rcazERgtQswyiBYSt7sFHINdx3OLODYy/SPSmjEHw/9Ge0F123qyLaQZeXB/l56KaR0Q9TSQo38xfhZDPxf2qv5M3UFBwXvgY8+PHyUl7VRtD5anVGSi8fiImDE1zRWxJZ+kYH793zfyi5nMNV1WBSLq0qc9PhCHQ1Xz7SfSgcAFc5f0oUn4JnqvgpmSCM0IXhGlb5s7SgcRXSqDai70craAsRY4IOLA4koRTpDOMSDVwbhuPd6Yci0nlhymgkdylGHBSnOkcphRwWglMAO+Mlk2/YOwwGyi+Wm6vsqXCGjW8FkZsNSu7mKEZ2fqoe2hX5ZXob9nPgeYlGZ1MCMOOX/HDTX2D1NwSj5Ja1JeJ/URXmnDDjBvWcc9cAVHMXQvTPBrl8GXLG7fC3Us/MEUUBLhL6dCQGy+otZK/v4ldheWk8z76nBs8PzTIwoOqA84p+eesXo40FHN9OEIaEXoS3i9jBk5QgCk81r9Uh5RL2A= X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Apr 2020 23:22:27.2794 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d9c316c1-4fd6-4db2-963b-08d7e4b88636 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: VI1PR08MB4079 Subject: Re: [dpdk-dev] [PATCH v4 1/4] lib/rcu: add resource reclamation APIs X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" >=20 > > Add resource reclamation APIs to make it simple for applications and > > libraries to integrate rte_rcu library. >=20 > Few nits, thoughts, please see below. > Apart from that - LGTM. > Acked-by: Konstantin Ananyev >=20 > > > > Signed-off-by: Honnappa Nagarahalli > > Reviewed-by: Ola Liljedhal > > Reviewed-by: Ruifeng Wang > > --- > > lib/librte_rcu/Makefile | 2 +- > > lib/librte_rcu/meson.build | 2 + > > lib/librte_rcu/rcu_qsbr_pvt.h | 57 +++++++ > > lib/librte_rcu/rte_rcu_qsbr.c | 243 ++++++++++++++++++++++++++++- > > lib/librte_rcu/rte_rcu_qsbr.h | 188 ++++++++++++++++++++++ > > lib/librte_rcu/rte_rcu_version.map | 4 + > > lib/meson.build | 6 +- > > 7 files changed, 498 insertions(+), 4 deletions(-) create mode > > 100644 lib/librte_rcu/rcu_qsbr_pvt.h > > > > diff --git a/lib/librte_rcu/Makefile b/lib/librte_rcu/Makefile index > > c4bb28d77..95f8a57e2 100644 > > --- a/lib/librte_rcu/Makefile > > +++ b/lib/librte_rcu/Makefile > > @@ -8,7 +8,7 @@ LIB =3D librte_rcu.a > > > > CFLAGS +=3D -DALLOW_EXPERIMENTAL_API > > CFLAGS +=3D $(WERROR_FLAGS) -I$(SRCDIR) -O3 -LDLIBS +=3D -lrte_eal > > +LDLIBS +=3D -lrte_eal -lrte_ring > > > > EXPORT_MAP :=3D rte_rcu_version.map > > > > diff --git a/lib/librte_rcu/meson.build b/lib/librte_rcu/meson.build > > index 62920ba02..e280b29c1 100644 > > --- a/lib/librte_rcu/meson.build > > +++ b/lib/librte_rcu/meson.build > > @@ -10,3 +10,5 @@ headers =3D files('rte_rcu_qsbr.h') if cc.get_id() = =3D=3D > > 'clang' and dpdk_conf.get('RTE_ARCH_64') =3D=3D false > > ext_deps +=3D cc.find_library('atomic') endif > > + > > +deps +=3D ['ring'] > > diff --git a/lib/librte_rcu/rcu_qsbr_pvt.h > > b/lib/librte_rcu/rcu_qsbr_pvt.h new file mode 100644 index > > 000000000..413f28587 > > --- /dev/null > > +++ b/lib/librte_rcu/rcu_qsbr_pvt.h > > @@ -0,0 +1,57 @@ > > +/* SPDX-License-Identifier: BSD-3-Clause > > + * Copyright (c) 2019 Arm Limited > > + */ > > + > > +#ifndef _RTE_RCU_QSBR_PVT_H_ > > +#define _RTE_RCU_QSBR_PVT_H_ > > + > > +/** > > + * This file is private to the RCU library. It should not be included > > + * by the user of this library. > > + */ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +#include > > +#include > > + > > +#include "rte_rcu_qsbr.h" > > + > > +/* RTE defer queue structure. > > + * This structure holds the defer queue. The defer queue is used to > > + * hold the deleted entries from the data structure that are not > > + * yet freed. > > + */ > > +struct rte_rcu_qsbr_dq { > > + struct rte_rcu_qsbr *v; /**< RCU QSBR variable used by this queue.*/ > > + struct rte_ring *r; /**< RCU QSBR defer queue. */ > > + uint32_t size; > > + /**< Number of elements in the defer queue */ > > + uint32_t esize; > > + /**< Size (in bytes) of data, including the token, stored on the > > + * defer queue. > > + */ > > + uint32_t trigger_reclaim_limit; > > + /**< Trigger automatic reclamation after the defer queue > > + * has atleast these many resources waiting. > > + */ > > + uint32_t max_reclaim_size; > > + /**< Reclaim at the max these many resources during auto > > + * reclamation. > > + */ > > + rte_rcu_qsbr_free_resource_t free_fn; > > + /**< Function to call to free the resource. */ > > + void *p; > > + /**< Pointer passed to the free function. Typically, this is the > > + * pointer to the data structure to which the resource to free > > + * belongs. > > + */ > > +}; > > + > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif /* _RTE_RCU_QSBR_PVT_H_ */ > > diff --git a/lib/librte_rcu/rte_rcu_qsbr.c > > b/lib/librte_rcu/rte_rcu_qsbr.c index 2f3fad776..e8c1e386f 100644 > > --- a/lib/librte_rcu/rte_rcu_qsbr.c > > +++ b/lib/librte_rcu/rte_rcu_qsbr.c > > @@ -1,6 +1,6 @@ > > /* SPDX-License-Identifier: BSD-3-Clause > > * > > - * Copyright (c) 2018 Arm Limited > > + * Copyright (c) 2018-2019 Arm Limited > > */ > > > > #include > > @@ -18,8 +18,10 @@ > > #include > > #include > > #include > > +#include > > > > #include "rte_rcu_qsbr.h" > > +#include "rcu_qsbr_pvt.h" > > > > /* Get the memory size of QSBR variable */ size_t @@ -270,6 +272,245 > > @@ rte_rcu_qsbr_dump(FILE *f, struct rte_rcu_qsbr *v) > > return 0; > > } > > > > +/* Create a queue used to store the data structure elements that can > > + * be freed later. This queue is referred to as 'defer queue'. > > + */ > > +struct rte_rcu_qsbr_dq * > > +rte_rcu_qsbr_dq_create(const struct rte_rcu_qsbr_dq_parameters > > +*params) { > > + struct rte_rcu_qsbr_dq *dq; > > + uint32_t qs_fifo_size; > > + unsigned int flags; > > + > > + if (params =3D=3D NULL || params->free_fn =3D=3D NULL || > > + params->v =3D=3D NULL || params->name =3D=3D NULL || > > + params->size =3D=3D 0 || params->esize =3D=3D 0 || > > + (params->esize % 4 !=3D 0)) { > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): Invalid input parameter\n", __func__); > > + rte_errno =3D EINVAL; > > + > > + return NULL; > > + } > > + /* If auto reclamation is configured, reclaim limit > > + * should be a valid value. > > + */ > > + if ((params->trigger_reclaim_limit <=3D params->size) && > > + (params->max_reclaim_size =3D=3D 0)) { > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): Invalid input parameter, size =3D %u, > trigger_reclaim_limit =3D %u, max_reclaim_size =3D %u\n", > > + __func__, params->size, params- > >trigger_reclaim_limit, > > + params->max_reclaim_size); > > + rte_errno =3D EINVAL; > > + > > + return NULL; > > + } > > + > > + dq =3D rte_zmalloc(NULL, sizeof(struct rte_rcu_qsbr_dq), > > + RTE_CACHE_LINE_SIZE); > > + if (dq =3D=3D NULL) { > > + rte_errno =3D ENOMEM; > > + > > + return NULL; > > + } > > + > > + /* Decide the flags for the ring. > > + * If MT safety is requested, use RTS for ring enqueue as most > > + * use cases involve dq-enqueue happening on the control plane. > > + * Ring dequeue is always HTS due to the possibility of revert. > > + */ > > + flags =3D RING_F_MP_RTS_ENQ; > > + if (params->flags & RTE_RCU_QSBR_DQ_MT_UNSAFE) > > + flags =3D RING_F_SP_ENQ; > > + flags |=3D RING_F_MC_HTS_DEQ; > > + /* round up qs_fifo_size to next power of two that is not less than > > + * max_size. > > + */ > > + qs_fifo_size =3D rte_align32pow2(params->size + 1); > > + /* Add token size to ring element size */ > > + dq->r =3D rte_ring_create_elem(params->name, > > + __RTE_QSBR_TOKEN_SIZE + params->esize, > > + qs_fifo_size, SOCKET_ID_ANY, flags); > > + if (dq->r =3D=3D NULL) { > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): defer queue create failed\n", __func__); > > + rte_free(dq); > > + return NULL; > > + } > > + > > + dq->v =3D params->v; > > + dq->size =3D params->size; > > + dq->esize =3D __RTE_QSBR_TOKEN_SIZE + params->esize; > > + dq->trigger_reclaim_limit =3D params->trigger_reclaim_limit; > > + dq->max_reclaim_size =3D params->max_reclaim_size; > > + dq->free_fn =3D params->free_fn; > > + dq->p =3D params->p; > > + > > + return dq; > > +} > > + > > +/* Enqueue one resource to the defer queue to free after the grace > > + * period is over. > > + */ > > +int rte_rcu_qsbr_dq_enqueue(struct rte_rcu_qsbr_dq *dq, void *e) { > > + uint64_t token; > > + uint32_t cur_size, free_size; > > + > > + if (dq =3D=3D NULL || e =3D=3D NULL) { > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): Invalid input parameter\n", __func__); > > + rte_errno =3D EINVAL; > > + > > + return 1; > > + } > > + > > + /* Start the grace period */ > > + token =3D rte_rcu_qsbr_start(dq->v); > > + > > + /* Reclaim resources if the queue is 1/8th full. This helps >=20 > Comment about 1/8 is probably left from older version? > As I understand now it is configurable parameter. Ack, will correct this. >=20 > > + * the queue from growing too large and allows time for reader > > + * threads to report their quiescent state. > > + */ > > + cur_size =3D rte_ring_count(dq->r); > > + if (cur_size > dq->trigger_reclaim_limit) { > > + rte_log(RTE_LOG_INFO, rte_rcu_log_type, > > + "%s(): Triggering reclamation\n", __func__); > > + rte_rcu_qsbr_dq_reclaim(dq, dq->max_reclaim_size, NULL, > NULL); > > + } > > + > > + /* Check if there is space for atleast 1 resource */ > > + free_size =3D rte_ring_free_count(dq->r); > > + if (!free_size) { >=20 > Is there any point to do this check at all? > You are doing enqueue below and handle situation with not enough space in > the ring anyway. Ack >=20 > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): Defer queue is full\n", __func__); > > + /* Note that the token generated above is not used. > > + * Other than wasting tokens, it should not cause any > > + * other issues. > > + */ > > + rte_log(RTE_LOG_INFO, rte_rcu_log_type, > > + "%s(): Skipped enqueuing token =3D %"PRIu64"\n", > > + __func__, token); > > + > > + rte_errno =3D ENOSPC; > > + return 1; > > + } > > + > > + /* Enqueue the token and resource. Generating the token > > + * and enqueuing (token + resource) on the queue is not an > > + * atomic operation. This might result in tokens enqueued > > + * out of order on the queue. So, some tokens might wait > > + * longer than they are required to be reclaimed. > > + */ > > + char data[dq->esize]; > > + memcpy(data, &token, __RTE_QSBR_TOKEN_SIZE); > > + memcpy(data + __RTE_QSBR_TOKEN_SIZE, e, > > + dq->esize - __RTE_QSBR_TOKEN_SIZE); > > + /* Check the status as enqueue might fail since the other thread > > + * might have used up the freed space. > > + * Enqueue uses the configured flags when the DQ was created. > > + */ > > + if (rte_ring_enqueue_elem(dq->r, data, dq->esize) !=3D 0) { > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): Enqueue failed\n", __func__); > > + /* Note that the token generated above is not used. > > + * Other than wasting tokens, it should not cause any > > + * other issues. > > + */ > > + rte_log(RTE_LOG_INFO, rte_rcu_log_type, > > + "%s(): Skipped enqueuing token =3D %"PRIu64"\n", > > + __func__, token); > > + > > + rte_errno =3D ENOSPC; > > + return 1; > > + } >=20 >=20 > Just as a thought: in theory if we'll use MP_HTS(/SP) ring we can avoid > wasting RCU tokens: >=20 > if (rte_ring_enqueue_elem_bulk_start(dq->r, 1, NULL) !=3D 0) { > token =3D rte_rcu_qsbr_start(dq->v); > memcpy(data, &token, __RTE_QSBR_TOKEN_SIZE); > rte_ring_enqueue_elem_finish(dq->r, data, dq->esize, 1); } >=20 > Though it might slowdown things if we'll have a lot of parallel dq_enqueu= e. > So not sure is it worth it or not. Adding peek APIs for RTS would be better. That should take care of the para= llel dw_enqueue. Not sure if I gave you the comment. My ring patch supporte= d these APIs. >=20 > > + > > + rte_log(RTE_LOG_INFO, rte_rcu_log_type, > > + "%s(): Enqueued token =3D %"PRIu64"\n", __func__, token); > > + > > + return 0; > > +} > > + > > +/* Reclaim resources from the defer queue. */ int > > +rte_rcu_qsbr_dq_reclaim(struct rte_rcu_qsbr_dq *dq, unsigned int n, > > + unsigned int *freed, unsigned int *pending) { > > + uint32_t cnt; > > + uint64_t token; > > + > > + if (dq =3D=3D NULL || n =3D=3D 0) { > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): Invalid input parameter\n", __func__); > > + rte_errno =3D EINVAL; > > + > > + return 1; > > + } > > + > > + cnt =3D 0; > > + > > + char e[dq->esize]; > > + /* Check reader threads quiescent state and reclaim resources */ > > + while ((cnt < n) && > > + (rte_ring_dequeue_bulk_elem_start(dq->r, e, > > + dq->esize, 1, NULL) !=3D 0)) { >=20 > Another thought - any point to use burst_elem_start() here to retrieve mo= re > then 1 elem in one go? Something like: I think it makes sense. > char e[32][dq->size]; > while ((cnt < n) { > k =3D RTE_MAX(32, cnt - n); > k =3D rte_ring_dequeue_burst_elem_start(dq->r, e, dq->esize, k, NULL); > if (k =3D 0) > break; > for (i =3D 0; i !=3D k; i++) { > memcpy(&token, e[i], sizeof(uint64_t)); > if (rte_rcu_qsbr_check(dq->v, token, false) !=3D 1) > break; > } > k =3D i; > rte_ring_dequeue_elem_finish(dq->r, k); > for (i =3D 0; i !=3D k; i++) > dq->free_fn(dq->p, e[i] + __RTE_QSBR_TOKEN_SIZE); I think it also makes sense to change the free_fn to take 'n' number of tok= ens. > n +=3D k; > if (k =3D=3D 0) > break; >=20 > ? > Also if at enqueue we guarantee strict ordrer (via > enqueue_start/enqueue_finish), then here we probably can do _check_ from > the last retrieved token here? > In theory that might help to minimize number of checks. > I.E. do: > for (i =3D k; i-- !=3D0; ) { > memcpy(&token, e[i], sizeof(uint64_t)); > if (rte_rcu_qsbr_check(dq->v, token, false) !=3D 1) There is a higher chance that later tokens are not acked. This introduces m= ore polling of the counters. The rte_rcu_qsbr_check has an optimization. While acking the current token,= it will also caches the greatest token acked. It uses the cached token for= the subsequent calls. I think this provides a better optimization. > break; > } > k =3D i + 1; > ... >=20 > > + memcpy(&token, e, sizeof(uint64_t)); > > + > > + /* Reclaim the resource */ > > + if (rte_rcu_qsbr_check(dq->v, token, false) !=3D 1) { > > + rte_ring_dequeue_finish(dq->r, 0); > > + break; > > + } > > + rte_ring_dequeue_finish(dq->r, 1); > > + > > + rte_log(RTE_LOG_INFO, rte_rcu_log_type, > > + "%s(): Reclaimed token =3D %"PRIu64"\n", > > + __func__, *(uint64_t *)e); > > + > > + dq->free_fn(dq->p, e + __RTE_QSBR_TOKEN_SIZE); > > + > > + cnt++; > > + } > > + > > + rte_log(RTE_LOG_INFO, rte_rcu_log_type, > > + "%s(): Reclaimed %u resources\n", __func__, cnt); > > + > > + if (freed !=3D NULL) > > + *freed =3D cnt; > > + if (pending !=3D NULL) > > + *pending =3D rte_ring_count(dq->r); > > + > > + return 0; > > +} > > + > > +/* Delete a defer queue. */ > > +int > > +rte_rcu_qsbr_dq_delete(struct rte_rcu_qsbr_dq *dq) { > > + unsigned int pending; > > + > > + if (dq =3D=3D NULL) { > > + rte_log(RTE_LOG_ERR, rte_rcu_log_type, > > + "%s(): Invalid input parameter\n", __func__); > > + rte_errno =3D EINVAL; > > + > > + return 1; > > + } > > + > > + /* Reclaim all the resources */ > > + rte_rcu_qsbr_dq_reclaim(dq, ~0, NULL, &pending); > > + if (pending !=3D 0) { > > + rte_errno =3D EAGAIN; > > + > > + return 1; > > + } > > + > > + rte_ring_free(dq->r); > > + rte_free(dq); > > + > > + return 0; > > +} > > + > > int rte_rcu_log_type; > > > > RTE_INIT(rte_rcu_register) > > diff --git a/lib/librte_rcu/rte_rcu_qsbr.h > > b/lib/librte_rcu/rte_rcu_qsbr.h index 0b5585925..213f9b029 100644 > > --- a/lib/librte_rcu/rte_rcu_qsbr.h > > +++ b/lib/librte_rcu/rte_rcu_qsbr.h > > @@ -34,6 +34,7 @@ extern "C" { > > #include > > #include > > #include > > +#include > > > > extern int rte_rcu_log_type; > > > > @@ -84,6 +85,7 @@ struct rte_rcu_qsbr_cnt { #define > > __RTE_QSBR_CNT_THR_OFFLINE 0 #define __RTE_QSBR_CNT_INIT 1 > #define > > __RTE_QSBR_CNT_MAX ((uint64_t)~0) > > +#define __RTE_QSBR_TOKEN_SIZE sizeof(uint64_t) > > > > /* RTE Quiescent State variable structure. > > * This structure has two elements that vary in size based on the @@ > > -114,6 +116,84 @@ struct rte_rcu_qsbr { > > */ > > } __rte_cache_aligned; > > > > +/** > > + * Call back function called to free the resources. > > + * > > + * @param p > > + * Pointer provided while creating the defer queue > > + * @param e > > + * Pointer to the resource data stored on the defer queue > > + * > > + * @return > > + * None > > + */ > > +typedef void (*rte_rcu_qsbr_free_resource_t)(void *p, void *e); > > + > > +#define RTE_RCU_QSBR_DQ_NAMESIZE RTE_RING_NAMESIZE > > + > > +/** > > + * Various flags supported. > > + */ > > +/**< Enqueue and reclaim operations are multi-thread safe by default. > > + * The call back functions registered to free the resources are > > + * assumed to be multi-thread safe. > > + * Set this flag is multi-thread safety is not required. > > + */ > > +#define RTE_RCU_QSBR_DQ_MT_UNSAFE 1 > > + > > +/** > > + * Parameters used when creating the defer queue. > > + */ > > +struct rte_rcu_qsbr_dq_parameters { > > + const char *name; > > + /**< Name of the queue. */ > > + uint32_t flags; > > + /**< Flags to control API behaviors */ > > + uint32_t size; > > + /**< Number of entries in queue. Typically, this will be > > + * the same as the maximum number of entries supported in the > > + * lock free data structure. > > + * Data structures with unbounded number of entries is not > > + * supported currently. > > + */ > > + uint32_t esize; > > + /**< Size (in bytes) of each element in the defer queue. > > + * This has to be multiple of 4B. > > + */ > > + uint32_t trigger_reclaim_limit; > > + /**< Trigger automatic reclamation after the defer queue > > + * has atleast these many resources waiting. This auto > > + * reclamation is triggered in rte_rcu_qsbr_dq_enqueue API > > + * call. > > + * If this is greater than 'size', auto reclamation is > > + * not triggered. > > + * If this is set to 0, auto reclamation is triggered > > + * in every call to rte_rcu_qsbr_dq_enqueue API. > > + */ > > + uint32_t max_reclaim_size; > > + /**< When automatic reclamation is enabled, reclaim at the max > > + * these many resources. This should contain a valid value, if > > + * auto reclamation is on. Setting this to 'size' or greater will > > + * reclaim all possible resources currently on the defer queue. > > + */ > > + rte_rcu_qsbr_free_resource_t free_fn; > > + /**< Function to call to free the resource. */ > > + void *p; > > + /**< Pointer passed to the free function. Typically, this is the > > + * pointer to the data structure to which the resource to free > > + * belongs. This can be NULL. > > + */ > > + struct rte_rcu_qsbr *v; > > + /**< RCU QSBR variable to use for this defer queue */ }; > > + > > +/* RTE defer queue structure. > > + * This structure holds the defer queue. The defer queue is used to > > + * hold the deleted entries from the data structure that are not > > + * yet freed. > > + */ > > +struct rte_rcu_qsbr_dq; > > + > > /** > > * @warning > > * @b EXPERIMENTAL: this API may change without prior notice @@ > > -692,6 +772,114 @@ __rte_experimental int rte_rcu_qsbr_dump(FILE *f, > > struct rte_rcu_qsbr *v); > > > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice > > + * > > + * Create a queue used to store the data structure elements that can > > + * be freed later. This queue is referred to as 'defer queue'. > > + * > > + * @param params > > + * Parameters to create a defer queue. > > + * @return > > + * On success - Valid pointer to defer queue > > + * On error - NULL > > + * Possible rte_errno codes are: > > + * - EINVAL - NULL parameters are passed > > + * - ENOMEM - Not enough memory > > + */ > > +__rte_experimental > > +struct rte_rcu_qsbr_dq * > > +rte_rcu_qsbr_dq_create(const struct rte_rcu_qsbr_dq_parameters > > +*params); > > + > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice > > + * > > + * Enqueue one resource to the defer queue and start the grace period. > > + * The resource will be freed later after at least one grace period > > + * is over. > > + * > > + * If the defer queue is full, it will attempt to reclaim resources. > > + * It will also reclaim resources at regular intervals to avoid > > + * the defer queue from growing too big. > > + * > > + * Multi-thread safety is provided as the defer queue configuration. > > + * When multi-thread safety is requested, it is possible that the > > + * resources are not stored in their order of deletion. This results > > + * in resources being held in the defer queue longer than they should. > > + * > > + * @param dq > > + * Defer queue to allocate an entry from. > > + * @param e > > + * Pointer to resource data to copy to the defer queue. The size of > > + * the data to copy is equal to the element size provided when the > > + * defer queue was created. > > + * @return > > + * On success - 0 > > + * On error - 1 with rte_errno set to > > + * - EINVAL - NULL parameters are passed > > + * - ENOSPC - Defer queue is full. This condition can not happen > > + * if the defer queue size is equal (or larger) than the > > + * number of elements in the data structure. > > + */ > > +__rte_experimental > > +int > > +rte_rcu_qsbr_dq_enqueue(struct rte_rcu_qsbr_dq *dq, void *e); > > + > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice > > + * > > + * Free quesed resources from the defer queue. > > + * > > + * This API is multi-thread safe. > > + * > > + * @param dq > > + * Defer queue to free an entry from. > > + * @param n > > + * Maximum number of resources to free. > > + * @param freed > > + * Number of resources that were freed. > > + * @param pending > > + * Number of resources pending on the defer queue. This number might > not > > + * be acurate if multi-thread safety is configured. > > + * @return > > + * On successful reclamation of at least 1 resource - 0 > > + * On error - 1 with rte_errno set to > > + * - EINVAL - NULL parameters are passed > > + */ > > +__rte_experimental > > +int > > +rte_rcu_qsbr_dq_reclaim(struct rte_rcu_qsbr_dq *dq, unsigned int n, > > + unsigned int *freed, unsigned int *pending); > > + > > +/** > > + * @warning > > + * @b EXPERIMENTAL: this API may change without prior notice > > + * > > + * Delete a defer queue. > > + * > > + * It tries to reclaim all the resources on the defer queue. > > + * If any of the resources have not completed the grace period > > + * the reclamation stops and returns immediately. The rest of > > + * the resources are not reclaimed and the defer queue is not > > + * freed. > > + * > > + * @param dq > > + * Defer queue to delete. > > + * @return > > + * On success - 0 > > + * On error - 1 > > + * Possible rte_errno codes are: > > + * - EINVAL - NULL parameters are passed > > + * - EAGAIN - Some of the resources have not completed at least 1 gr= ace > > + * period, try again. > > + */ > > +__rte_experimental > > +int > > +rte_rcu_qsbr_dq_delete(struct rte_rcu_qsbr_dq *dq); > > + > > #ifdef __cplusplus > > } > > #endif > > diff --git a/lib/librte_rcu/rte_rcu_version.map > > b/lib/librte_rcu/rte_rcu_version.map > > index f8b9ef2ab..dfac88a37 100644 > > --- a/lib/librte_rcu/rte_rcu_version.map > > +++ b/lib/librte_rcu/rte_rcu_version.map > > @@ -8,6 +8,10 @@ EXPERIMENTAL { > > rte_rcu_qsbr_synchronize; > > rte_rcu_qsbr_thread_register; > > rte_rcu_qsbr_thread_unregister; > > + rte_rcu_qsbr_dq_create; > > + rte_rcu_qsbr_dq_enqueue; > > + rte_rcu_qsbr_dq_reclaim; > > + rte_rcu_qsbr_dq_delete; > > > > local: *; > > }; > > diff --git a/lib/meson.build b/lib/meson.build index > > 9c3cc55d5..15e91a303 100644 > > --- a/lib/meson.build > > +++ b/lib/meson.build > > @@ -11,7 +11,9 @@ > > libraries =3D [ > > 'kvargs', # eal depends on kvargs > > 'eal', # everything depends on eal > > - 'ring', 'mempool', 'mbuf', 'net', 'meter', 'ethdev', 'pci', # core > > + 'ring', > > + 'rcu', # rcu depends on ring > > + 'mempool', 'mbuf', 'net', 'meter', 'ethdev', 'pci', # core > > 'cmdline', > > 'metrics', # bitrate/latency stats depends on this > > 'hash', # efd depends on this > > @@ -22,7 +24,7 @@ libraries =3D [ > > 'gro', 'gso', 'ip_frag', 'jobstats', > > 'kni', 'latencystats', 'lpm', 'member', > > 'power', 'pdump', 'rawdev', > > - 'rcu', 'rib', 'reorder', 'sched', 'security', 'stack', 'vhost', > > + 'rib', 'reorder', 'sched', 'security', 'stack', 'vhost', > > # ipsec lib depends on net, crypto and security > > 'ipsec', > > #fib lib depends on rib > > -- > > 2.17.1