| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- /*
- * Copyright (c) 2008 Travis Geiselbrecht
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- #include <debug.h>
- #include <string.h>
- #include <malloc.h>
- #include <app.h>
- #include <platform.h>
- #include <kernel/thread.h>
- static uint8_t *src;
- static uint8_t *dst;
- static uint8_t *src2;
- static uint8_t *dst2;
- #define BUFFER_SIZE (1024*1024)
- #define ITERATIONS 16
- extern void *mymemcpy(void *dst, const void *src, size_t len);
- extern void *mymemset(void *dst, int c, size_t len);
- static void *null_memcpy(void *dst, const void *src, size_t len)
- {
- return dst;
- }
- static time_t bench_memcpy_routine(void *memcpy_routine(void *, const void *, size_t), size_t srcalign, size_t dstalign)
- {
- int i;
- time_t t0;
- t0 = current_time();
- for (i=0; i < ITERATIONS; i++) {
- memcpy_routine(dst + dstalign, src + srcalign, BUFFER_SIZE);
- }
- return current_time() - t0;
- }
- static void bench_memcpy(void)
- {
- time_t null, libc, mine;
- size_t srcalign, dstalign;
-
- printf("memcpy speed test\n");
- thread_sleep(200); // let the debug string clear the serial port
- for (srcalign = 0; srcalign < 64; ) {
- for (dstalign = 0; dstalign < 64; ) {
- null = bench_memcpy_routine(&null_memcpy, srcalign, dstalign);
- libc = bench_memcpy_routine(&memcpy, srcalign, dstalign);
- mine = bench_memcpy_routine(&mymemcpy, srcalign, dstalign);
- printf("srcalign %lu, dstalign %lu\n", srcalign, dstalign);
- printf(" null memcpy %u msecs\n", null);
- printf(" libc memcpy %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
- printf(" my memcpy %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
- if (dstalign == 0)
- dstalign = 1;
- else
- dstalign <<= 1;
- }
- if (srcalign == 0)
- srcalign = 1;
- else
- srcalign <<= 1;
- }
- }
- static void fillbuf(void *ptr, size_t len, uint32_t seed)
- {
- size_t i;
- for (i = 0; i < len; i++) {
- ((char *)ptr)[i] = seed;
- seed *= 0x1234567;
- }
- }
- static void validate_memcpy(void)
- {
- size_t srcalign, dstalign, size;
- const size_t maxsize = 256;
- printf("testing memcpy for correctness\n");
- /*
- * do the simple tests to make sure that memcpy doesn't color outside
- * the lines for all alignment cases
- */
- for (srcalign = 0; srcalign < 64; srcalign++) {
- for (dstalign = 0; dstalign < 64; dstalign++) {
- // printf("srcalign %zu, dstalign %zu\n", srcalign, dstalign);
- for (size = 0; size < maxsize; size++) {
- // printf("srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
- fillbuf(src, maxsize * 2, 567);
- fillbuf(src2, maxsize * 2, 567);
- fillbuf(dst, maxsize * 2, 123514);
- fillbuf(dst2, maxsize * 2, 123514);
- memcpy(dst + dstalign, src + srcalign, size);
- mymemcpy(dst2 + dstalign, src2 + srcalign, size);
- int comp = memcmp(dst, dst2, maxsize * 2);
- if (comp != 0) {
- printf("error! srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
- }
- }
- }
- }
- }
- static void validate_memcpy_overlap(void)
- {
- size_t srcalign, dstalign, size;
- const size_t maxsize = 256;
- int comp;
- printf("testing memcpy for correctness in overlap cases\n");
- for (dstalign = 0; dstalign < 64; dstalign++) {
- for (size = 0; size < maxsize; size++) {
- fillbuf(src, maxsize * 2, 567);
- fillbuf(src2, maxsize * 2, 567);
- /* Case one will check cpy memory is the same - fwd*/
- memcpy(src + dstalign, src, size);
- comp = memcmp(src + dstalign, src2, size);
- if (comp != 0) {
- printf("ERROR (Case1): dstalign %zu, size %zu, ret %d\n", dstalign, size, comp);
- }
- fillbuf(src, maxsize * 2, 8588485);
- fillbuf(src2, maxsize * 2, 8588485);
- /* Case two will check cpy memory is the same - bkwd*/
- memcpy(src, src + dstalign, size);
- comp = memcmp(src, src2 + dstalign, size);
- if (comp != 0) {
- printf("ERROR (Case2): dstalign %zu, size %zu, ret %d\n", dstalign, size, comp);
- }
- }
- }
- }
- static time_t bench_memset_routine(void *memset_routine(void *, int, size_t), size_t dstalign)
- {
- int i;
- time_t t0;
- t0 = current_time();
- for (i=0; i < ITERATIONS; i++) {
- memset_routine(dst + dstalign, 0, BUFFER_SIZE);
- }
- return current_time() - t0;
- }
- static void bench_memset(void)
- {
- time_t libc, mine;
- size_t dstalign;
-
- printf("memset speed test\n");
- thread_sleep(200); // let the debug string clear the serial port
- for (dstalign = 0; dstalign < 64; dstalign++) {
- libc = bench_memset_routine(&memset, dstalign);
- mine = bench_memset_routine(&mymemset, dstalign);
- printf("dstalign %lu\n", dstalign);
- printf(" libc memset %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
- printf(" my memset %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
- }
- }
- static void validate_memset(void)
- {
- size_t dstalign, size;
- int c;
- const size_t maxsize = 256;
- printf("testing memset for correctness\n");
- for (dstalign = 0; dstalign < 64; dstalign++) {
- printf("align %zd\n", dstalign);
- for (size = 0; size < maxsize; size++) {
- for (c = 0; c < 256; c++) {
- fillbuf(dst, maxsize * 2, 123514);
- fillbuf(dst2, maxsize * 2, 123514);
- memset(dst + dstalign, c, size);
- mymemset(dst2 + dstalign, c, size);
- int comp = memcmp(dst, dst2, maxsize * 2);
- if (comp != 0) {
- printf("error! align %zu, c %d, size %zu\n", dstalign, c, size);
- }
- }
- }
- }
- }
- #if defined(WITH_LIB_CONSOLE)
- #include <lib/console.h>
- static int string_tests(int argc, cmd_args *argv)
- {
- src = memalign(64, BUFFER_SIZE + 256);
- dst = memalign(64, BUFFER_SIZE + 256);
- src2 = memalign(64, BUFFER_SIZE + 256);
- dst2 = memalign(64, BUFFER_SIZE + 256);
- printf("src %p, dst %p\n", src, dst);
- printf("src2 %p, dst2 %p\n", src2, dst2);
- if (argc < 3) {
- printf("not enough arguments:\n");
- usage:
- printf("%s validate <routine>\n", argv[0].str);
- printf("%s bench <routine>\n", argv[0].str);
- goto out;
- }
- if (!strcmp(argv[1].str, "validate")) {
- if (!strcmp(argv[2].str, "memcpy")) {
- validate_memcpy();
- } else if (!strcmp(argv[2].str, "memset")) {
- validate_memset();
- } else if (!strcmp(argv[2].str, "memcpy_overlap")) {
- validate_memcpy_overlap();
- }
- } else if (!strcmp(argv[1].str, "bench")) {
- if (!strcmp(argv[2].str, "memcpy")) {
- bench_memcpy();
- } else if (!strcmp(argv[2].str, "memset")) {
- bench_memset();
- }
- } else {
- goto usage;
- }
- out:
- free(src);
- free(dst);
- free(src2);
- free(dst2);
- return 0;
- }
- STATIC_COMMAND_START
- { "string", NULL, &string_tests },
- STATIC_COMMAND_END(stringtests);
- #endif
- APP_START(stringtests)
- APP_END
|