1 /* Measure strcat functions.
2    Copyright (C) 2013-2022 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 #define TEST_MAIN
20 #ifndef WIDE
21 # define TEST_NAME "strcat"
22 #else
23 # define TEST_NAME "wcscat"
24 # define generic_strcat generic_wcscat
25 #endif /* WIDE */
26 #include "bench-string.h"
27 
28 #define BIG_CHAR MAX_CHAR
29 
30 #ifndef WIDE
31 # define sfmt "s"
32 # define SMALL_CHAR 127
33 #else
34 # define sfmt "ls"
35 # define SMALL_CHAR 1273
36 #endif /* WIDE */
37 
38 
39 typedef CHAR *(*proto_t) (CHAR *, const CHAR *);
40 
41 CHAR *
generic_strcat(CHAR * dst,const CHAR * src)42 generic_strcat (CHAR *dst, const CHAR *src)
43 {
44   STRCPY (dst + STRLEN (dst), src);
45   return dst;
46 }
47 
48 IMPL (STRCAT, 1)
49 IMPL (generic_strcat, 0)
50 
51 static void
do_one_test(impl_t * impl,CHAR * dst,const CHAR * src)52 do_one_test (impl_t *impl, CHAR *dst, const CHAR *src)
53 {
54   size_t k = STRLEN (dst), i, iters = INNER_LOOP_ITERS_LARGE;
55   timing_t start, stop, cur;
56 
57   if (CALL (impl, dst, src) != dst)
58     {
59       error (0, 0, "Wrong result in function %s %p %p", impl->name,
60 	     CALL (impl, dst, src), dst);
61       ret = 1;
62       return;
63     }
64 
65   if (STRCMP (dst + k, src) != 0)
66     {
67       error (0, 0, "Wrong result in function %s dst \"%" sfmt "\" src \"%" sfmt "\"",
68 	     impl->name, dst, src);
69       ret = 1;
70       return;
71     }
72 
73   TIMING_NOW (start);
74   for (i = 0; i < iters; ++i)
75     {
76       dst[k] = '\0';
77       CALL (impl, dst, src);
78     }
79   TIMING_NOW (stop);
80 
81   TIMING_DIFF (cur, start, stop);
82 
83   TIMING_PRINT_MEAN ((double) cur, (double) iters);
84 }
85 
86 static void
do_test(size_t align1,size_t align2,size_t len1,size_t len2,int max_char)87 do_test (size_t align1, size_t align2, size_t len1, size_t len2, int max_char)
88 {
89   size_t i;
90   CHAR *s1, *s2;
91 
92   align1 &= 7;
93   if ((align1 + len1) * sizeof (CHAR) >= page_size)
94     return;
95 
96   align2 &= 7;
97   if ((align2 + len1 + len2) * sizeof (CHAR) >= page_size)
98     return;
99 
100   s1 = (CHAR *) (buf1) + align1;
101   s2 = (CHAR *) (buf2) + align2;
102 
103   for (i = 0; i < len1; ++i)
104     s1[i] = 32 + 23 * i % (max_char - 32);
105   s1[len1] = '\0';
106 
107   for (i = 0; i < len2; i++)
108     s2[i] = 32 + 23 * i % (max_char - 32);
109 
110   printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len1, len2, align1, align2);
111 
112   FOR_EACH_IMPL (impl, 0)
113     {
114       s2[len2] = '\0';
115       do_one_test (impl, s2, s1);
116     }
117 
118   putchar ('\n');
119 }
120 
121 int
test_main(void)122 test_main (void)
123 {
124   size_t i;
125 
126   test_init ();
127 
128   printf ("%28s", "");
129   FOR_EACH_IMPL (impl, 0)
130     printf ("\t%s", impl->name);
131   putchar ('\n');
132 
133   for (i = 0; i < 16; ++i)
134     {
135       do_test (0, 0, i, i, SMALL_CHAR);
136       do_test (0, 0, i, i, BIG_CHAR);
137       do_test (0, i, i, i, SMALL_CHAR);
138       do_test (i, 0, i, i, BIG_CHAR);
139     }
140 
141   for (i = 1; i < 8; ++i)
142     {
143       do_test (0, 0, 8 << i, 8 << i, SMALL_CHAR);
144       do_test (8 - i, 2 * i, 8 << i, 8 << i, SMALL_CHAR);
145       do_test (0, 0, 8 << i, 2 << i, SMALL_CHAR);
146       do_test (8 - i, 2 * i, 8 << i, 2 << i, SMALL_CHAR);
147     }
148 
149   for (i = 1; i < 8; ++i)
150     {
151       do_test (i, 2 * i, 8 << i, 1, SMALL_CHAR);
152       do_test (2 * i, i, 8 << i, 1, BIG_CHAR);
153       do_test (i, i, 8 << i, 10, SMALL_CHAR);
154       do_test (i, i, 8 << i, 10, BIG_CHAR);
155     }
156 
157   return ret;
158 }
159 
160 #include <support/test-driver.c>
161