Re: [PATCH v5 16/18] riscv: Add RVV strncpy for multiarch and non-multiarch

Peter Bergner <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
On 2/3/26 9:05 AM, Yao Zihong wrote:
> Signed-off-by: Yao Zihong <[email protected]>
> ---
>  sysdeps/riscv/multiarch/strncpy-generic.c     | 26 +++++++++
>  sysdeps/riscv/multiarch/strncpy-vector.S      | 24 ++++++++
>  sysdeps/riscv/rvv/stpncpy.S                   | 27 +++++++--
>  sysdeps/riscv/rvv/strncpy.S                   | 20 +++++++
>  .../unix/sysv/linux/riscv/multiarch/Makefile  |  3 +
>  .../linux/riscv/multiarch/ifunc-impl-list.c   |  5 ++
>  .../unix/sysv/linux/riscv/multiarch/stpncpy.c | 15 ++---
>  .../unix/sysv/linux/riscv/multiarch/strncpy.c | 56 +++++++++++++++++++
>  8 files changed, 164 insertions(+), 12 deletions(-)
>  create mode 100644 sysdeps/riscv/multiarch/strncpy-generic.c
>  create mode 100644 sysdeps/riscv/multiarch/strncpy-vector.S
>  create mode 100644 sysdeps/riscv/rvv/strncpy.S
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c

LGTM, modulo I modified the multiarch/stpncpy.c to again use the special
macros from ifunc-init.h to simplify the implementation a little more,
similar to the stpncpy.c change I replied to earlier.
The updated patch passed make check-abi and a normal make check.
Given the freeze, I plan on pushing this commit tomorrow unless there
are any objections due to issues they see.

Reviewed-by: Peter Bergner <[email protected]>


I've attached the full updated patch below for awareness.


Peter



riscv: Add RVV strncpy for both multiarch and non-multiarch builds

This patch adds an RVV-optimized implementation of strncpy for RISC-V and
enables it for both multiarch (IFUNC) and non-multiarch builds.

The implementation integrates Hau Hsu's 2023 RVV work under a unified
ifunc-based framework. A vectorized version (__strncpy_vector) is added
alongside the generic fallback (__strncpy_generic). The runtime resolver
selects the RVV variant when RISCV_HWPROBE_KEY_IMA_EXT_0 reports vector
support (RVV).

Currently, the resolver still selects the RVV variant even when the RVV
extension is disabled via prctl(). As a consequence, any process that
has RVV disabled via prctl() will receive SIGILL when calling strncpy().

Co-authored-by: Hau Hsu <[email protected]>
Co-authored-by: Jerry Shih <[email protected]>
Signed-off-by: Yao Zihong <[email protected]>
Reviewed-by: Peter Bergner <[email protected]>
---
 sysdeps/riscv/multiarch/strncpy-generic.c     | 26 ++++++++
 sysdeps/riscv/multiarch/strncpy-vector.S      | 24 ++++++++
 sysdeps/riscv/rvv/stpncpy.S                   | 27 +++++++--
 sysdeps/riscv/rvv/strncpy.S                   | 20 +++++++
 .../unix/sysv/linux/riscv/multiarch/Makefile  |  3 +
 .../linux/riscv/multiarch/ifunc-impl-list.c   |  5 ++
 .../unix/sysv/linux/riscv/multiarch/strncpy.c | 59 +++++++++++++++++++
 7 files changed, 159 insertions(+), 5 deletions(-)
 create mode 100644 sysdeps/riscv/multiarch/strncpy-generic.c
 create mode 100644 sysdeps/riscv/multiarch/strncpy-vector.S
 create mode 100644 sysdeps/riscv/rvv/strncpy.S
 create mode 100644 sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c

diff --git a/sysdeps/riscv/multiarch/strncpy-generic.c b/sysdeps/riscv/multiarch/strncpy-generic.c
new file mode 100644
index 0000000000..726ca9ed5f
--- /dev/null
+++ b/sysdeps/riscv/multiarch/strncpy-generic.c
@@ -0,0 +1,26 @@
+/* Re-include the default strncpy implementation.
+   Copyright (C) 2026 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 <string.h>
+
+#if IS_IN(libc)
+# define STRNCPY __strncpy_generic
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(x)
+# include <string/strncpy.c>
+#endif
diff --git a/sysdeps/riscv/multiarch/strncpy-vector.S b/sysdeps/riscv/multiarch/strncpy-vector.S
new file mode 100644
index 0000000000..32256f7695
--- /dev/null
+++ b/sysdeps/riscv/multiarch/strncpy-vector.S
@@ -0,0 +1,24 @@
+/* Re-include the RISC-V RVV based strncpy implementation.
+   Copyright (C) 2026 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/>.  */
+
+#if IS_IN(libc)
+# define STRNCPY __strncpy_vector
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(x)
+# include <sysdeps/riscv/rvv/strncpy.S>
+#endif
diff --git a/sysdeps/riscv/rvv/stpncpy.S b/sysdeps/riscv/rvv/stpncpy.S
index 7cfc2f76cc..71bb46b04e 100644
--- a/sysdeps/riscv/rvv/stpncpy.S
+++ b/sysdeps/riscv/rvv/stpncpy.S
@@ -19,12 +19,20 @@
 #include <sysdep.h>
 #include <sys/asm.h>
 
-#ifndef STPNCPY
-# ifdef weak_alias
-#  define STPNCPY __stpncpy
+#ifndef USE_AS_STRNCPY
+# ifndef STPNCPY
+#  ifdef weak_alias
+#   define STPNCPY __stpncpy
 weak_alias (__stpncpy, stpncpy)
+#  else
+#   define STPNCPY stpncpy
+#  endif
+# endif
+#else
+# ifndef STRNCPY
+#  define STPNCPY strncpy
 # else
-#  define STPNCPY stpncpy
+#  define STPNCPY STRNCPY
 # endif
 #endif
 
@@ -62,7 +70,9 @@ L(stpcpy_loop):
     add dst_ptr, dst_ptr, cur_vl
     bgez active_elem_pos, L(fill_zero)
     bnez length, L(stpcpy_loop)
+#ifndef USE_AS_STRNCPY
     mv dst, dst_ptr
+#endif
     ret
 
     /* Fill the tail zero.  */
@@ -72,8 +82,10 @@ L(fill_zero):
        to get the correct remaining length for zero filling.  */
     sub temp, cur_vl, active_elem_pos
     addi temp, temp, -1
+#ifndef USE_AS_STRNCPY
     sub dst, dst_ptr, cur_vl
     add dst, dst, active_elem_pos
+#endif
     add length, length, temp
     /* Return early for the `strlen(src) + 1 == count` case.  */
     bnez length, L(do_fill_zero)
@@ -92,6 +104,11 @@ L(fill_zero_loop):
     ret
 .option pop
 END (STPNCPY)
-#ifdef weak_alias
+
+#ifndef USE_AS_STRNCPY
+# ifdef weak_alias
 libc_hidden_def (__stpncpy)
+# endif
+#else
+libc_hidden_builtin_def (strncpy)
 #endif
diff --git a/sysdeps/riscv/rvv/strncpy.S b/sysdeps/riscv/rvv/strncpy.S
new file mode 100644
index 0000000000..961c16416e
--- /dev/null
+++ b/sysdeps/riscv/rvv/strncpy.S
@@ -0,0 +1,20 @@
+/* RISC-V RVV based strncpy.
+   Copyright (C) 2026 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/>.  */
+
+#define USE_AS_STRNCPY
+#include <sysdeps/riscv/rvv/stpncpy.S>
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
index 25d8216d2e..4991466369 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile
@@ -40,6 +40,9 @@ sysdep_routines += \
   strncmp \
   strncmp-generic \
   strncmp-vector \
+  strncpy \
+  strncpy-generic \
+  strncpy-vector \
   strrchr \
   strrchr-generic \
   strrchr-vector \
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
index 755ba9d637..ac2b25de74 100644
--- a/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/ifunc-impl-list.c
@@ -115,5 +115,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __stpncpy_vector)
 	      IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_generic))
 
+  IFUNC_IMPL (i, name, strncpy,
+	      IFUNC_IMPL_ADD (array, i, strncpy, rvv_enabled,
+			      __strncpy_vector)
+	      IFUNC_IMPL_ADD (array, i, strncpy, 1, __strncpy_generic))
+
   return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c b/sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c
new file mode 100644
index 0000000000..2ed6878bfd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/multiarch/strncpy.c
@@ -0,0 +1,59 @@
+/* Multiple versions of strncpy.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2026 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/>.  */
+
+#if IS_IN (libc)
+#define SYMBOL_NAME strncpy
+# include <ifunc-init.h>
+
+/* Redefine strncpy so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strncpy
+# define strncpy REDIRECT_NAME
+# include <string.h>
+# undef strncpy
+
+# include <stdint.h>
+# include <riscv-ifunc.h>
+# include <sys/hwprobe.h>
+
+extern __typeof (REDIRECT_NAME) __strncpy;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (vector) attribute_hidden;
+
+static inline __typeof (REDIRECT_NAME) *
+select_strncpy_ifunc (uint64_t dl_hwcap, __riscv_hwprobe_t hwprobe_func)
+{
+  unsigned long long int v;
+  if (__riscv_hwprobe_one (hwprobe_func, RISCV_HWPROBE_KEY_IMA_EXT_0, &v) == 0
+      && (v & RISCV_HWPROBE_IMA_V) == RISCV_HWPROBE_IMA_V)
+    return OPTIMIZE (vector);
+  return OPTIMIZE (generic);
+}
+
+riscv_libc_ifunc (__strncpy, select_strncpy_ifunc);
+
+strong_alias (__strncpy, strncpy);
+
+# ifdef SHARED
+__hidden_ver1 (strncpy, __GI_strncpy, REDIRECT_NAME)
+  __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strncpy);
+# endif
+#else
+# include <string/strncpy.c>
+#endif
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.