test-memmove.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* Test and measure memmove functions.
  2. Copyright (C) 1999-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Written by Jakub Jelinek <jakub@redhat.com>, 1999.
  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. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. #define TEST_MAIN
  17. #ifdef TEST_BCOPY
  18. # define TEST_NAME "bcopy"
  19. #else
  20. # define TEST_NAME "memmove"
  21. #endif
  22. #include "test-string.h"
  23. #include <support/test-driver.h>
  24. char *simple_memmove (char *, const char *, size_t);
  25. #ifdef TEST_BCOPY
  26. typedef void (*proto_t) (const char *, char *, size_t);
  27. void simple_bcopy (const char *, char *, size_t);
  28. IMPL (simple_bcopy, 0)
  29. IMPL (bcopy, 1)
  30. void
  31. simple_bcopy (const char *src, char *dst, size_t n)
  32. {
  33. simple_memmove (dst, src, n);
  34. }
  35. #else
  36. typedef char *(*proto_t) (char *, const char *, size_t);
  37. IMPL (simple_memmove, 0)
  38. IMPL (memmove, 1)
  39. #endif
  40. char *
  41. inhibit_loop_to_libcall
  42. simple_memmove (char *dst, const char *src, size_t n)
  43. {
  44. char *ret = dst;
  45. if (src < dst)
  46. {
  47. dst += n;
  48. src += n;
  49. while (n--)
  50. *--dst = *--src;
  51. }
  52. else
  53. while (n--)
  54. *dst++ = *src++;
  55. return ret;
  56. }
  57. static void
  58. do_one_test (impl_t *impl, char *dst, char *src, const char *orig_src,
  59. size_t len)
  60. {
  61. /* This also clears the destination buffer set by the previous run. */
  62. memcpy (src, orig_src, len);
  63. #ifdef TEST_BCOPY
  64. CALL (impl, src, dst, len);
  65. #else
  66. char *res;
  67. res = CALL (impl, dst, src, len);
  68. if (res != dst)
  69. {
  70. error (0, 0, "Wrong result in function %s %p %p", impl->name,
  71. res, dst);
  72. ret = 1;
  73. return;
  74. }
  75. #endif
  76. if (memcmp (dst, orig_src, len) != 0)
  77. {
  78. error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"",
  79. impl->name, dst, src);
  80. ret = 1;
  81. return;
  82. }
  83. }
  84. static void
  85. do_test (size_t align1, size_t align2, size_t len)
  86. {
  87. size_t i, j;
  88. char *s1, *s2;
  89. align1 &= 63;
  90. if (align1 + len >= page_size)
  91. return;
  92. align2 &= 63;
  93. if (align2 + len >= page_size)
  94. return;
  95. s1 = (char *) (buf1 + align1);
  96. s2 = (char *) (buf2 + align2);
  97. for (i = 0, j = 1; i < len; i++, j += 23)
  98. s1[i] = j;
  99. FOR_EACH_IMPL (impl, 0)
  100. do_one_test (impl, s2, (char *) (buf2 + align1), s1, len);
  101. }
  102. static void
  103. do_random_tests (void)
  104. {
  105. size_t i, n, align1, align2, len, size;
  106. size_t srcstart, srcend, dststart, dstend;
  107. int c;
  108. unsigned char *p1, *p2;
  109. #ifndef TEST_BCOPY
  110. unsigned char *res;
  111. #endif
  112. for (n = 0; n < ITERATIONS; n++)
  113. {
  114. if ((random () & 255) == 0)
  115. size = 65536;
  116. else
  117. size = 512;
  118. if (size > page_size)
  119. size = page_size;
  120. if ((random () & 3) == 0)
  121. {
  122. len = random () & (size - 1);
  123. align1 = size - len - (random () & 31);
  124. align2 = size - len - (random () & 31);
  125. if (align1 > size)
  126. align1 = 0;
  127. if (align2 > size)
  128. align2 = 0;
  129. }
  130. else
  131. {
  132. align1 = random () & (size / 2 - 1);
  133. align2 = random () & (size / 2 - 1);
  134. len = random () & (size - 1);
  135. if (align1 + len > size)
  136. align1 = size - len;
  137. if (align2 + len > size)
  138. align2 = size - len;
  139. }
  140. p1 = buf1 + page_size - size;
  141. p2 = buf2 + page_size - size;
  142. c = random () & 255;
  143. srcend = align1 + len + 256;
  144. if (srcend > size)
  145. srcend = size;
  146. if (align1 > 256)
  147. srcstart = align1 - 256;
  148. else
  149. srcstart = 0;
  150. for (i = srcstart; i < srcend; ++i)
  151. p1[i] = random () & 255;
  152. dstend = align2 + len + 256;
  153. if (dstend > size)
  154. dstend = size;
  155. if (align2 > 256)
  156. dststart = align2 - 256;
  157. else
  158. dststart = 0;
  159. FOR_EACH_IMPL (impl, 1)
  160. {
  161. memset (p2 + dststart, c, dstend - dststart);
  162. memcpy (p2 + srcstart, p1 + srcstart, srcend - srcstart);
  163. #ifdef TEST_BCOPY
  164. CALL (impl, (char *) (p2 + align1), (char *) (p2 + align2), len);
  165. #else
  166. res = (unsigned char *) CALL (impl,
  167. (char *) (p2 + align2),
  168. (char *) (p2 + align1), len);
  169. if (res != p2 + align2)
  170. {
  171. error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
  172. n, impl->name, align1, align2, len, res, p2 + align2);
  173. ret = 1;
  174. }
  175. #endif
  176. if (memcmp (p1 + align1, p2 + align2, len))
  177. {
  178. error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
  179. n, impl->name, align1, align2, len);
  180. ret = 1;
  181. }
  182. for (i = dststart; i < dstend; ++i)
  183. {
  184. if (i >= align2 && i < align2 + len)
  185. {
  186. i = align2 + len - 1;
  187. continue;
  188. }
  189. if (i >= srcstart && i < srcend)
  190. {
  191. i = srcend - 1;
  192. continue;
  193. }
  194. if (p2[i] != c)
  195. {
  196. error (0, 0, "Iteration %zd - garbage in memset area, %s (%zd, %zd, %zd)",
  197. n, impl->name, align1, align2, len);
  198. ret = 1;
  199. break;
  200. }
  201. }
  202. if (srcstart < align2
  203. && memcmp (p2 + srcstart, p1 + srcstart,
  204. (srcend > align2 ? align2 : srcend) - srcstart))
  205. {
  206. error (0, 0, "Iteration %zd - garbage before dst, %s (%zd, %zd, %zd)",
  207. n, impl->name, align1, align2, len);
  208. ret = 1;
  209. break;
  210. }
  211. i = srcstart > align2 + len ? srcstart : align2 + len;
  212. if (srcend > align2 + len
  213. && memcmp (p2 + i, p1 + i, srcend - i))
  214. {
  215. error (0, 0, "Iteration %zd - garbage after dst, %s (%zd, %zd, %zd)",
  216. n, impl->name, align1, align2, len);
  217. ret = 1;
  218. break;
  219. }
  220. }
  221. }
  222. }
  223. static void
  224. do_test2 (void)
  225. {
  226. size_t size = 0x20000000;
  227. uint32_t * large_buf;
  228. large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE,
  229. MAP_PRIVATE | MAP_ANON, -1, 0);
  230. if (large_buf == MAP_FAILED)
  231. error (EXIT_UNSUPPORTED, errno, "Large mmap failed");
  232. if ((uintptr_t) large_buf > 0x80000000 - 128
  233. || 0x80000000 - (uintptr_t) large_buf > 0x20000000)
  234. {
  235. error (0, 0, "Large mmap allocated improperly");
  236. ret = EXIT_UNSUPPORTED;
  237. munmap ((void *) large_buf, size);
  238. return;
  239. }
  240. size_t bytes_move = 0x80000000 - (uintptr_t) large_buf;
  241. size_t arr_size = bytes_move / sizeof (uint32_t);
  242. size_t i;
  243. FOR_EACH_IMPL (impl, 0)
  244. {
  245. for (i = 0; i < arr_size; i++)
  246. large_buf[i] = (uint32_t) i;
  247. uint32_t * dst = &large_buf[33];
  248. #ifdef TEST_BCOPY
  249. CALL (impl, (char *) large_buf, (char *) dst, bytes_move);
  250. #else
  251. CALL (impl, (char *) dst, (char *) large_buf, bytes_move);
  252. #endif
  253. for (i = 0; i < arr_size; i++)
  254. {
  255. if (dst[i] != (uint32_t) i)
  256. {
  257. error (0, 0,
  258. "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"",
  259. impl->name, dst, large_buf, i);
  260. ret = 1;
  261. break;
  262. }
  263. }
  264. }
  265. munmap ((void *) large_buf, size);
  266. }
  267. int
  268. test_main (void)
  269. {
  270. size_t i;
  271. test_init ();
  272. printf ("%23s", "");
  273. FOR_EACH_IMPL (impl, 0)
  274. printf ("\t%s", impl->name);
  275. putchar ('\n');
  276. for (i = 0; i < 14; ++i)
  277. {
  278. do_test (0, 32, 1 << i);
  279. do_test (32, 0, 1 << i);
  280. do_test (0, i, 1 << i);
  281. do_test (i, 0, 1 << i);
  282. }
  283. for (i = 0; i < 32; ++i)
  284. {
  285. do_test (0, 32, i);
  286. do_test (32, 0, i);
  287. do_test (0, i, i);
  288. do_test (i, 0, i);
  289. }
  290. for (i = 3; i < 32; ++i)
  291. {
  292. if ((i & (i - 1)) == 0)
  293. continue;
  294. do_test (0, 32, 16 * i);
  295. do_test (32, 0, 16 * i);
  296. do_test (0, i, 16 * i);
  297. do_test (i, 0, 16 * i);
  298. }
  299. do_random_tests ();
  300. do_test2 ();
  301. return ret;
  302. }
  303. #include <support/test-driver.c>