]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
tile: allow memcpy(p, p, n) without corrupting memory at "p"
authorChris Metcalf <cmetcalf@tilera.com>
Fri, 11 May 2012 21:59:23 +0000 (17:59 -0400)
committerChris Metcalf <cmetcalf@tilera.com>
Mon, 14 May 2012 19:46:12 +0000 (15:46 -0400)
Although this is not required by the definition of memcpy(),
in practice this sort of thing does happen, and it's easy to make
the code robust by doing nothing in this case.  (Since structure
copy causes the compiler to emit a memcpy, in the case where the
target structure is the same as the destination, we were seeing
corruption.)

ChangeLog.tile
sysdeps/tile/tilegx/memcpy.c

index 5cdc293f8ee6a2d19e32f5abde5318fab9911349..83136aa6c34dee8f4b3d7ac0396fec9600820fd8 100644 (file)
@@ -1,3 +1,8 @@
+2012-05-12  Chris Metcalf  <cmetcalf@tilera.com>
+
+       * sysdeps/tile/tilegx/memcpy.c: Allow memcpy(p, p, n)
+       without corrupting memory at "p".
+
 2012-05-12  Chris Metcalf  <cmetcalf@tilera.com>
 
        * sysdeps/tile/__tls_get_addr.S: Use __WORDSIZE, not _LP64.
index 9cfb283c821d7ea85e07bef0ef964f0bdaa90e63..dd6e30dd60783915721466a6a6aafe444f8cd555 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2011-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
 
@@ -107,6 +107,17 @@ __memcpy (void *__restrict dstv, const void *__restrict srcv, size_t n)
                n -= sizeof (word_t))
             *dst8++ = *src8++;
 
+          /* If copying to self, return.  The test is cheap enough
+             that we do it despite the fact that the memcpy() contract
+             doesn't require us to support overlapping dst and src.
+             This is the most common case of overlap, and any close
+             overlap will cause corruption due to the wh64 below.
+             This case is particularly important since the compiler
+             will emit memcpy() calls for aggregate copies even if it
+             can't prove that src != dst.  */
+          if (__builtin_expect (dst8 == src8, 0))
+            return dstv;
+
           for (; n >= CHIP_L2_LINE_SIZE ();)
             {
               __insn_wh64 (dst8);