[RFC,19/19] riscv: Add __riscv_cpu_relax() to allow yielding in busy loops

Message ID 20230207001618.458947-20-christoph.muellner@vrull.eu
State New
Headers
Series riscv: ifunc support with optimized mem*/str*/cpu_relax routines |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Christoph Müllner Feb. 7, 2023, 12:16 a.m. UTC
  From: Christoph Müllner <christoph.muellner@vrull.eu>

The spinning loop of PTHREAD_MUTEX_ADAPTIVE_NP provides the hook
atomic_spin_nop() that can be used by architectures.

On RISC-V we have two instructions that can be used here:
* WRS.STO from the Zawrs extension
* PAUSE from the Zihintpause extension

Let's use these instructions and prefer WRS.STO over PAUSE
(based on availability of the corresponding ISA extension
at runtime).

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 sysdeps/riscv/multiarch/Makefile              |  5 +++
 sysdeps/riscv/multiarch/cpu_relax.c           | 36 +++++++++++++++++
 sysdeps/riscv/multiarch/cpu_relax_impl.S      | 40 +++++++++++++++++++
 .../unix/sysv/linux/riscv/atomic-machine.h    |  3 ++
 4 files changed, 84 insertions(+)
 create mode 100644 sysdeps/riscv/multiarch/cpu_relax.c
 create mode 100644 sysdeps/riscv/multiarch/cpu_relax_impl.S
  

Comments

Andrew Waterman Feb. 7, 2023, 12:23 a.m. UTC | #1
Note that all implementations must support `pause`, since it's a HINT
instruction encoded within a base-ISA instruction that has no
architecturally visible effect.  So it's not clear to me that there's
any virtue in distinguishing implementations that claim to support
Zihintpause from those that don't.


On Mon, Feb 6, 2023 at 4:17 PM Christoph Muellner
<christoph.muellner@vrull.eu> wrote:
>
> From: Christoph Müllner <christoph.muellner@vrull.eu>
>
> The spinning loop of PTHREAD_MUTEX_ADAPTIVE_NP provides the hook
> atomic_spin_nop() that can be used by architectures.
>
> On RISC-V we have two instructions that can be used here:
> * WRS.STO from the Zawrs extension
> * PAUSE from the Zihintpause extension
>
> Let's use these instructions and prefer WRS.STO over PAUSE
> (based on availability of the corresponding ISA extension
> at runtime).
>
> Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
> ---
>  sysdeps/riscv/multiarch/Makefile              |  5 +++
>  sysdeps/riscv/multiarch/cpu_relax.c           | 36 +++++++++++++++++
>  sysdeps/riscv/multiarch/cpu_relax_impl.S      | 40 +++++++++++++++++++
>  .../unix/sysv/linux/riscv/atomic-machine.h    |  3 ++
>  4 files changed, 84 insertions(+)
>  create mode 100644 sysdeps/riscv/multiarch/cpu_relax.c
>  create mode 100644 sysdeps/riscv/multiarch/cpu_relax_impl.S
>
> diff --git a/sysdeps/riscv/multiarch/Makefile b/sysdeps/riscv/multiarch/Makefile
> index 9f22e31b99..b5b9fcf986 100644
> --- a/sysdeps/riscv/multiarch/Makefile
> +++ b/sysdeps/riscv/multiarch/Makefile
> @@ -17,3 +17,8 @@ sysdep_routines += \
>         strncmp_generic \
>         strncmp_zbb
>  endif
> +
> +# nscd uses atomic_spin_nop which in turn requires cpu_relax
> +ifeq ($(subdir),nscd)
> +routines += cpu_relax cpu_relax_impl
> +endif
> diff --git a/sysdeps/riscv/multiarch/cpu_relax.c b/sysdeps/riscv/multiarch/cpu_relax.c
> new file mode 100644
> index 0000000000..4e6825ca50
> --- /dev/null
> +++ b/sysdeps/riscv/multiarch/cpu_relax.c
> @@ -0,0 +1,36 @@
> +/* CPU strand yielding for busy loops.  RISC-V version.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <ldsodefs.h>
> +#include <init-arch.h>
> +
> +void __cpu_relax (void);
> +extern void __cpu_relax_zawrs (void);
> +extern void __cpu_relax_zihintpause (void);
> +
> +static void
> +__cpu_relax_generic (void)
> +{
> +}
> +
> +libc_ifunc (__cpu_relax,
> +           HAVE_RV(zawrs)
> +           ? __cpu_relax_zawrs
> +           : HAVE_RV(zihintpause)
> +             ? __cpu_relax_zihintpause
> +             : __cpu_relax_generic);
> diff --git a/sysdeps/riscv/multiarch/cpu_relax_impl.S b/sysdeps/riscv/multiarch/cpu_relax_impl.S
> new file mode 100644
> index 0000000000..5d349c351f
> --- /dev/null
> +++ b/sysdeps/riscv/multiarch/cpu_relax_impl.S
> @@ -0,0 +1,40 @@
> +/* Copyright (C) 2022 Free Software Foundation, Inc.
> +
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdep.h>
> +#include <sys/asm.h>
> +
> +.option push
> +.option arch,+zawrs
> +
> +ENTRY_ALIGN (__cpu_relax_zawrs, 4)
> +       wrs.sto
> +       ret
> +END (__cpu_relax_zawrs)
> +
> +.option pop
> +
> +.option push
> +.option arch,+zihintpause
> +
> +ENTRY_ALIGN (__cpu_relax_zihintpause, 4)
> +       pause
> +       ret
> +END (__cpu_relax_zihintpause)
> +
> +.option pop
> diff --git a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> index dbf70d8d57..88aa58ef95 100644
> --- a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> +++ b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> @@ -178,4 +178,7 @@
>  # error "ISAs that do not subsume the A extension are not supported"
>  #endif /* !__riscv_atomic */
>
> +extern void __cpu_relax (void);
> +#define atomic_spin_nop() __cpu_relax()
> +
>  #endif /* bits/atomic.h */
> --
> 2.39.1
>
  
Christoph Müllner Feb. 7, 2023, 12:29 a.m. UTC | #2
On Tue, Feb 7, 2023 at 1:23 AM Andrew Waterman <andrew@sifive.com> wrote:

> Note that all implementations must support `pause`, since it's a HINT
> instruction encoded within a base-ISA instruction that has no
> architecturally visible effect.  So it's not clear to me that there's
> any virtue in distinguishing implementations that claim to support
> Zihintpause from those that don't.
>

Will be considered in a v2.
Thanks!


>
>
> On Mon, Feb 6, 2023 at 4:17 PM Christoph Muellner
> <christoph.muellner@vrull.eu> wrote:
> >
> > From: Christoph Müllner <christoph.muellner@vrull.eu>
> >
> > The spinning loop of PTHREAD_MUTEX_ADAPTIVE_NP provides the hook
> > atomic_spin_nop() that can be used by architectures.
> >
> > On RISC-V we have two instructions that can be used here:
> > * WRS.STO from the Zawrs extension
> > * PAUSE from the Zihintpause extension
> >
> > Let's use these instructions and prefer WRS.STO over PAUSE
> > (based on availability of the corresponding ISA extension
> > at runtime).
> >
> > Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
> > ---
> >  sysdeps/riscv/multiarch/Makefile              |  5 +++
> >  sysdeps/riscv/multiarch/cpu_relax.c           | 36 +++++++++++++++++
> >  sysdeps/riscv/multiarch/cpu_relax_impl.S      | 40 +++++++++++++++++++
> >  .../unix/sysv/linux/riscv/atomic-machine.h    |  3 ++
> >  4 files changed, 84 insertions(+)
> >  create mode 100644 sysdeps/riscv/multiarch/cpu_relax.c
> >  create mode 100644 sysdeps/riscv/multiarch/cpu_relax_impl.S
> >
> > diff --git a/sysdeps/riscv/multiarch/Makefile
> b/sysdeps/riscv/multiarch/Makefile
> > index 9f22e31b99..b5b9fcf986 100644
> > --- a/sysdeps/riscv/multiarch/Makefile
> > +++ b/sysdeps/riscv/multiarch/Makefile
> > @@ -17,3 +17,8 @@ sysdep_routines += \
> >         strncmp_generic \
> >         strncmp_zbb
> >  endif
> > +
> > +# nscd uses atomic_spin_nop which in turn requires cpu_relax
> > +ifeq ($(subdir),nscd)
> > +routines += cpu_relax cpu_relax_impl
> > +endif
> > diff --git a/sysdeps/riscv/multiarch/cpu_relax.c
> b/sysdeps/riscv/multiarch/cpu_relax.c
> > new file mode 100644
> > index 0000000000..4e6825ca50
> > --- /dev/null
> > +++ b/sysdeps/riscv/multiarch/cpu_relax.c
> > @@ -0,0 +1,36 @@
> > +/* CPU strand yielding for busy loops.  RISC-V version.
> > +   Copyright (C) 2022 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <ldsodefs.h>
> > +#include <init-arch.h>
> > +
> > +void __cpu_relax (void);
> > +extern void __cpu_relax_zawrs (void);
> > +extern void __cpu_relax_zihintpause (void);
> > +
> > +static void
> > +__cpu_relax_generic (void)
> > +{
> > +}
> > +
> > +libc_ifunc (__cpu_relax,
> > +           HAVE_RV(zawrs)
> > +           ? __cpu_relax_zawrs
> > +           : HAVE_RV(zihintpause)
> > +             ? __cpu_relax_zihintpause
> > +             : __cpu_relax_generic);
> > diff --git a/sysdeps/riscv/multiarch/cpu_relax_impl.S
> b/sysdeps/riscv/multiarch/cpu_relax_impl.S
> > new file mode 100644
> > index 0000000000..5d349c351f
> > --- /dev/null
> > +++ b/sysdeps/riscv/multiarch/cpu_relax_impl.S
> > @@ -0,0 +1,40 @@
> > +/* Copyright (C) 2022 Free Software Foundation, Inc.
> > +
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library.  If not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <sysdep.h>
> > +#include <sys/asm.h>
> > +
> > +.option push
> > +.option arch,+zawrs
> > +
> > +ENTRY_ALIGN (__cpu_relax_zawrs, 4)
> > +       wrs.sto
> > +       ret
> > +END (__cpu_relax_zawrs)
> > +
> > +.option pop
> > +
> > +.option push
> > +.option arch,+zihintpause
> > +
> > +ENTRY_ALIGN (__cpu_relax_zihintpause, 4)
> > +       pause
> > +       ret
> > +END (__cpu_relax_zihintpause)
> > +
> > +.option pop
> > diff --git a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> > index dbf70d8d57..88aa58ef95 100644
> > --- a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> > +++ b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
> > @@ -178,4 +178,7 @@
> >  # error "ISAs that do not subsume the A extension are not supported"
> >  #endif /* !__riscv_atomic */
> >
> > +extern void __cpu_relax (void);
> > +#define atomic_spin_nop() __cpu_relax()
> > +
> >  #endif /* bits/atomic.h */
> > --
> > 2.39.1
> >
>
  

Patch

diff --git a/sysdeps/riscv/multiarch/Makefile b/sysdeps/riscv/multiarch/Makefile
index 9f22e31b99..b5b9fcf986 100644
--- a/sysdeps/riscv/multiarch/Makefile
+++ b/sysdeps/riscv/multiarch/Makefile
@@ -17,3 +17,8 @@  sysdep_routines += \
 	strncmp_generic \
 	strncmp_zbb
 endif
+
+# nscd uses atomic_spin_nop which in turn requires cpu_relax
+ifeq ($(subdir),nscd)
+routines += cpu_relax cpu_relax_impl
+endif
diff --git a/sysdeps/riscv/multiarch/cpu_relax.c b/sysdeps/riscv/multiarch/cpu_relax.c
new file mode 100644
index 0000000000..4e6825ca50
--- /dev/null
+++ b/sysdeps/riscv/multiarch/cpu_relax.c
@@ -0,0 +1,36 @@ 
+/* CPU strand yielding for busy loops.  RISC-V version.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+#include <init-arch.h>
+
+void __cpu_relax (void);
+extern void __cpu_relax_zawrs (void);
+extern void __cpu_relax_zihintpause (void);
+
+static void
+__cpu_relax_generic (void)
+{
+}
+
+libc_ifunc (__cpu_relax,
+	    HAVE_RV(zawrs)
+	    ? __cpu_relax_zawrs
+	    : HAVE_RV(zihintpause)
+	      ? __cpu_relax_zihintpause
+	      : __cpu_relax_generic);
diff --git a/sysdeps/riscv/multiarch/cpu_relax_impl.S b/sysdeps/riscv/multiarch/cpu_relax_impl.S
new file mode 100644
index 0000000000..5d349c351f
--- /dev/null
+++ b/sysdeps/riscv/multiarch/cpu_relax_impl.S
@@ -0,0 +1,40 @@ 
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+.option push
+.option arch,+zawrs
+
+ENTRY_ALIGN (__cpu_relax_zawrs, 4)
+	wrs.sto
+	ret
+END (__cpu_relax_zawrs)
+
+.option pop
+
+.option push
+.option arch,+zihintpause
+
+ENTRY_ALIGN (__cpu_relax_zihintpause, 4)
+	pause
+	ret
+END (__cpu_relax_zihintpause)
+
+.option pop
diff --git a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
index dbf70d8d57..88aa58ef95 100644
--- a/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
+++ b/sysdeps/unix/sysv/linux/riscv/atomic-machine.h
@@ -178,4 +178,7 @@ 
 # error "ISAs that do not subsume the A extension are not supported"
 #endif /* !__riscv_atomic */
 
+extern void __cpu_relax (void);
+#define atomic_spin_nop() __cpu_relax()
+
 #endif /* bits/atomic.h */