blob: d3a4df9a8c9d39dd7653092fe244ae0bd08341d5 [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <debug.h>
24#include <string.h>
25#include <malloc.h>
Travis Geiselbrecht3f14b662009-01-24 21:21:54 -080026#include <app.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070027#include <platform.h>
28#include <kernel/thread.h>
29
30static uint8_t *src;
31static uint8_t *dst;
32
33static uint8_t *src2;
34static uint8_t *dst2;
35
36#define BUFFER_SIZE (1024*1024)
37#define ITERATIONS 16
38
39extern void *mymemcpy(void *dst, const void *src, size_t len);
40extern void *mymemset(void *dst, int c, size_t len);
41
42static void *null_memcpy(void *dst, const void *src, size_t len)
43{
44 return dst;
45}
46
47static time_t bench_memcpy_routine(void *memcpy_routine(void *, const void *, size_t), size_t srcalign, size_t dstalign)
48{
49 int i;
50 time_t t0;
51
52 t0 = current_time();
53 for (i=0; i < ITERATIONS; i++) {
54 memcpy_routine(dst + dstalign, src + srcalign, BUFFER_SIZE);
55 }
56 return current_time() - t0;
57}
58
59static void bench_memcpy(void)
60{
61 time_t null, libc, mine;
62 size_t srcalign, dstalign;
63
Travis Geiselbrechteb946052008-09-07 22:32:49 -070064 printf("memcpy speed test\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070065 thread_sleep(200); // let the debug string clear the serial port
66
67 for (srcalign = 0; srcalign < 64; ) {
68 for (dstalign = 0; dstalign < 64; ) {
69
70 null = bench_memcpy_routine(&null_memcpy, srcalign, dstalign);
71 libc = bench_memcpy_routine(&memcpy, srcalign, dstalign);
72 mine = bench_memcpy_routine(&mymemcpy, srcalign, dstalign);
73
Travis Geiselbrechteb946052008-09-07 22:32:49 -070074 printf("srcalign %lu, dstalign %lu\n", srcalign, dstalign);
75 printf(" null memcpy %u msecs\n", null);
76 printf(" libc memcpy %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
77 printf(" my memcpy %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070078
79 if (dstalign == 0)
80 dstalign = 1;
81 else
82 dstalign <<= 1;
83 }
84 if (srcalign == 0)
85 srcalign = 1;
86 else
87 srcalign <<= 1;
88 }
89}
90
91static void fillbuf(void *ptr, size_t len, uint32_t seed)
92{
93 size_t i;
94
95 for (i = 0; i < len; i++) {
96 ((char *)ptr)[i] = seed;
97 seed *= 0x1234567;
98 }
99}
100
101static void validate_memcpy(void)
102{
103 size_t srcalign, dstalign, size;
104 const size_t maxsize = 256;
105
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700106 printf("testing memcpy for correctness\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700107
108 /*
109 * do the simple tests to make sure that memcpy doesn't color outside
110 * the lines for all alignment cases
111 */
112 for (srcalign = 0; srcalign < 64; srcalign++) {
113 for (dstalign = 0; dstalign < 64; dstalign++) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700114// printf("srcalign %zu, dstalign %zu\n", srcalign, dstalign);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700115 for (size = 0; size < maxsize; size++) {
116
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700117// printf("srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700118
119 fillbuf(src, maxsize * 2, 567);
120 fillbuf(src2, maxsize * 2, 567);
121 fillbuf(dst, maxsize * 2, 123514);
122 fillbuf(dst2, maxsize * 2, 123514);
123
124 memcpy(dst + dstalign, src + srcalign, size);
125 mymemcpy(dst2 + dstalign, src2 + srcalign, size);
126
127 int comp = memcmp(dst, dst2, maxsize * 2);
128 if (comp != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700129 printf("error! srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700130 }
131 }
132 }
133 }
134}
135
Kinson Chik150cc962011-10-10 13:11:32 -0700136static void validate_memcpy_overlap(void)
137{
138 size_t srcalign, dstalign, size;
139 const size_t maxsize = 256;
140 int comp;
141
142 printf("testing memcpy for correctness in overlap cases\n");
143
144 for (dstalign = 0; dstalign < 64; dstalign++) {
145 for (size = 0; size < maxsize; size++) {
146
147 fillbuf(src, maxsize * 2, 567);
148 fillbuf(src2, maxsize * 2, 567);
149
150 /* Case one will check cpy memory is the same - fwd*/
151 memcpy(src + dstalign, src, size);
152 comp = memcmp(src + dstalign, src2, size);
153 if (comp != 0) {
154 printf("ERROR (Case1): dstalign %zu, size %zu, ret %d\n", dstalign, size, comp);
155 }
156
157 fillbuf(src, maxsize * 2, 8588485);
158 fillbuf(src2, maxsize * 2, 8588485);
159
160 /* Case two will check cpy memory is the same - bkwd*/
161 memcpy(src, src + dstalign, size);
162 comp = memcmp(src, src2 + dstalign, size);
163 if (comp != 0) {
164 printf("ERROR (Case2): dstalign %zu, size %zu, ret %d\n", dstalign, size, comp);
165 }
166 }
167 }
168}
169
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700170static time_t bench_memset_routine(void *memset_routine(void *, int, size_t), size_t dstalign)
171{
172 int i;
173 time_t t0;
174
175 t0 = current_time();
176 for (i=0; i < ITERATIONS; i++) {
177 memset_routine(dst + dstalign, 0, BUFFER_SIZE);
178 }
179 return current_time() - t0;
180}
181
182static void bench_memset(void)
183{
184 time_t libc, mine;
185 size_t dstalign;
186
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700187 printf("memset speed test\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700188 thread_sleep(200); // let the debug string clear the serial port
189
190 for (dstalign = 0; dstalign < 64; dstalign++) {
191
192 libc = bench_memset_routine(&memset, dstalign);
193 mine = bench_memset_routine(&mymemset, dstalign);
194
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700195 printf("dstalign %lu\n", dstalign);
196 printf(" libc memset %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
197 printf(" my memset %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700198 }
199}
200
201static void validate_memset(void)
202{
203 size_t dstalign, size;
204 int c;
205 const size_t maxsize = 256;
206
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700207 printf("testing memset for correctness\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700208
209 for (dstalign = 0; dstalign < 64; dstalign++) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700210 printf("align %zd\n", dstalign);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700211 for (size = 0; size < maxsize; size++) {
212 for (c = 0; c < 256; c++) {
213
214 fillbuf(dst, maxsize * 2, 123514);
215 fillbuf(dst2, maxsize * 2, 123514);
216
217 memset(dst + dstalign, c, size);
218 mymemset(dst2 + dstalign, c, size);
219
220 int comp = memcmp(dst, dst2, maxsize * 2);
221 if (comp != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700222 printf("error! align %zu, c %d, size %zu\n", dstalign, c, size);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700223 }
224 }
225 }
226 }
227}
228
Travis Geiselbrecht39deded2009-01-24 20:12:27 -0800229#if defined(WITH_LIB_CONSOLE)
230#include <lib/console.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700231
232static int string_tests(int argc, cmd_args *argv)
233{
234 src = memalign(64, BUFFER_SIZE + 256);
235 dst = memalign(64, BUFFER_SIZE + 256);
236 src2 = memalign(64, BUFFER_SIZE + 256);
237 dst2 = memalign(64, BUFFER_SIZE + 256);
238
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700239 printf("src %p, dst %p\n", src, dst);
240 printf("src2 %p, dst2 %p\n", src2, dst2);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700241
242 if (argc < 3) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700243 printf("not enough arguments:\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700244usage:
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700245 printf("%s validate <routine>\n", argv[0].str);
246 printf("%s bench <routine>\n", argv[0].str);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700247 goto out;
248 }
249
250 if (!strcmp(argv[1].str, "validate")) {
251 if (!strcmp(argv[2].str, "memcpy")) {
252 validate_memcpy();
253 } else if (!strcmp(argv[2].str, "memset")) {
254 validate_memset();
Kinson Chik150cc962011-10-10 13:11:32 -0700255 } else if (!strcmp(argv[2].str, "memcpy_overlap")) {
256 validate_memcpy_overlap();
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700257 }
258 } else if (!strcmp(argv[1].str, "bench")) {
259 if (!strcmp(argv[2].str, "memcpy")) {
260 bench_memcpy();
261 } else if (!strcmp(argv[2].str, "memset")) {
262 bench_memset();
263 }
264 } else {
265 goto usage;
266 }
267
268out:
269 free(src);
270 free(dst);
271 free(src2);
272 free(dst2);
273
274 return 0;
275}
276
277STATIC_COMMAND_START
278{ "string", NULL, &string_tests },
279STATIC_COMMAND_END(stringtests);
280
281#endif
282
Travis Geiselbrecht3f14b662009-01-24 21:21:54 -0800283APP_START(stringtests)
Travis Geiselbrecht3f14b662009-01-24 21:21:54 -0800284APP_END
285