| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Measure string and memory functions. | 
|  | 2 | Copyright (C) 2013-2016 Free Software Foundation, Inc. | 
|  | 3 | This file is part of the GNU C Library. | 
|  | 4 |  | 
|  | 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 |  | 
|  | 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. | 
|  | 14 |  | 
|  | 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 | <http://www.gnu.org/licenses/>.  */ | 
|  | 18 |  | 
|  | 19 | #include <sys/cdefs.h> | 
|  | 20 |  | 
|  | 21 | typedef struct | 
|  | 22 | { | 
|  | 23 | const char *name; | 
|  | 24 | void (*fn) (void); | 
|  | 25 | long test; | 
|  | 26 | } impl_t; | 
|  | 27 | extern impl_t __start_impls[], __stop_impls[]; | 
|  | 28 |  | 
|  | 29 | #define IMPL(name, test) \ | 
|  | 30 | impl_t tst_ ## name							\ | 
|  | 31 | __attribute__ ((section ("impls"), aligned (sizeof (void *))))	\ | 
|  | 32 | = { __STRING (name), (void (*) (void))name, test }; | 
|  | 33 |  | 
|  | 34 | #ifdef TEST_MAIN | 
|  | 35 |  | 
|  | 36 | # ifndef _GNU_SOURCE | 
|  | 37 | #  define _GNU_SOURCE | 
|  | 38 | # endif | 
|  | 39 |  | 
|  | 40 | # undef __USE_STRING_INLINES | 
|  | 41 |  | 
|  | 42 | # include <stdio.h> | 
|  | 43 | # include <stdlib.h> | 
|  | 44 | # include <string.h> | 
|  | 45 | # include <sys/mman.h> | 
|  | 46 | # include <sys/param.h> | 
|  | 47 | # include <unistd.h> | 
|  | 48 | # include <fcntl.h> | 
|  | 49 | # include <error.h> | 
|  | 50 | # include <errno.h> | 
|  | 51 | # include <time.h> | 
|  | 52 | # include <ifunc-impl-list.h> | 
|  | 53 | # define GL(x) _##x | 
|  | 54 | # define GLRO(x) _##x | 
|  | 55 | # include "bench-timing.h" | 
|  | 56 |  | 
|  | 57 |  | 
|  | 58 | # define TEST_FUNCTION test_main () | 
|  | 59 | # define TIMEOUT (4 * 60) | 
|  | 60 | # define OPT_ITERATIONS 10000 | 
|  | 61 | # define OPT_RANDOM 10001 | 
|  | 62 | # define OPT_SEED 10002 | 
|  | 63 |  | 
|  | 64 | # define INNER_LOOP_ITERS 64 | 
|  | 65 |  | 
|  | 66 | unsigned char *buf1, *buf2; | 
|  | 67 | int ret, do_srandom; | 
|  | 68 | unsigned int seed; | 
|  | 69 | size_t page_size; | 
|  | 70 |  | 
|  | 71 | # ifndef ITERATIONS | 
|  | 72 | size_t iterations = 100000; | 
|  | 73 | #  define ITERATIONS_OPTIONS \ | 
|  | 74 | { "iterations", required_argument, NULL, OPT_ITERATIONS }, | 
|  | 75 | #  define ITERATIONS_PROCESS \ | 
|  | 76 | case OPT_ITERATIONS:						      \ | 
|  | 77 | iterations = strtoul (optarg, NULL, 0);				      \ | 
|  | 78 | break; | 
|  | 79 | #  define ITERATIONS iterations | 
|  | 80 | # else | 
|  | 81 | #  define ITERATIONS_OPTIONS | 
|  | 82 | #  define ITERATIONS_PROCESS | 
|  | 83 | # endif | 
|  | 84 |  | 
|  | 85 | # define CMDLINE_OPTIONS ITERATIONS_OPTIONS \ | 
|  | 86 | { "random", no_argument, NULL, OPT_RANDOM },			      \ | 
|  | 87 | { "seed", required_argument, NULL, OPT_SEED }, | 
|  | 88 | # define CMDLINE_PROCESS ITERATIONS_PROCESS \ | 
|  | 89 | case OPT_RANDOM:							      \ | 
|  | 90 | {									      \ | 
|  | 91 | int fdr = open ("/dev/urandom", O_RDONLY);			      \ | 
|  | 92 | \ | 
|  | 93 | if (fdr < 0 || read (fdr, &seed, sizeof(seed)) != sizeof (seed))      \ | 
|  | 94 | seed = time (NULL);						      \ | 
|  | 95 | if (fdr >= 0)							      \ | 
|  | 96 | close (fdr);							      \ | 
|  | 97 | do_srandom = 1;							      \ | 
|  | 98 | break;								      \ | 
|  | 99 | }									      \ | 
|  | 100 | \ | 
|  | 101 | case OPT_SEED:							      \ | 
|  | 102 | seed = strtoul (optarg, NULL, 0);					      \ | 
|  | 103 | do_srandom = 1;							      \ | 
|  | 104 | break; | 
|  | 105 |  | 
|  | 106 | # define CALL(impl, ...)	\ | 
|  | 107 | (* (proto_t) (impl)->fn) (__VA_ARGS__) | 
|  | 108 |  | 
|  | 109 | # ifdef TEST_NAME | 
|  | 110 | /* Increase size of FUNC_LIST if assert is triggered at run-time.  */ | 
|  | 111 | static struct libc_ifunc_impl func_list[32]; | 
|  | 112 | static int func_count; | 
|  | 113 | static int impl_count = -1; | 
|  | 114 | static impl_t *impl_array; | 
|  | 115 |  | 
|  | 116 | #  define FOR_EACH_IMPL(impl, notall) \ | 
|  | 117 | impl_t *impl;							      \ | 
|  | 118 | int count;								      \ | 
|  | 119 | if (impl_count == -1)						      \ | 
|  | 120 | {								      \ | 
|  | 121 | impl_count = 0;						      \ | 
|  | 122 | if (func_count != 0)						      \ | 
|  | 123 | {								      \ | 
|  | 124 | int f;							      \ | 
|  | 125 | impl_t *skip = NULL, *a;					      \ | 
|  | 126 | for (impl = __start_impls; impl < __stop_impls; ++impl)	      \ | 
|  | 127 | if (strcmp (impl->name, TEST_NAME) == 0)			      \ | 
|  | 128 | skip = impl;						      \ | 
|  | 129 | else							      \ | 
|  | 130 | impl_count++;						      \ | 
|  | 131 | a = impl_array = malloc ((impl_count + func_count) *	      \ | 
|  | 132 | sizeof (impl_t));			      \ | 
|  | 133 | for (impl = __start_impls; impl < __stop_impls; ++impl)	      \ | 
|  | 134 | if (impl != skip)					      \ | 
|  | 135 | *a++ = *impl;						      \ | 
|  | 136 | for (f = 0; f < func_count; f++)				      \ | 
|  | 137 | if (func_list[f].usable)					      \ | 
|  | 138 | {							      \ | 
|  | 139 | a->name = func_list[f].name;				      \ | 
|  | 140 | a->fn = func_list[f].fn;				      \ | 
|  | 141 | a->test = 1;						      \ | 
|  | 142 | a++;							      \ | 
|  | 143 | }							      \ | 
|  | 144 | impl_count = a - impl_array;				      \ | 
|  | 145 | }								      \ | 
|  | 146 | else								      \ | 
|  | 147 | {								      \ | 
|  | 148 | impl_count = __stop_impls - __start_impls;			      \ | 
|  | 149 | impl_array = __start_impls;				      \ | 
|  | 150 | }								      \ | 
|  | 151 | }								      \ | 
|  | 152 | impl = impl_array;							      \ | 
|  | 153 | for (count = 0; count < impl_count; ++count, ++impl)		      \ | 
|  | 154 | if (!notall || impl->test) | 
|  | 155 | # else /* !TEST_NAME */ | 
|  | 156 | #  define FOR_EACH_IMPL(impl, notall) \ | 
|  | 157 | for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl)	      \ | 
|  | 158 | if (!notall || impl->test) | 
|  | 159 | # endif /* !TEST_NAME */ | 
|  | 160 |  | 
|  | 161 | # ifndef BUF1PAGES | 
|  | 162 | #  define BUF1PAGES 1 | 
|  | 163 | # endif | 
|  | 164 |  | 
|  | 165 | static void | 
|  | 166 | test_init (void) | 
|  | 167 | { | 
|  | 168 | # ifdef TEST_NAME | 
|  | 169 | func_count = __libc_ifunc_impl_list (TEST_NAME, func_list, | 
|  | 170 | (sizeof func_list | 
|  | 171 | / sizeof func_list[0])); | 
|  | 172 | # endif | 
|  | 173 |  | 
|  | 174 | page_size = 2 * getpagesize (); | 
|  | 175 | # ifdef MIN_PAGE_SIZE | 
|  | 176 | if (page_size < MIN_PAGE_SIZE) | 
|  | 177 | page_size = MIN_PAGE_SIZE; | 
|  | 178 | # endif | 
|  | 179 | buf1 = mmap (0, (BUF1PAGES + 1) * page_size, PROT_READ | PROT_WRITE, | 
|  | 180 | MAP_PRIVATE | MAP_ANON, -1, 0); | 
|  | 181 | if (buf1 == MAP_FAILED) | 
|  | 182 | error (EXIT_FAILURE, errno, "mmap failed"); | 
|  | 183 | if (mprotect (buf1 + BUF1PAGES * page_size, page_size, PROT_NONE)) | 
|  | 184 | error (EXIT_FAILURE, errno, "mprotect failed"); | 
|  | 185 | buf2 = mmap (0, 2 * page_size, PROT_READ | PROT_WRITE, | 
|  | 186 | MAP_PRIVATE | MAP_ANON, -1, 0); | 
|  | 187 | if (buf2 == MAP_FAILED) | 
|  | 188 | error (EXIT_FAILURE, errno, "mmap failed"); | 
|  | 189 | if (mprotect (buf2 + page_size, page_size, PROT_NONE)) | 
|  | 190 | error (EXIT_FAILURE, errno, "mprotect failed"); | 
|  | 191 | if (do_srandom) | 
|  | 192 | { | 
|  | 193 | printf ("Setting seed to 0x%x\n", seed); | 
|  | 194 | srandom (seed); | 
|  | 195 | } | 
|  | 196 |  | 
|  | 197 | memset (buf1, 0xa5, BUF1PAGES * page_size); | 
|  | 198 | memset (buf2, 0x5a, page_size); | 
|  | 199 | } | 
|  | 200 |  | 
|  | 201 | #endif /* TEST_MAIN */ |