(root)/
glibc-2.38/
string/
test-memcpy-support.h
       1  /* Support for testing and measuring memcpy functions.
       2     Copyright (C) 1999-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  /* This fail contains the actual memcpy test functions. It is included
      20     in test-memcpy.c and test-memcpy-large.c.  They are split because
      21     the tests take a long time to run and splitting them allows for
      22     simpler parallel testing.  */
      23  
      24  #ifndef MEMCPY_RESULT
      25  #define MEMCPY_RESULT(dst, len) dst
      26  #define MIN_PAGE_SIZE 131072
      27  #define TEST_MAIN
      28  #define TEST_NAME "memcpy"
      29  #define TIMEOUT (8 * 60)
      30  #include "test-string.h"
      31  
      32  IMPL (memcpy, 1)
      33  
      34  /* Naive implementation to verify results.  */
      35  char *
      36  simple_memcpy (char *dst, const char *src, size_t n)
      37  {
      38    char *ret = dst;
      39    while (n--)
      40      *dst++ = *src++;
      41    return ret;
      42  }
      43  
      44  #endif
      45  typedef char *(*proto_t) (char *, const char *, size_t);
      46  typedef uint32_t __attribute__ ((may_alias, aligned (1))) unaligned_uint32_t;
      47  
      48  static void
      49  do_one_test (impl_t *impl, char *dst, const char *src, size_t len)
      50  {
      51    size_t i;
      52  
      53    /* Must clear the destination buffer set by the previous run.  */
      54    for (i = 0; i < len; i++)
      55      dst[i] = 0;
      56  
      57    if (CALL (impl, dst, src, len) != MEMCPY_RESULT (dst, len))
      58      {
      59        error (0, 0, "Wrong result in function %s %p %p", impl->name,
      60               CALL (impl, dst, src, len), MEMCPY_RESULT (dst, len));
      61        ret = 1;
      62        return;
      63      }
      64  
      65    if (memcmp (dst, src, len) != 0)
      66      {
      67        error (0, 0,
      68               "Wrong result in function %s dst %p \"%.*s\" src %p \"%.*s\" len "
      69               "%zu",
      70               impl->name, dst, (int)len, dst, src, (int)len, src, len);
      71        ret = 1;
      72        return;
      73      }
      74  }
      75  
      76  static void
      77  do_test (size_t align1, size_t align2, size_t len)
      78  {
      79    size_t i, j;
      80    char *s1, *s2;
      81  
      82    align1 &= 4095;
      83    if (align1 + len >= page_size)
      84      return;
      85  
      86    align2 &= 4095;
      87    if (align2 + len >= page_size)
      88      return;
      89  
      90    s1 = (char *)(buf1 + align1);
      91    s2 = (char *)(buf2 + align2);
      92    for (size_t repeats = 0; repeats < 2; ++repeats)
      93      {
      94        for (i = 0, j = 1; i < len; i++, j += 23)
      95          s1[i] = j;
      96  
      97        FOR_EACH_IMPL (impl, 0)
      98        do_one_test (impl, s2, s1, len);
      99  
     100        s1 = (char *) (buf2 + align1);
     101        s2 = (char *) (buf1 + align2);
     102      }
     103  }
     104  
     105  static void
     106  do_test1 (size_t align1, size_t align2, size_t size)
     107  {
     108    void *large_buf;
     109    size_t mmap_size, region_size;
     110  
     111    align1 &= (page_size - 1);
     112    if (align1 == 0)
     113      align1 = page_size;
     114  
     115    align2 &= (page_size - 1);
     116    if (align2 == 0)
     117      align2 = page_size;
     118  
     119    region_size = (size + page_size - 1) & (~(page_size - 1));
     120  
     121    mmap_size = region_size * 2 + 3 * page_size;
     122    large_buf = mmap (NULL, mmap_size, PROT_READ | PROT_WRITE,
     123                      MAP_PRIVATE | MAP_ANON, -1, 0);
     124    if (large_buf == MAP_FAILED)
     125      {
     126        puts ("Failed to allocate large_buf, skipping do_test");
     127        return;
     128      }
     129    if (mprotect (large_buf + region_size + page_size, page_size, PROT_NONE))
     130      error (EXIT_FAILURE, errno, "mprotect failed");
     131  
     132    size_t array_size = size / sizeof (uint32_t);
     133    unaligned_uint32_t *dest = large_buf + align1;
     134    unaligned_uint32_t *src = large_buf + region_size + 2 * page_size + align2;
     135    size_t i;
     136    for (size_t repeats = 0; repeats < 2; repeats++)
     137      {
     138        for (i = 0; i < array_size; i++)
     139          src[i] = (uint32_t)i;
     140        FOR_EACH_IMPL (impl, 0)
     141  	{
     142  	  memset (dest, -1, size);
     143  	  CALL (impl, (char *)dest, (char *)src, size);
     144  	  if (memcmp (src, dest, size))
     145  	    {
     146  	      for (i = 0; i < array_size; i++)
     147  		if (dest[i] != src[i])
     148  		  {
     149  		    error (0, 0,
     150  			   "Wrong result in function %s dst \"%p\" src \"%p\" "
     151  			   "offset \"%zd\"",
     152  			   impl->name, dest, src, i);
     153  		    ret = 1;
     154  		    munmap ((void *)large_buf, mmap_size);
     155  		    return;
     156  		  }
     157  	    }
     158  	}
     159        dest = large_buf + region_size + 2 * page_size + align1;
     160        src = large_buf + align2;
     161      }
     162    munmap ((void *)large_buf, mmap_size);
     163  }