Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <stdint.h>
6 : : #include <stdio.h>
7 : : #include <string.h>
8 : : #include <stdlib.h>
9 : :
10 : : #include <rte_common.h>
11 : : #include <rte_random.h>
12 : : #include <rte_memcpy.h>
13 : :
14 : : #include "test.h"
15 : :
16 : : /*
17 : : * Set this to the maximum buffer size you want to test. If it is 0, then the
18 : : * values in the buf_sizes[] array below will be used.
19 : : */
20 : : #define TEST_VALUE_RANGE 0
21 : :
22 : : /* List of buffer sizes to test */
23 : : #if TEST_VALUE_RANGE == 0
24 : : static size_t buf_sizes[] = {
25 : : 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129, 255,
26 : : 256, 257, 320, 384, 511, 512, 513, 1023, 1024, 1025, 1518, 1522, 1600,
27 : : 2048, 3072, 4096, 5120, 6144, 7168, 8192
28 : : };
29 : : /* MUST be as large as largest packet size above */
30 : : #define SMALL_BUFFER_SIZE 8192
31 : : #else /* TEST_VALUE_RANGE != 0 */
32 : : static size_t buf_sizes[TEST_VALUE_RANGE];
33 : : #define SMALL_BUFFER_SIZE TEST_VALUE_RANGE
34 : : #endif /* TEST_VALUE_RANGE == 0 */
35 : :
36 : : /* Data is aligned on this many bytes (power of 2) */
37 : : #define ALIGNMENT_UNIT 32
38 : :
39 : : /*
40 : : * Subset of offsets to test. These values cover the structurally
41 : : * interesting alignment cases for SSE/AVX copy paths:
42 : : * aligned (0), off-by-one (1), partial vector (7, 15, 17),
43 : : * vector boundaries (16, 31). Testing all 1024 src x dst
44 : : * combinations of offsets 0..31 is unnecessary since many
45 : : * map to the same code paths, and causes the test to timeout
46 : : * on slow (e.g. emulated 32-bit) build environments.
47 : : */
48 : : static const unsigned int test_offsets[] = {0, 1, 7, 15, 16, 17, 31};
49 : :
50 : : /*
51 : : * Create two buffers, and initialise one with random values. These are copied
52 : : * to the second buffer and then compared to see if the copy was successful.
53 : : * The bytes outside the copied area are also checked to make sure they were not
54 : : * changed.
55 : : */
56 : : static int
57 : 1862 : test_single_memcpy(unsigned int off_src, unsigned int off_dst, size_t size)
58 : : {
59 : : unsigned int i;
60 : : uint8_t dest[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT];
61 : : uint8_t src[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT];
62 : : void * ret;
63 : :
64 : : /* Setup buffers */
65 [ + + ]: 15314950 : for (i = 0; i < SMALL_BUFFER_SIZE + ALIGNMENT_UNIT; i++) {
66 : 15313088 : dest[i] = 0;
67 : 15313088 : src[i] = (uint8_t) rte_rand();
68 : : }
69 : :
70 : : /* Do the copy */
71 [ + + ]: 1862 : ret = rte_memcpy(dest + off_dst, src + off_src, size);
72 : : if (ret != (dest + off_dst)) {
73 : : printf("rte_memcpy() returned %p, not %p\n",
74 : : ret, dest + off_dst);
75 : : }
76 : :
77 : : /* Check nothing before offset is affected */
78 [ + + ]: 25004 : for (i = 0; i < off_dst; i++) {
79 [ - + ]: 23142 : if (dest[i] != 0) {
80 : 0 : printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
81 : : "[modified before start of dst].\n",
82 : : (unsigned)size, off_src, off_dst);
83 : 0 : return -1;
84 : : }
85 : : }
86 : :
87 : : /* Check everything was copied */
88 [ + + ]: 2319807 : for (i = 0; i < size; i++) {
89 [ - + ]: 2317945 : if (dest[i + off_dst] != src[i + off_src]) {
90 : 0 : printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
91 : : "[didn't copy byte %u].\n",
92 : : (unsigned)size, off_src, off_dst, i);
93 : 0 : return -1;
94 : : }
95 : : }
96 : :
97 : : /* Check nothing after copy was affected */
98 [ + + ]: 12937421 : for (i = size; i < SMALL_BUFFER_SIZE; i++) {
99 [ - + ]: 12935559 : if (dest[i + off_dst] != 0) {
100 : : printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
101 : : "[copied too many].\n",
102 : : (unsigned)size, off_src, off_dst);
103 : 0 : return -1;
104 : : }
105 : : }
106 : : return 0;
107 : : }
108 : :
109 : : /*
110 : : * Check functionality for various buffer sizes and data offsets/alignments.
111 : : */
112 : : static int
113 : 1 : func_test(void)
114 : : {
115 : : unsigned int off_src, off_dst, i;
116 : : unsigned int n_offsets = RTE_DIM(test_offsets);
117 : : int ret;
118 : :
119 [ + + ]: 8 : for (off_src = 0; off_src < n_offsets; off_src++) {
120 [ + + ]: 56 : for (off_dst = 0; off_dst < n_offsets; off_dst++) {
121 [ + + ]: 1911 : for (i = 0; i < RTE_DIM(buf_sizes); i++) {
122 : 1862 : ret = test_single_memcpy(test_offsets[off_src],
123 : 1862 : test_offsets[off_dst],
124 : : buf_sizes[i]);
125 [ + - ]: 1862 : if (ret != 0)
126 : : return -1;
127 : : }
128 : : }
129 : : }
130 : : return 0;
131 : : }
132 : :
133 : : static int
134 : 1 : test_memcpy(void)
135 : : {
136 : : int ret;
137 : :
138 : 1 : ret = func_test();
139 [ - + ]: 1 : if (ret != 0)
140 : 0 : return -1;
141 : : return 0;
142 : : }
143 : :
144 : 276 : REGISTER_FAST_TEST(memcpy_autotest, NOHUGE_OK, ASAN_OK, test_memcpy);
|