xref: /aosp_15_r20/external/ltp/utils/benchmark/ebizzy-0.3/ebizzy.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  * Ebizzy - replicate a large ebusiness type of workload.
3*49cdfc7eSAndroid Build Coastguard Worker  *
4*49cdfc7eSAndroid Build Coastguard Worker  * Written by Valerie Henson <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * Copyright 2006 - 2007 Intel Corporation
7*49cdfc7eSAndroid Build Coastguard Worker  * Copyright 2007 Valerie Henson <[email protected]>
8*49cdfc7eSAndroid Build Coastguard Worker  *
9*49cdfc7eSAndroid Build Coastguard Worker  * Rodrigo Rubira Branco <[email protected]> - HP/BSD/Solaris port and some
10*49cdfc7eSAndroid Build Coastguard Worker  *  						 new features
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
13*49cdfc7eSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
14*49cdfc7eSAndroid Build Coastguard Worker  * the Free Software Foundation; version 2 of the License.
15*49cdfc7eSAndroid Build Coastguard Worker  *
16*49cdfc7eSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
17*49cdfc7eSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18*49cdfc7eSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19*49cdfc7eSAndroid Build Coastguard Worker  * GNU General Public License for more details.
20*49cdfc7eSAndroid Build Coastguard Worker  *
21*49cdfc7eSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
22*49cdfc7eSAndroid Build Coastguard Worker  * along with this program; if not, write to the Free Software
23*49cdfc7eSAndroid Build Coastguard Worker  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
24*49cdfc7eSAndroid Build Coastguard Worker  * USA
25*49cdfc7eSAndroid Build Coastguard Worker  *
26*49cdfc7eSAndroid Build Coastguard Worker  */
27*49cdfc7eSAndroid Build Coastguard Worker 
28*49cdfc7eSAndroid Build Coastguard Worker /*
29*49cdfc7eSAndroid Build Coastguard Worker  * This program is designed to replicate a common web search app
30*49cdfc7eSAndroid Build Coastguard Worker  * workload.  A lot of search applications have the basic pattern: Get
31*49cdfc7eSAndroid Build Coastguard Worker  * a request to find a certain record, index into the chunk of memory
32*49cdfc7eSAndroid Build Coastguard Worker  * that contains it, copy it into another chunk, then look it up via
33*49cdfc7eSAndroid Build Coastguard Worker  * binary search.  The interesting parts of this workload are:
34*49cdfc7eSAndroid Build Coastguard Worker  *
35*49cdfc7eSAndroid Build Coastguard Worker  * Large working set
36*49cdfc7eSAndroid Build Coastguard Worker  * Data alloc/copy/free cycle
37*49cdfc7eSAndroid Build Coastguard Worker  * Unpredictable data access patterns
38*49cdfc7eSAndroid Build Coastguard Worker  *
39*49cdfc7eSAndroid Build Coastguard Worker  * Fiddle with the command line options until you get something
40*49cdfc7eSAndroid Build Coastguard Worker  * resembling the kind of workload you want to investigate.
41*49cdfc7eSAndroid Build Coastguard Worker  *
42*49cdfc7eSAndroid Build Coastguard Worker  */
43*49cdfc7eSAndroid Build Coastguard Worker 
44*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
45*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
46*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
47*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
48*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
49*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
50*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
51*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
52*49cdfc7eSAndroid Build Coastguard Worker #include <sys/resource.h>
53*49cdfc7eSAndroid Build Coastguard Worker #include <stdint.h>
54*49cdfc7eSAndroid Build Coastguard Worker 
55*49cdfc7eSAndroid Build Coastguard Worker #include "ebizzy.h"
56*49cdfc7eSAndroid Build Coastguard Worker 
57*49cdfc7eSAndroid Build Coastguard Worker /*
58*49cdfc7eSAndroid Build Coastguard Worker  * Command line options
59*49cdfc7eSAndroid Build Coastguard Worker  */
60*49cdfc7eSAndroid Build Coastguard Worker 
61*49cdfc7eSAndroid Build Coastguard Worker static unsigned int always_mmap;
62*49cdfc7eSAndroid Build Coastguard Worker static unsigned int never_mmap;
63*49cdfc7eSAndroid Build Coastguard Worker static unsigned int chunks;
64*49cdfc7eSAndroid Build Coastguard Worker static unsigned int use_permissions;
65*49cdfc7eSAndroid Build Coastguard Worker static unsigned int use_holes;
66*49cdfc7eSAndroid Build Coastguard Worker static unsigned int random_size;
67*49cdfc7eSAndroid Build Coastguard Worker static unsigned int chunk_size;
68*49cdfc7eSAndroid Build Coastguard Worker static unsigned int seconds;
69*49cdfc7eSAndroid Build Coastguard Worker static unsigned int threads;
70*49cdfc7eSAndroid Build Coastguard Worker static unsigned int verbose;
71*49cdfc7eSAndroid Build Coastguard Worker static unsigned int linear;
72*49cdfc7eSAndroid Build Coastguard Worker static unsigned int touch_pages;
73*49cdfc7eSAndroid Build Coastguard Worker static unsigned int no_lib_memcpy;
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker /*
76*49cdfc7eSAndroid Build Coastguard Worker  * Other global variables
77*49cdfc7eSAndroid Build Coastguard Worker  */
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker typedef size_t record_t;
80*49cdfc7eSAndroid Build Coastguard Worker static unsigned int record_size = sizeof(record_t);
81*49cdfc7eSAndroid Build Coastguard Worker static char *cmd;
82*49cdfc7eSAndroid Build Coastguard Worker static record_t **mem;
83*49cdfc7eSAndroid Build Coastguard Worker static char **hole_mem;
84*49cdfc7eSAndroid Build Coastguard Worker static unsigned int page_size;
85*49cdfc7eSAndroid Build Coastguard Worker static time_t start_time;
86*49cdfc7eSAndroid Build Coastguard Worker static volatile int threads_go;
87*49cdfc7eSAndroid Build Coastguard Worker 
usage(void)88*49cdfc7eSAndroid Build Coastguard Worker static void usage(void)
89*49cdfc7eSAndroid Build Coastguard Worker {
90*49cdfc7eSAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: %s [options]\n"
91*49cdfc7eSAndroid Build Coastguard Worker 		"-T\t\t Just 'touch' the allocated pages\n"
92*49cdfc7eSAndroid Build Coastguard Worker 		"-l\t\t Don't use library memcpy\n"
93*49cdfc7eSAndroid Build Coastguard Worker 		"-m\t\t Always use mmap instead of malloc\n"
94*49cdfc7eSAndroid Build Coastguard Worker 		"-M\t\t Never use mmap\n"
95*49cdfc7eSAndroid Build Coastguard Worker 		"-n <num>\t Number of memory chunks to allocate\n"
96*49cdfc7eSAndroid Build Coastguard Worker 		"-p \t\t Prevent mmap coalescing using permissions\n"
97*49cdfc7eSAndroid Build Coastguard Worker 		"-P \t\t Prevent mmap coalescing using holes\n"
98*49cdfc7eSAndroid Build Coastguard Worker 		"-R\t\t Randomize size of memory to copy and search\n"
99*49cdfc7eSAndroid Build Coastguard Worker 		"-s <size>\t Size of memory chunks, in bytes\n"
100*49cdfc7eSAndroid Build Coastguard Worker 		"-S <seconds>\t Number of seconds to run\n"
101*49cdfc7eSAndroid Build Coastguard Worker 		"-t <num>\t Number of threads (2 * number cpus by default)\n"
102*49cdfc7eSAndroid Build Coastguard Worker 		"-v[v[v]]\t Be verbose (more v's for more verbose)\n"
103*49cdfc7eSAndroid Build Coastguard Worker 		"-z\t\t Linear search instead of binary search\n", cmd);
104*49cdfc7eSAndroid Build Coastguard Worker 	exit(1);
105*49cdfc7eSAndroid Build Coastguard Worker }
106*49cdfc7eSAndroid Build Coastguard Worker 
107*49cdfc7eSAndroid Build Coastguard Worker /*
108*49cdfc7eSAndroid Build Coastguard Worker  * Read options, check them, and set some defaults.
109*49cdfc7eSAndroid Build Coastguard Worker  */
110*49cdfc7eSAndroid Build Coastguard Worker 
read_options(int argc,char * argv[])111*49cdfc7eSAndroid Build Coastguard Worker static void read_options(int argc, char *argv[])
112*49cdfc7eSAndroid Build Coastguard Worker {
113*49cdfc7eSAndroid Build Coastguard Worker 	int c;
114*49cdfc7eSAndroid Build Coastguard Worker 
115*49cdfc7eSAndroid Build Coastguard Worker 	page_size = getpagesize();
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	/*
118*49cdfc7eSAndroid Build Coastguard Worker 	 * Set some defaults.  These are currently tuned to run in a
119*49cdfc7eSAndroid Build Coastguard Worker 	 * reasonable amount of time on my laptop.
120*49cdfc7eSAndroid Build Coastguard Worker 	 *
121*49cdfc7eSAndroid Build Coastguard Worker 	 * We could set the static defaults in the declarations, but
122*49cdfc7eSAndroid Build Coastguard Worker 	 * then the defaults would be split between here and the top
123*49cdfc7eSAndroid Build Coastguard Worker 	 * of the file, which is annoying.
124*49cdfc7eSAndroid Build Coastguard Worker 	 */
125*49cdfc7eSAndroid Build Coastguard Worker 	threads = 2 * sysconf(_SC_NPROCESSORS_ONLN);
126*49cdfc7eSAndroid Build Coastguard Worker 	chunks = 10;
127*49cdfc7eSAndroid Build Coastguard Worker 	chunk_size = record_size * 64 * 1024;
128*49cdfc7eSAndroid Build Coastguard Worker 	seconds = 10;
129*49cdfc7eSAndroid Build Coastguard Worker 
130*49cdfc7eSAndroid Build Coastguard Worker 	/* On to option processing */
131*49cdfc7eSAndroid Build Coastguard Worker 
132*49cdfc7eSAndroid Build Coastguard Worker 	cmd = argv[0];
133*49cdfc7eSAndroid Build Coastguard Worker 	opterr = 1;
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker 	while ((c = getopt(argc, argv, "lmMn:pPRs:S:t:vzT")) != -1) {
136*49cdfc7eSAndroid Build Coastguard Worker 		switch (c) {
137*49cdfc7eSAndroid Build Coastguard Worker 		case 'l':
138*49cdfc7eSAndroid Build Coastguard Worker 			no_lib_memcpy = 1;
139*49cdfc7eSAndroid Build Coastguard Worker 			break;
140*49cdfc7eSAndroid Build Coastguard Worker 		case 'm':
141*49cdfc7eSAndroid Build Coastguard Worker 			always_mmap = 1;
142*49cdfc7eSAndroid Build Coastguard Worker 			break;
143*49cdfc7eSAndroid Build Coastguard Worker 		case 'M':
144*49cdfc7eSAndroid Build Coastguard Worker 			never_mmap = 1;
145*49cdfc7eSAndroid Build Coastguard Worker 			break;
146*49cdfc7eSAndroid Build Coastguard Worker 		case 'n':
147*49cdfc7eSAndroid Build Coastguard Worker 			chunks = atoi(optarg);
148*49cdfc7eSAndroid Build Coastguard Worker 			if (chunks == 0)
149*49cdfc7eSAndroid Build Coastguard Worker 				usage();
150*49cdfc7eSAndroid Build Coastguard Worker 			break;
151*49cdfc7eSAndroid Build Coastguard Worker 		case 'p':
152*49cdfc7eSAndroid Build Coastguard Worker 			use_permissions = 1;
153*49cdfc7eSAndroid Build Coastguard Worker 			break;
154*49cdfc7eSAndroid Build Coastguard Worker 		case 'P':
155*49cdfc7eSAndroid Build Coastguard Worker 			use_holes = 1;
156*49cdfc7eSAndroid Build Coastguard Worker 			break;
157*49cdfc7eSAndroid Build Coastguard Worker 		case 'R':
158*49cdfc7eSAndroid Build Coastguard Worker 			random_size = 1;
159*49cdfc7eSAndroid Build Coastguard Worker 			break;
160*49cdfc7eSAndroid Build Coastguard Worker 		case 's':
161*49cdfc7eSAndroid Build Coastguard Worker 			chunk_size = atoi(optarg);
162*49cdfc7eSAndroid Build Coastguard Worker 			if (chunk_size == 0)
163*49cdfc7eSAndroid Build Coastguard Worker 				usage();
164*49cdfc7eSAndroid Build Coastguard Worker 			break;
165*49cdfc7eSAndroid Build Coastguard Worker 		case 'S':
166*49cdfc7eSAndroid Build Coastguard Worker 			seconds = atoi(optarg);
167*49cdfc7eSAndroid Build Coastguard Worker 			if (seconds == 0)
168*49cdfc7eSAndroid Build Coastguard Worker 				usage();
169*49cdfc7eSAndroid Build Coastguard Worker 			break;
170*49cdfc7eSAndroid Build Coastguard Worker 		case 't':
171*49cdfc7eSAndroid Build Coastguard Worker 			threads = atoi(optarg);
172*49cdfc7eSAndroid Build Coastguard Worker 			if (threads == 0)
173*49cdfc7eSAndroid Build Coastguard Worker 				usage();
174*49cdfc7eSAndroid Build Coastguard Worker 			break;
175*49cdfc7eSAndroid Build Coastguard Worker 		case 'T':
176*49cdfc7eSAndroid Build Coastguard Worker 			touch_pages = 1;
177*49cdfc7eSAndroid Build Coastguard Worker 			break;
178*49cdfc7eSAndroid Build Coastguard Worker 		case 'v':
179*49cdfc7eSAndroid Build Coastguard Worker 			verbose++;
180*49cdfc7eSAndroid Build Coastguard Worker 			break;
181*49cdfc7eSAndroid Build Coastguard Worker 		case 'z':
182*49cdfc7eSAndroid Build Coastguard Worker 			linear = 1;
183*49cdfc7eSAndroid Build Coastguard Worker 			break;
184*49cdfc7eSAndroid Build Coastguard Worker 		default:
185*49cdfc7eSAndroid Build Coastguard Worker 			usage();
186*49cdfc7eSAndroid Build Coastguard Worker 		}
187*49cdfc7eSAndroid Build Coastguard Worker 	}
188*49cdfc7eSAndroid Build Coastguard Worker 
189*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
190*49cdfc7eSAndroid Build Coastguard Worker 		printf("ebizzy 0.2\n"
191*49cdfc7eSAndroid Build Coastguard Worker 		       "(C) 2006-7 Intel Corporation\n"
192*49cdfc7eSAndroid Build Coastguard Worker 		       "(C) 2007 Valerie Henson <[email protected]>\n");
193*49cdfc7eSAndroid Build Coastguard Worker 
194*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose) {
195*49cdfc7eSAndroid Build Coastguard Worker 		printf("always_mmap %u\n", always_mmap);
196*49cdfc7eSAndroid Build Coastguard Worker 		printf("never_mmap %u\n", never_mmap);
197*49cdfc7eSAndroid Build Coastguard Worker 		printf("chunks %u\n", chunks);
198*49cdfc7eSAndroid Build Coastguard Worker 		printf("prevent coalescing using permissions %u\n",
199*49cdfc7eSAndroid Build Coastguard Worker 		       use_permissions);
200*49cdfc7eSAndroid Build Coastguard Worker 		printf("prevent coalescing using holes %u\n", use_holes);
201*49cdfc7eSAndroid Build Coastguard Worker 		printf("random_size %u\n", random_size);
202*49cdfc7eSAndroid Build Coastguard Worker 		printf("chunk_size %u\n", chunk_size);
203*49cdfc7eSAndroid Build Coastguard Worker 		printf("seconds %d\n", seconds);
204*49cdfc7eSAndroid Build Coastguard Worker 		printf("threads %u\n", threads);
205*49cdfc7eSAndroid Build Coastguard Worker 		printf("verbose %u\n", verbose);
206*49cdfc7eSAndroid Build Coastguard Worker 		printf("linear %u\n", linear);
207*49cdfc7eSAndroid Build Coastguard Worker 		printf("touch_pages %u\n", touch_pages);
208*49cdfc7eSAndroid Build Coastguard Worker 		printf("page size %d\n", page_size);
209*49cdfc7eSAndroid Build Coastguard Worker 	}
210*49cdfc7eSAndroid Build Coastguard Worker 
211*49cdfc7eSAndroid Build Coastguard Worker 	/* Check for incompatible options */
212*49cdfc7eSAndroid Build Coastguard Worker 
213*49cdfc7eSAndroid Build Coastguard Worker 	if (always_mmap && never_mmap) {
214*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Both -m \"always mmap\" and -M "
215*49cdfc7eSAndroid Build Coastguard Worker 			"\"never mmap\" option specified\n");
216*49cdfc7eSAndroid Build Coastguard Worker 		usage();
217*49cdfc7eSAndroid Build Coastguard Worker 	}
218*49cdfc7eSAndroid Build Coastguard Worker #ifdef __GLIBC__
219*49cdfc7eSAndroid Build Coastguard Worker 	if (never_mmap)
220*49cdfc7eSAndroid Build Coastguard Worker 		mallopt(M_MMAP_MAX, 0);
221*49cdfc7eSAndroid Build Coastguard Worker #endif
222*49cdfc7eSAndroid Build Coastguard Worker 	if (chunk_size < record_size) {
223*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Chunk size %u smaller than record size %u\n",
224*49cdfc7eSAndroid Build Coastguard Worker 			chunk_size, record_size);
225*49cdfc7eSAndroid Build Coastguard Worker 		usage();
226*49cdfc7eSAndroid Build Coastguard Worker 	}
227*49cdfc7eSAndroid Build Coastguard Worker }
228*49cdfc7eSAndroid Build Coastguard Worker 
touch_mem(char * dest,size_t size)229*49cdfc7eSAndroid Build Coastguard Worker static void touch_mem(char *dest, size_t size)
230*49cdfc7eSAndroid Build Coastguard Worker {
231*49cdfc7eSAndroid Build Coastguard Worker 	int i;
232*49cdfc7eSAndroid Build Coastguard Worker 	if (touch_pages) {
233*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < (long)size; i += page_size)
234*49cdfc7eSAndroid Build Coastguard Worker 			*(dest + i) = 0xff;
235*49cdfc7eSAndroid Build Coastguard Worker 	}
236*49cdfc7eSAndroid Build Coastguard Worker }
237*49cdfc7eSAndroid Build Coastguard Worker 
alloc_mem(size_t size)238*49cdfc7eSAndroid Build Coastguard Worker static void *alloc_mem(size_t size)
239*49cdfc7eSAndroid Build Coastguard Worker {
240*49cdfc7eSAndroid Build Coastguard Worker 	char *p;
241*49cdfc7eSAndroid Build Coastguard Worker 	int err = 0;
242*49cdfc7eSAndroid Build Coastguard Worker 
243*49cdfc7eSAndroid Build Coastguard Worker 	if (always_mmap) {
244*49cdfc7eSAndroid Build Coastguard Worker 		p = mmap(NULL, size, (PROT_READ | PROT_WRITE),
245*49cdfc7eSAndroid Build Coastguard Worker 			 (MAP_PRIVATE | MAP_ANONYMOUS), -1, 0);
246*49cdfc7eSAndroid Build Coastguard Worker 		if (p == MAP_FAILED)
247*49cdfc7eSAndroid Build Coastguard Worker 			err = 1;
248*49cdfc7eSAndroid Build Coastguard Worker 	} else {
249*49cdfc7eSAndroid Build Coastguard Worker 		p = malloc(size);
250*49cdfc7eSAndroid Build Coastguard Worker 		if (p == NULL)
251*49cdfc7eSAndroid Build Coastguard Worker 			err = 1;
252*49cdfc7eSAndroid Build Coastguard Worker 	}
253*49cdfc7eSAndroid Build Coastguard Worker 
254*49cdfc7eSAndroid Build Coastguard Worker 	if (err) {
255*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Couldn't allocate %zu bytes, try smaller "
256*49cdfc7eSAndroid Build Coastguard Worker 			"chunks or size options\n"
257*49cdfc7eSAndroid Build Coastguard Worker 			"Using -n %u chunks and -s %u size\n",
258*49cdfc7eSAndroid Build Coastguard Worker 			size, chunks, chunk_size);
259*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
260*49cdfc7eSAndroid Build Coastguard Worker 	}
261*49cdfc7eSAndroid Build Coastguard Worker 
262*49cdfc7eSAndroid Build Coastguard Worker 	return (p);
263*49cdfc7eSAndroid Build Coastguard Worker }
264*49cdfc7eSAndroid Build Coastguard Worker 
free_mem(void * p,size_t size)265*49cdfc7eSAndroid Build Coastguard Worker static void free_mem(void *p, size_t size)
266*49cdfc7eSAndroid Build Coastguard Worker {
267*49cdfc7eSAndroid Build Coastguard Worker 	if (always_mmap)
268*49cdfc7eSAndroid Build Coastguard Worker 		munmap(p, size);
269*49cdfc7eSAndroid Build Coastguard Worker 	else
270*49cdfc7eSAndroid Build Coastguard Worker 		free(p);
271*49cdfc7eSAndroid Build Coastguard Worker }
272*49cdfc7eSAndroid Build Coastguard Worker 
273*49cdfc7eSAndroid Build Coastguard Worker /*
274*49cdfc7eSAndroid Build Coastguard Worker  * Factor out differences in memcpy implementation by optionally using
275*49cdfc7eSAndroid Build Coastguard Worker  * our own simple memcpy implementation.
276*49cdfc7eSAndroid Build Coastguard Worker  */
277*49cdfc7eSAndroid Build Coastguard Worker 
my_memcpy(void * dest,void * src,size_t len)278*49cdfc7eSAndroid Build Coastguard Worker static void my_memcpy(void *dest, void *src, size_t len)
279*49cdfc7eSAndroid Build Coastguard Worker {
280*49cdfc7eSAndroid Build Coastguard Worker 	char *d = (char *)dest;
281*49cdfc7eSAndroid Build Coastguard Worker 	char *s = (char *)src;
282*49cdfc7eSAndroid Build Coastguard Worker 	int i;
283*49cdfc7eSAndroid Build Coastguard Worker 
284*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < (long)len; i++)
285*49cdfc7eSAndroid Build Coastguard Worker 		d[i] = s[i];
286*49cdfc7eSAndroid Build Coastguard Worker 	return;
287*49cdfc7eSAndroid Build Coastguard Worker }
288*49cdfc7eSAndroid Build Coastguard Worker 
allocate(void)289*49cdfc7eSAndroid Build Coastguard Worker static void allocate(void)
290*49cdfc7eSAndroid Build Coastguard Worker {
291*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i;
292*49cdfc7eSAndroid Build Coastguard Worker 
293*49cdfc7eSAndroid Build Coastguard Worker 	mem = alloc_mem(chunks * sizeof(record_t *));
294*49cdfc7eSAndroid Build Coastguard Worker 
295*49cdfc7eSAndroid Build Coastguard Worker 	if (use_holes)
296*49cdfc7eSAndroid Build Coastguard Worker 		hole_mem = alloc_mem(chunks * sizeof(record_t *));
297*49cdfc7eSAndroid Build Coastguard Worker 
298*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < chunks; i++) {
299*49cdfc7eSAndroid Build Coastguard Worker 		mem[i] = (record_t *) alloc_mem(chunk_size);
300*49cdfc7eSAndroid Build Coastguard Worker 		/* Prevent coalescing using holes */
301*49cdfc7eSAndroid Build Coastguard Worker 		if (use_holes)
302*49cdfc7eSAndroid Build Coastguard Worker 			hole_mem[i] = alloc_mem(page_size);
303*49cdfc7eSAndroid Build Coastguard Worker 	}
304*49cdfc7eSAndroid Build Coastguard Worker 
305*49cdfc7eSAndroid Build Coastguard Worker 	/* Free hole memory */
306*49cdfc7eSAndroid Build Coastguard Worker 	if (use_holes)
307*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < chunks; i++)
308*49cdfc7eSAndroid Build Coastguard Worker 			free_mem(hole_mem[i], page_size);
309*49cdfc7eSAndroid Build Coastguard Worker 
310*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
311*49cdfc7eSAndroid Build Coastguard Worker 		printf("Allocated memory\n");
312*49cdfc7eSAndroid Build Coastguard Worker }
313*49cdfc7eSAndroid Build Coastguard Worker 
write_pattern(void)314*49cdfc7eSAndroid Build Coastguard Worker static void write_pattern(void)
315*49cdfc7eSAndroid Build Coastguard Worker {
316*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i, j;
317*49cdfc7eSAndroid Build Coastguard Worker 
318*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < chunks; i++) {
319*49cdfc7eSAndroid Build Coastguard Worker 		for (j = 0; j < chunk_size / record_size; j++)
320*49cdfc7eSAndroid Build Coastguard Worker 			mem[i][j] = (record_t) j;
321*49cdfc7eSAndroid Build Coastguard Worker 		/* Prevent coalescing by alternating permissions */
322*49cdfc7eSAndroid Build Coastguard Worker 		if (use_permissions && (i % 2) == 0)
323*49cdfc7eSAndroid Build Coastguard Worker 			mprotect((void *)mem[i], chunk_size, PROT_READ);
324*49cdfc7eSAndroid Build Coastguard Worker 	}
325*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
326*49cdfc7eSAndroid Build Coastguard Worker 		printf("Wrote memory\n");
327*49cdfc7eSAndroid Build Coastguard Worker }
328*49cdfc7eSAndroid Build Coastguard Worker 
linear_search(record_t key,record_t * base,size_t size)329*49cdfc7eSAndroid Build Coastguard Worker static void *linear_search(record_t key, record_t * base, size_t size)
330*49cdfc7eSAndroid Build Coastguard Worker {
331*49cdfc7eSAndroid Build Coastguard Worker 	record_t *p;
332*49cdfc7eSAndroid Build Coastguard Worker 	record_t *end = base + (size / record_size);
333*49cdfc7eSAndroid Build Coastguard Worker 
334*49cdfc7eSAndroid Build Coastguard Worker 	for (p = base; p < end; p++)
335*49cdfc7eSAndroid Build Coastguard Worker 		if (*p == key)
336*49cdfc7eSAndroid Build Coastguard Worker 			return p;
337*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
338*49cdfc7eSAndroid Build Coastguard Worker }
339*49cdfc7eSAndroid Build Coastguard Worker 
compare(const void * p1,const void * p2)340*49cdfc7eSAndroid Build Coastguard Worker static int compare(const void *p1, const void *p2)
341*49cdfc7eSAndroid Build Coastguard Worker {
342*49cdfc7eSAndroid Build Coastguard Worker 	return (*(record_t *) p1 - *(record_t *) p2);
343*49cdfc7eSAndroid Build Coastguard Worker }
344*49cdfc7eSAndroid Build Coastguard Worker 
345*49cdfc7eSAndroid Build Coastguard Worker /*
346*49cdfc7eSAndroid Build Coastguard Worker  * Stupid ranged random number function.  We don't care about quality.
347*49cdfc7eSAndroid Build Coastguard Worker  *
348*49cdfc7eSAndroid Build Coastguard Worker  * Inline because it's starting to be a scaling issue.
349*49cdfc7eSAndroid Build Coastguard Worker  */
350*49cdfc7eSAndroid Build Coastguard Worker 
rand_num(unsigned int max,unsigned int * state)351*49cdfc7eSAndroid Build Coastguard Worker static inline unsigned int rand_num(unsigned int max, unsigned int *state)
352*49cdfc7eSAndroid Build Coastguard Worker {
353*49cdfc7eSAndroid Build Coastguard Worker 	*state *= 1103515245 + 12345;
354*49cdfc7eSAndroid Build Coastguard Worker 	return ((*state / 65536) % max);
355*49cdfc7eSAndroid Build Coastguard Worker }
356*49cdfc7eSAndroid Build Coastguard Worker 
357*49cdfc7eSAndroid Build Coastguard Worker /*
358*49cdfc7eSAndroid Build Coastguard Worker  * This function is the meat of the program; the rest is just support.
359*49cdfc7eSAndroid Build Coastguard Worker  *
360*49cdfc7eSAndroid Build Coastguard Worker  * In this function, we randomly select a memory chunk, copy it into a
361*49cdfc7eSAndroid Build Coastguard Worker  * newly allocated buffer, randomly select a search key, look it up,
362*49cdfc7eSAndroid Build Coastguard Worker  * then free the memory.  An option tells us to allocate and copy a
363*49cdfc7eSAndroid Build Coastguard Worker  * randomly sized chunk of the memory instead of the whole thing.
364*49cdfc7eSAndroid Build Coastguard Worker  *
365*49cdfc7eSAndroid Build Coastguard Worker  * Linear search provided for sanity checking.
366*49cdfc7eSAndroid Build Coastguard Worker  *
367*49cdfc7eSAndroid Build Coastguard Worker  */
368*49cdfc7eSAndroid Build Coastguard Worker 
search_mem(void)369*49cdfc7eSAndroid Build Coastguard Worker static uintptr_t search_mem(void)
370*49cdfc7eSAndroid Build Coastguard Worker {
371*49cdfc7eSAndroid Build Coastguard Worker 	record_t key, *found;
372*49cdfc7eSAndroid Build Coastguard Worker 	record_t *src, *copy;
373*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int chunk;
374*49cdfc7eSAndroid Build Coastguard Worker 	size_t copy_size = chunk_size;
375*49cdfc7eSAndroid Build Coastguard Worker 	uintptr_t i;
376*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int state = 0;
377*49cdfc7eSAndroid Build Coastguard Worker 
378*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; threads_go == 1; i++) {
379*49cdfc7eSAndroid Build Coastguard Worker 		chunk = rand_num(chunks, &state);
380*49cdfc7eSAndroid Build Coastguard Worker 		src = mem[chunk];
381*49cdfc7eSAndroid Build Coastguard Worker 		/*
382*49cdfc7eSAndroid Build Coastguard Worker 		 * If we're doing random sizes, we need a non-zero
383*49cdfc7eSAndroid Build Coastguard Worker 		 * multiple of record size.
384*49cdfc7eSAndroid Build Coastguard Worker 		 */
385*49cdfc7eSAndroid Build Coastguard Worker 		if (random_size)
386*49cdfc7eSAndroid Build Coastguard Worker 			copy_size = (rand_num(chunk_size / record_size, &state)
387*49cdfc7eSAndroid Build Coastguard Worker 				     + 1) * record_size;
388*49cdfc7eSAndroid Build Coastguard Worker 		copy = alloc_mem(copy_size);
389*49cdfc7eSAndroid Build Coastguard Worker 
390*49cdfc7eSAndroid Build Coastguard Worker 		if (touch_pages) {
391*49cdfc7eSAndroid Build Coastguard Worker 			touch_mem((char *)copy, copy_size);
392*49cdfc7eSAndroid Build Coastguard Worker 		} else {
393*49cdfc7eSAndroid Build Coastguard Worker 
394*49cdfc7eSAndroid Build Coastguard Worker 			if (no_lib_memcpy)
395*49cdfc7eSAndroid Build Coastguard Worker 				my_memcpy(copy, src, copy_size);
396*49cdfc7eSAndroid Build Coastguard Worker 			else
397*49cdfc7eSAndroid Build Coastguard Worker 				memcpy(copy, src, copy_size);
398*49cdfc7eSAndroid Build Coastguard Worker 
399*49cdfc7eSAndroid Build Coastguard Worker 			key = rand_num(copy_size / record_size, &state);
400*49cdfc7eSAndroid Build Coastguard Worker 
401*49cdfc7eSAndroid Build Coastguard Worker 			if (verbose > 2)
402*49cdfc7eSAndroid Build Coastguard Worker 				printf("Search key %zu, copy size %zu\n", key,
403*49cdfc7eSAndroid Build Coastguard Worker 				       copy_size);
404*49cdfc7eSAndroid Build Coastguard Worker 			if (linear)
405*49cdfc7eSAndroid Build Coastguard Worker 				found = linear_search(key, copy, copy_size);
406*49cdfc7eSAndroid Build Coastguard Worker 			else
407*49cdfc7eSAndroid Build Coastguard Worker 				found =
408*49cdfc7eSAndroid Build Coastguard Worker 				    bsearch(&key, copy, copy_size / record_size,
409*49cdfc7eSAndroid Build Coastguard Worker 					    record_size, compare);
410*49cdfc7eSAndroid Build Coastguard Worker 
411*49cdfc7eSAndroid Build Coastguard Worker 			/* Below check is mainly for memory corruption or other bug */
412*49cdfc7eSAndroid Build Coastguard Worker 			if (found == NULL) {
413*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "Couldn't find key %zd\n", key);
414*49cdfc7eSAndroid Build Coastguard Worker 				exit(1);
415*49cdfc7eSAndroid Build Coastguard Worker 			}
416*49cdfc7eSAndroid Build Coastguard Worker 		}		/* end if ! touch_pages */
417*49cdfc7eSAndroid Build Coastguard Worker 
418*49cdfc7eSAndroid Build Coastguard Worker 		free_mem(copy, copy_size);
419*49cdfc7eSAndroid Build Coastguard Worker 	}
420*49cdfc7eSAndroid Build Coastguard Worker 
421*49cdfc7eSAndroid Build Coastguard Worker 	return (i);
422*49cdfc7eSAndroid Build Coastguard Worker }
423*49cdfc7eSAndroid Build Coastguard Worker 
thread_run(void * arg)424*49cdfc7eSAndroid Build Coastguard Worker static void *thread_run(void *arg __attribute__((unused)))
425*49cdfc7eSAndroid Build Coastguard Worker {
426*49cdfc7eSAndroid Build Coastguard Worker 	uintptr_t records_thread;
427*49cdfc7eSAndroid Build Coastguard Worker 
428*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose > 1)
429*49cdfc7eSAndroid Build Coastguard Worker 		printf("Thread started\n");
430*49cdfc7eSAndroid Build Coastguard Worker 
431*49cdfc7eSAndroid Build Coastguard Worker 	/* Wait for the start signal */
432*49cdfc7eSAndroid Build Coastguard Worker 
433*49cdfc7eSAndroid Build Coastguard Worker 	while (threads_go == 0) ;
434*49cdfc7eSAndroid Build Coastguard Worker 
435*49cdfc7eSAndroid Build Coastguard Worker 	records_thread = search_mem();
436*49cdfc7eSAndroid Build Coastguard Worker 
437*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose > 1)
438*49cdfc7eSAndroid Build Coastguard Worker 		printf("Thread finished, %f seconds\n",
439*49cdfc7eSAndroid Build Coastguard Worker 		       difftime(time(NULL), start_time));
440*49cdfc7eSAndroid Build Coastguard Worker 
441*49cdfc7eSAndroid Build Coastguard Worker 	return (void *)records_thread;
442*49cdfc7eSAndroid Build Coastguard Worker }
443*49cdfc7eSAndroid Build Coastguard Worker 
difftimeval(struct timeval * end,struct timeval * start)444*49cdfc7eSAndroid Build Coastguard Worker static struct timeval difftimeval(struct timeval *end, struct timeval *start)
445*49cdfc7eSAndroid Build Coastguard Worker {
446*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval diff;
447*49cdfc7eSAndroid Build Coastguard Worker 	diff.tv_sec = end->tv_sec - start->tv_sec;
448*49cdfc7eSAndroid Build Coastguard Worker 	diff.tv_usec = end->tv_usec - start->tv_usec;
449*49cdfc7eSAndroid Build Coastguard Worker 	return diff;
450*49cdfc7eSAndroid Build Coastguard Worker }
451*49cdfc7eSAndroid Build Coastguard Worker 
start_threads(void)452*49cdfc7eSAndroid Build Coastguard Worker static void start_threads(void)
453*49cdfc7eSAndroid Build Coastguard Worker {
454*49cdfc7eSAndroid Build Coastguard Worker 	pthread_t thread_array[threads];
455*49cdfc7eSAndroid Build Coastguard Worker 	double elapsed;
456*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i;
457*49cdfc7eSAndroid Build Coastguard Worker 	struct rusage start_ru, end_ru;
458*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval usr_time, sys_time;
459*49cdfc7eSAndroid Build Coastguard Worker 	double records_per_sec = 0.0;
460*49cdfc7eSAndroid Build Coastguard Worker 	int err;
461*49cdfc7eSAndroid Build Coastguard Worker 
462*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
463*49cdfc7eSAndroid Build Coastguard Worker 		printf("Threads starting\n");
464*49cdfc7eSAndroid Build Coastguard Worker 
465*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < threads; i++) {
466*49cdfc7eSAndroid Build Coastguard Worker 		err = pthread_create(&thread_array[i], NULL, thread_run, NULL);
467*49cdfc7eSAndroid Build Coastguard Worker 		if (err) {
468*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "Error creating thread %d\n", i);
469*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
470*49cdfc7eSAndroid Build Coastguard Worker 		}
471*49cdfc7eSAndroid Build Coastguard Worker 	}
472*49cdfc7eSAndroid Build Coastguard Worker 
473*49cdfc7eSAndroid Build Coastguard Worker 	/*
474*49cdfc7eSAndroid Build Coastguard Worker 	 * Begin accounting - this is when we actually do the things
475*49cdfc7eSAndroid Build Coastguard Worker 	 * we want to measure. */
476*49cdfc7eSAndroid Build Coastguard Worker 
477*49cdfc7eSAndroid Build Coastguard Worker 	getrusage(RUSAGE_SELF, &start_ru);
478*49cdfc7eSAndroid Build Coastguard Worker 	start_time = time(NULL);
479*49cdfc7eSAndroid Build Coastguard Worker 	threads_go = 1;
480*49cdfc7eSAndroid Build Coastguard Worker 	sleep(seconds);
481*49cdfc7eSAndroid Build Coastguard Worker 	threads_go = 0;
482*49cdfc7eSAndroid Build Coastguard Worker 	elapsed = difftime(time(NULL), start_time);
483*49cdfc7eSAndroid Build Coastguard Worker 	getrusage(RUSAGE_SELF, &end_ru);
484*49cdfc7eSAndroid Build Coastguard Worker 
485*49cdfc7eSAndroid Build Coastguard Worker 	/*
486*49cdfc7eSAndroid Build Coastguard Worker 	 * The rest is just clean up.
487*49cdfc7eSAndroid Build Coastguard Worker 	 */
488*49cdfc7eSAndroid Build Coastguard Worker 
489*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < threads; i++) {
490*49cdfc7eSAndroid Build Coastguard Worker 		uintptr_t record_thread;
491*49cdfc7eSAndroid Build Coastguard Worker 		err = pthread_join(thread_array[i], (void *)&record_thread);
492*49cdfc7eSAndroid Build Coastguard Worker 		if (err) {
493*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "Error joining thread %d\n", i);
494*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
495*49cdfc7eSAndroid Build Coastguard Worker 		}
496*49cdfc7eSAndroid Build Coastguard Worker 		records_per_sec += ((double)record_thread / elapsed);
497*49cdfc7eSAndroid Build Coastguard Worker 	}
498*49cdfc7eSAndroid Build Coastguard Worker 
499*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
500*49cdfc7eSAndroid Build Coastguard Worker 		printf("Threads finished\n");
501*49cdfc7eSAndroid Build Coastguard Worker 
502*49cdfc7eSAndroid Build Coastguard Worker 	printf("%tu records/s\n", (uintptr_t) records_per_sec);
503*49cdfc7eSAndroid Build Coastguard Worker 
504*49cdfc7eSAndroid Build Coastguard Worker 	usr_time = difftimeval(&end_ru.ru_utime, &start_ru.ru_utime);
505*49cdfc7eSAndroid Build Coastguard Worker 	sys_time = difftimeval(&end_ru.ru_stime, &start_ru.ru_stime);
506*49cdfc7eSAndroid Build Coastguard Worker 
507*49cdfc7eSAndroid Build Coastguard Worker 	printf("real %5.2f s\n", elapsed);
508*49cdfc7eSAndroid Build Coastguard Worker 	printf("user %5.2f s\n", usr_time.tv_sec + usr_time.tv_usec / 1e6);
509*49cdfc7eSAndroid Build Coastguard Worker 	printf("sys  %5.2f s\n", sys_time.tv_sec + sys_time.tv_usec / 1e6);
510*49cdfc7eSAndroid Build Coastguard Worker }
511*49cdfc7eSAndroid Build Coastguard Worker 
main(int argc,char * argv[])512*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char *argv[])
513*49cdfc7eSAndroid Build Coastguard Worker {
514*49cdfc7eSAndroid Build Coastguard Worker 	read_options(argc, argv);
515*49cdfc7eSAndroid Build Coastguard Worker 
516*49cdfc7eSAndroid Build Coastguard Worker 	allocate();
517*49cdfc7eSAndroid Build Coastguard Worker 
518*49cdfc7eSAndroid Build Coastguard Worker 	write_pattern();
519*49cdfc7eSAndroid Build Coastguard Worker 
520*49cdfc7eSAndroid Build Coastguard Worker 	start_threads();
521*49cdfc7eSAndroid Build Coastguard Worker 
522*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
523*49cdfc7eSAndroid Build Coastguard Worker }
524