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.
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.
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.
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/>. */
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. */
25 #define MEMCPY_RESULT(dst, len) dst
26 #define MIN_PAGE_SIZE 131072
28 #define TEST_NAME "memcpy"
29 #define TIMEOUT (8 * 60)
30 #include "test-string.h"
34 /* Naive implementation to verify results. */
36 simple_memcpy (char *dst
, const char *src
, size_t n
)
45 typedef char *(*proto_t
) (char *, const char *, size_t);
46 typedef uint32_t __attribute__ ((may_alias
, aligned (1))) unaligned_uint32_t
;
49 do_one_test (impl_t
*impl
, char *dst
, const char *src
, size_t len
)
53 /* Must clear the destination buffer set by the previous run. */
54 for (i
= 0; i
< len
; i
++)
57 if (CALL (impl
, dst
, src
, len
) != MEMCPY_RESULT (dst
, len
))
59 error (0, 0, "Wrong result in function %s %p %p", impl
->name
,
60 CALL (impl
, dst
, src
, len
), MEMCPY_RESULT (dst
, len
));
65 if (memcmp (dst
, src
, len
) != 0)
68 "Wrong result in function %s dst %p \"%.*s\" src %p \"%.*s\" len "
70 impl
->name
, dst
, (int)len
, dst
, src
, (int)len
, src
, len
);
77 do_test (size_t align1
, size_t align2
, size_t len
)
83 if (align1
+ len
>= page_size
)
87 if (align2
+ len
>= page_size
)
90 s1
= (char *)(buf1
+ align1
);
91 s2
= (char *)(buf2
+ align2
);
92 for (size_t repeats
= 0; repeats
< 2; ++repeats
)
94 for (i
= 0, j
= 1; i
< len
; i
++, j
+= 23)
97 FOR_EACH_IMPL (impl
, 0)
98 do_one_test (impl
, s2
, s1
, len
);
100 s1
= (char *) (buf2
+ align1
);
101 s2
= (char *) (buf1
+ align2
);
106 do_test1 (size_t align1
, size_t align2
, size_t size
)
109 size_t mmap_size
, region_size
;
111 align1
&= (page_size
- 1);
115 align2
&= (page_size
- 1);
119 region_size
= (size
+ page_size
- 1) & (~(page_size
- 1));
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
)
126 puts ("Failed to allocate large_buf, skipping do_test");
129 if (mprotect (large_buf
+ region_size
+ page_size
, page_size
, PROT_NONE
))
130 error (EXIT_FAILURE
, errno
, "mprotect failed");
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
;
136 for (size_t repeats
= 0; repeats
< 2; repeats
++)
138 for (i
= 0; i
< array_size
; i
++)
139 src
[i
] = (uint32_t)i
;
140 FOR_EACH_IMPL (impl
, 0)
142 memset (dest
, -1, size
);
143 CALL (impl
, (char *)dest
, (char *)src
, size
);
144 if (memcmp (src
, dest
, size
))
146 for (i
= 0; i
< array_size
; i
++)
147 if (dest
[i
] != src
[i
])
150 "Wrong result in function %s dst \"%p\" src \"%p\" "
152 impl
->name
, dest
, src
, i
);
154 munmap ((void *)large_buf
, mmap_size
);
159 dest
= large_buf
+ region_size
+ 2 * page_size
+ align1
;
160 src
= large_buf
+ align2
;
162 munmap ((void *)large_buf
, mmap_size
);