This is an automated email from the ASF dual-hosted git repository.

jerpelea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 1948a225f8f4590d2b76a833b14649f98af41a3f
Author: Justin Hammond <[email protected]>
AuthorDate: Sat Aug 15 14:50:58 2026 +0800

    libs/libc/machine/risc-v: Align strlcpy's destination too.
    
    The word loop walks src to a register boundary and then stores a whole
    register at a time to dst, but nothing establishes that dst is on a
    boundary too.  Where the two pointers disagree about where a boundary
    falls, every store in that loop is misaligned.
    
    The base ISA does not require misaligned stores to be supported.  Where
    firmware emulates them each store traps into machine mode, and where
    nothing emulates them the store faults, so this is not only a question of
    speed.  Measured on a 1.4 GHz rv64 that emulates them, with a 32 KB
    string whose src and dst are misaligned by different amounts:
    
      generic C     410.4 MB/s
      this file       7.5 MB/s
    
    which is around 178 cycles per byte, flat from 512 bytes to 32 KB.
    
    Test the two pointers against each other before going wide, as
    arch_strcpy.S already does.  Pointers that agree still reach the word
    loop, since walking src to a boundary walks dst to one as well; pointers
    that disagree take the byte path, where no single boundary serves both.
    After the change the misaligned case runs at 490 MB/s and the aligned
    rates are unchanged.
    
    The measurements come from the benchmark in apache/nuttx-apps#3706.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Justin Hammond <[email protected]>
---
 libs/libc/machine/risc-v/arch_strlcpy.S | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/libs/libc/machine/risc-v/arch_strlcpy.S 
b/libs/libc/machine/risc-v/arch_strlcpy.S
index 6d18cf40e73..ac90a89dae5 100644
--- a/libs/libc/machine/risc-v/arch_strlcpy.S
+++ b/libs/libc/machine/risc-v/arch_strlcpy.S
@@ -72,7 +72,17 @@ ARCH_LIBCFUN(strlcpy):
 
        addi    a2, a2, -1              /* reserve space for null terminator */
 
-       /* Bytewise copy head: align src to SZREG boundary */
+       /* The word loop below aligns src and then stores a register at a
+        * time to dst, so it is safe only where the two pointers agree about
+        * where a boundary falls.  Where they do not, no single boundary
+        * serves both and the copy goes a byte at a time.
+        */
+
+       xor     t0, a0, a1
+       andi    t0, t0, SZREG-1
+       bnez    t0, .Lcopy_tail
+
+       /* Bytewise copy head: align src, and with it dst */
 
 .Lcopy_head:
        beqz    a2, .Ltruncated

Reply via email to