[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 1/3] xen/rcu: introduce the concept of RCU epoch


  • To: "Roger Pau Monne" <roger@xxxxxxxxxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: "Alejandro Vallejo" <alejandro.garciavallejo@xxxxxxx>
  • Date: Mon, 28 Sep 2026 10:24:04 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=vjQ0Vrtx1aUThP+u5oKsd6/eLRAVOGOmhBETxvmkcd0=; b=tSx42iIDuqIpzQmVKwcXadsbpdSsnaTRc7b5EtnkxMeV3uiPC+mriQPEBSkiAMGVdARVM5C/zI/X//CO6D6BjAbzdgV1aMsfBqLXLjyqV+F8tssGLj5MdEIlF4f2Iugr9/ATT1a/9jAFWSHa4yQmGHik18pBE8ZaPAqRS1yinam3guIeeG+wm0g3bzPhi8ybZc6dxbUZ8hd2QeyS1M+x4i7mXLugsqZjxYUmB4bhsPQe1Jiq8UGQ1TiZoRdDNV7eWVvubEyK6+qPDxlsb7k3cjsEqv/bfq37u882h+XbXyE3XqiMJqgXr3Jvs3VGC7PGXjT9xyyUfZrnbOQdpJekVw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=jDu41Gl4cxglpPVVlUDZV40/9e1G7W9iSGrarcH29wWQnLhgeMbUMOnlTI+31w5sgfAZpe9mL+VgX3HsmwJjYNtpfXHxIVBxTFcQbjVUyaU1wBrT4CVm4o3Lh3Fl/DmZ1K4YjBdC13NozlLvnhgFModWHLOpBBuPiVllfNaLCl6Bpz85N3Hu6GxB2kToydHvMBgjNHLyHxJEsN3tFIk+1OnCpQeOSwHm4ZoDZ45j177uEskV8lfs5+To2ScNBJTWxmvrmqJolcOd7PiUOijE5oqIu0BNcgXO2dlewP85K2MwQDyrq17ifGJgXoVQcg4YJNVALOGt+4cRjuLufwKQzg==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=amd.com header.i="@amd.com" header.h="From:Date:Subject:Message-Id:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: mx.microsoft.com 1; dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=amd.com;
  • Cc: "Andrew Cooper" <andrew.cooper3@xxxxxxxxxx>, "Anthony PERARD" <anthony.perard@xxxxxxxxxx>, "Michal Orzel" <michal.orzel@xxxxxxx>, "Jan Beulich" <jbeulich@xxxxxxxx>, "Julien Grall" <julien@xxxxxxx>, "Stefano Stabellini" <sstabellini@xxxxxxxxxx>
  • Delivery-date: Mon, 28 Sep 2026 08:24:22 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Fri Sep 25, 2026 at 6:30 PM CEST, Roger Pau Monne wrote:
> An RCU epoch signals the lifetime of RCU references.  Each CPU records the
> epoch in force when it enters an RCU critical section.  When a callback is
> queued the current epoch is stored in the callback and the global epoch is
> then bumped, as a way to know when all CPUs have moved past a specific
> epoch.  At that point there can be no remaining references to objects
> fetched during the callback's epoch.
>
> The compiler barrier is switched to a full memory barrier, as future uses
> of rcu_lock_cnt must ensure the count is increased before taking a
> reference to any RCU protected object.
>
> Access rcu_lock_cnt, rcu_lock_epoch and rcu_epoch through ACCESS_ONCE()
> to stop the compiler shattering the loads and stores.  The reordering
> prevention aspect of ACCESS_ONCE() is not what we rely on here (the memory
> barriers cover that); what matters is that these variables now have remote
> consumers, so each access must be a single, non-torn memory operation.
>
> Signed-off-by: Roger Pau Monné <roger@xxxxxxxxxxxxxx>
> ---
> Can possibly be folded into the next patch, as it's lacking context on its
> own to understand the need to introduce the logic.
> ---
> Changes since v1:
>  - Do the setting of head->added in the interrupt disabled section.
>  - Unconditionally do a memory barrier when enter/exit RCU critical
>    regions.  Attempting to do selectively is too complex.
> ---
>  xen/common/rcupdate.c      |  6 ++++++
>  xen/include/xen/rcupdate.h | 17 +++++++++++++----
>  2 files changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/xen/common/rcupdate.c b/xen/common/rcupdate.c
> index c1b6b2ae768b..babaabbbeefe 100644
> --- a/xen/common/rcupdate.c
> +++ b/xen/common/rcupdate.c
> @@ -49,6 +49,11 @@
>  #include <asm/atomic.h>
>  
>  DEFINE_PER_CPU(unsigned int, rcu_lock_cnt);
> +/* Store epoch when CPU entered the RCU critical section. */
> +DEFINE_PER_CPU(unsigned int, rcu_lock_epoch);
> +
> +/* Current RCU epoch, bumped every time a new callback is queued. */
> +unsigned int rcu_epoch;

nit: I'd suggest calling this rcu_cur_epoch, and then renaming "added"
below to plain "epoch". "added" doesn't convey what the field is at all.

>  
>  /* Global control variables for rcupdate callback mechanism. */
>  static struct rcu_ctrlblk {
> @@ -283,6 +288,7 @@ void call_rcu(struct rcu_head *head,
>      head->func = func;
>      head->next = NULL;
>      local_irq_save(flags);
> +    head->added = arch_fetch_and_add(&rcu_epoch, 1);
>      rdp = &this_cpu(rcu_data);
>      *rdp->nxttail = head;
>      rdp->nxttail = &head->next;
> diff --git a/xen/include/xen/rcupdate.h b/xen/include/xen/rcupdate.h
> index c57f628107cf..5846e8c169d7 100644
> --- a/xen/include/xen/rcupdate.h
> +++ b/xen/include/xen/rcupdate.h
> @@ -34,24 +34,32 @@
>  #include <xen/compiler.h>
>  #include <xen/spinlock.h>
>  #include <xen/cpumask.h>
> +#include <xen/lib.h>
>  #include <xen/percpu.h>
>  #include <xen/preempt.h>
>  
>  #define __rcu
>  
>  DECLARE_PER_CPU(unsigned int, rcu_lock_cnt);
> +DECLARE_PER_CPU(unsigned int, rcu_lock_epoch);
> +
> +extern unsigned int rcu_epoch;
>  
>  static inline void rcu_quiesce_disable(void)
>  {
> +    unsigned int cpu = smp_processor_id();
> +
>      preempt_disable();
> -    this_cpu(rcu_lock_cnt)++;
> -    barrier();
> +    if ( !ACCESS_ONCE(per_cpu(rcu_lock_cnt, cpu))++ )
> +        ACCESS_ONCE(per_cpu(rcu_lock_epoch, cpu)) = ACCESS_ONCE(rcu_epoch);

I'm not terribly convinced about using ACCESS_ONCE() for atomic
accesses. In particular...

> +    smp_mb();
>  }
>  
>  static inline void rcu_quiesce_enable(void)
>  {
> -    barrier();
> -    this_cpu(rcu_lock_cnt)--;
> +
> +    smp_mb();
> +    ACCESS_ONCE(this_cpu(rcu_lock_cnt))--;

... this variable is to be read by remote CPUs and autodecrement seems
like the wrong tool for an atomic decrement.

>      preempt_enable();
>  }
>  
> @@ -68,6 +76,7 @@ static inline bool rcu_quiesce_allowed(void)
>  struct rcu_head {
>      struct rcu_head *next;
>      void (*func)(struct rcu_head *head);
> +    unsigned int added;
>  };
>  
>  #define RCU_HEAD_INIT   { .next = NULL, .func = NULL }

Cheers,
Alejandro



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.