(root)/
glibc-2.38/
benchtests/
bench-string.h
       1  /* Measure string and memory functions.
       2     Copyright (C) 2013-2023 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     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <getopt.h>
      20  #include <sys/cdefs.h>
      21  #include <programs/xmalloc.h>
      22  
      23  /* We are compiled under _ISOMAC, so libc-symbols.h does not do this
      24     for us.  */
      25  #include "config.h"
      26  #ifdef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL
      27  # define inhibit_loop_to_libcall \
      28      __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
      29  #else
      30  # define inhibit_loop_to_libcall
      31  #endif
      32  
      33  typedef struct
      34  {
      35    const char *name;
      36    void (*fn) (void);
      37    long test;
      38  } impl_t;
      39  extern impl_t __start_impls[], __stop_impls[];
      40  
      41  #define IMPL(name, test) \
      42    impl_t tst_ ## name							\
      43    __attribute__ ((section ("impls"), aligned (sizeof (void *))))	\
      44         = { __STRING (name), (void (*) (void))name, test };
      45  
      46  #ifdef TEST_MAIN
      47  
      48  # ifndef _GNU_SOURCE
      49  #  define _GNU_SOURCE
      50  # endif
      51  
      52  # undef __USE_STRING_INLINES
      53  
      54  # include <stdio.h>
      55  # include <stdlib.h>
      56  # include <string.h>
      57  # include <sys/mman.h>
      58  # include <sys/param.h>
      59  # include <unistd.h>
      60  # include <fcntl.h>
      61  # include <error.h>
      62  # include <errno.h>
      63  # include <time.h>
      64  # include <ifunc-impl-list.h>
      65  # define GL(x) _##x
      66  # define GLRO(x) _##x
      67  # include "bench-timing.h"
      68  
      69  # ifndef WIDE
      70  #  define CHAR char
      71  #  define UCHAR unsigned char
      72  #  define CHARBYTES 1
      73  #  define MAX_CHAR CHAR_MAX
      74  #  define MEMCHR memchr
      75  #  define MEMCMP memcmp
      76  #  define MEMCPY memcpy
      77  #  define MEMSET memset
      78  #  define STRCAT strcat
      79  #  define STRLEN strlen
      80  #  define STRCMP strcmp
      81  #  define STRCHR strchr
      82  #  define STRCPY strcpy
      83  #  define STRNLEN strnlen
      84  #  define STRCSPN strcspn
      85  #  define STRNCAT strncat
      86  #  define STRNCMP strncmp
      87  #  define STRNCPY strncpy
      88  #  define STRPBRK strpbrk
      89  #  define STRRCHR strrchr
      90  #  define STRSPN strspn
      91  #  define STPCPY stpcpy
      92  #  define STPNCPY stpncpy
      93  # else
      94  #  include <wchar.h>
      95  #  define CHAR wchar_t
      96  #  define UCHAR wchar_t
      97  #  define CHARBYTES 4
      98  #  define MAX_CHAR WCHAR_MAX
      99  #  define MEMCHR wmemchr
     100  #  define MEMCMP wmemcmp
     101  #  define MEMCPY wmemcpy
     102  #  define MEMSET wmemset
     103  #  define STRCAT wcscat
     104  #  define STRLEN wcslen
     105  #  define STRCMP wcscmp
     106  #  define STRCHR wcschr
     107  #  define STRCPY wcscpy
     108  #  define STRNLEN wcsnlen
     109  #  define STRCSPN wcscspn
     110  #  define STRNCAT wcsncat
     111  #  define STRNCMP wcsncmp
     112  #  define STRNCPY wcsncpy
     113  #  define STRPBRK wcspbrk
     114  #  define STRRCHR wcsrchr
     115  #  define STRSPN wcsspn
     116  #  define STPCPY wcpcpy
     117  #  define STPNCPY wcpncpy
     118  # endif /* WIDE */
     119  
     120  # define TEST_FUNCTION test_main
     121  # ifndef TIMEOUT
     122  #  define TIMEOUT (4 * 60)
     123  # endif
     124  # define OPT_ITERATIONS 10000
     125  # define OPT_RANDOM 10001
     126  # define OPT_SEED 10002
     127  
     128  # define INNER_LOOP_ITERS 8192
     129  # define INNER_LOOP_ITERS8 32768
     130  # define INNER_LOOP_ITERS_LARGE 131072
     131  # define INNER_LOOP_ITERS_MEDIUM 2048
     132  # define INNER_LOOP_ITERS_SMALL 256
     133  
     134  int ret, do_srandom;
     135  unsigned int seed;
     136  
     137  # ifndef ITERATIONS
     138  size_t iterations = 100000;
     139  #  define ITERATIONS_OPTIONS \
     140       { "iterations", required_argument, NULL, OPT_ITERATIONS },
     141  #  define ITERATIONS_PROCESS \
     142       case OPT_ITERATIONS:						      \
     143         iterations = strtoul (optarg, NULL, 0);				      \
     144         break;
     145  #  define ITERATIONS iterations
     146  # else
     147  #  define ITERATIONS_OPTIONS
     148  #  define ITERATIONS_PROCESS
     149  # endif
     150  
     151  # define CMDLINE_OPTIONS ITERATIONS_OPTIONS \
     152      { "random", no_argument, NULL, OPT_RANDOM },			      \
     153      { "seed", required_argument, NULL, OPT_SEED },
     154  
     155  static void __attribute__ ((used))
     156  cmdline_process_function (int c)
     157  {
     158    switch (c)
     159      {
     160        ITERATIONS_PROCESS
     161        case OPT_RANDOM:
     162  	{
     163  	  int fdr = open ("/dev/urandom", O_RDONLY);
     164  	  if (fdr < 0 || read (fdr, &seed, sizeof (seed)) != sizeof (seed))
     165  	    seed = time (NULL);
     166  	  if (fdr >= 0)
     167  	    close (fdr);
     168  	  do_srandom = 1;
     169  	  break;
     170  	}
     171  
     172        case OPT_SEED:
     173  	seed = strtoul (optarg, NULL, 0);
     174  	do_srandom = 1;
     175        break;
     176      }
     177  }
     178  # define CMDLINE_PROCESS cmdline_process_function
     179  # define CALL(impl, ...)	\
     180      (* (proto_t) (impl)->fn) (__VA_ARGS__)
     181  
     182  # ifdef TEST_NAME
     183  /* Increase size of FUNC_LIST if assert is triggered at run-time.  */
     184  static struct libc_ifunc_impl func_list[32];
     185  static int func_count;
     186  static int impl_count = -1;
     187  static impl_t *impl_array;
     188  
     189  #  define FOR_EACH_IMPL(impl, notall) \
     190       impl_t *impl;							      \
     191       int count;								      \
     192       if (impl_count == -1)						      \
     193         {								      \
     194  	 impl_count = 0;						      \
     195  	 if (func_count != 0)						      \
     196  	   {								      \
     197  	     int f;							      \
     198  	     impl_t *skip = NULL, *a;					      \
     199  	     for (impl = __start_impls; impl < __stop_impls; ++impl)	      \
     200  	       if (strcmp (impl->name, TEST_NAME) == 0)			      \
     201  		 skip = impl;						      \
     202  	       else							      \
     203  		 impl_count++;						      \
     204  	     a = impl_array = xmalloc ((impl_count + func_count) *	      \
     205  				       sizeof (impl_t));		      \
     206  	     for (impl = __start_impls; impl < __stop_impls; ++impl)	      \
     207  	       if (impl != skip)					      \
     208  		 *a++ = *impl;						      \
     209  	     for (f = 0; f < func_count; f++)				      \
     210  	       if (func_list[f].usable)					      \
     211  		 {							      \
     212  		   a->name = func_list[f].name;				      \
     213  		   a->fn = func_list[f].fn;				      \
     214  		   a->test = 1;						      \
     215  		   a++;							      \
     216  		 }							      \
     217  	     impl_count = a - impl_array;				      \
     218  	   }								      \
     219  	 else								      \
     220  	   {								      \
     221  	     impl_count = __stop_impls - __start_impls;			      \
     222  	     impl_array = __start_impls;				      \
     223  	   }								      \
     224         }								      \
     225       impl = impl_array;							      \
     226       for (count = 0; count < impl_count; ++count, ++impl)		      \
     227         if (!notall || impl->test)
     228  # else /* !TEST_NAME */
     229  #  define FOR_EACH_IMPL(impl, notall) \
     230       for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl)	      \
     231         if (!notall || impl->test)
     232  # endif /* !TEST_NAME */
     233  
     234  # ifndef BUF1PAGES
     235  #  define BUF1PAGES 1
     236  # endif
     237  
     238  unsigned char *buf1, *buf2;
     239  static size_t buf1_size, buf2_size, page_size;
     240  
     241  static void
     242  init_sizes (void)
     243  {
     244    page_size = 2 * getpagesize ();
     245  # ifdef MIN_PAGE_SIZE
     246    if (page_size < MIN_PAGE_SIZE)
     247      page_size = MIN_PAGE_SIZE;
     248  # endif
     249  
     250    buf1_size = BUF1PAGES * page_size;
     251    buf2_size = page_size;
     252  }
     253  
     254  static void
     255  exit_error (const char *id, const char *func)
     256  {
     257    error (EXIT_FAILURE, errno, "%s: %s failed", id, func);
     258  }
     259  
     260  /* Allocate a buffer of size SIZE with a guard page at the end.  */
     261  static void
     262  alloc_buf (const char *id, size_t size, unsigned char **retbuf)
     263  {
     264    size_t alloc_size = size + page_size;
     265  
     266    if (*retbuf != NULL)
     267      {
     268  	int ret = munmap (*retbuf, alloc_size);
     269  	if (ret != 0)
     270  	  exit_error (id, "munmap");
     271      }
     272  
     273    unsigned char *buf = mmap (0, alloc_size, PROT_READ | PROT_WRITE,
     274  			     MAP_PRIVATE | MAP_ANON, -1, 0);
     275  
     276    if (buf == MAP_FAILED)
     277      exit_error (id, "mmap");
     278    if (mprotect (buf + size, page_size, PROT_NONE))
     279      exit_error (id, "mprotect");
     280  
     281    *retbuf = buf;
     282  }
     283  
     284  static void
     285  alloc_bufs (void)
     286  {
     287    alloc_buf ("buf1", buf1_size, &buf1);
     288    alloc_buf ("buf2", buf2_size, &buf2);
     289  }
     290  
     291  static void
     292  test_init (void)
     293  {
     294  # ifdef TEST_NAME
     295    func_count = __libc_ifunc_impl_list (TEST_NAME, func_list,
     296  				       (sizeof func_list
     297  					/ sizeof func_list[0]));
     298  # endif
     299  
     300    init_sizes ();
     301    alloc_bufs ();
     302  
     303    if (do_srandom)
     304      {
     305        printf ("Setting seed to 0x%x\n", seed);
     306        srandom (seed);
     307      }
     308  }
     309  
     310  #endif /* TEST_MAIN */