1/*
2 * Copyright (c) 2006 Apple Inc.  All Rights Reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29
30/*
31 *	Order of Execution
32 *
33 *	benchmark_init
34 *
35 *	benchmark_optswitch
36 *
37 *		benchmark_initrun
38 *
39 *			benchmark_initworker
40 *				benchmark_initbatch
41 *					benchmark
42 *				benchmark_finibatch
43 *				benchmark_initbatch
44 *					benchmark
45 *				benchmark_finibatch, etc.
46 *			benchmark_finiworker
47 *
48 *		benchmark_result
49 *
50 *		benchmark_finirun
51 *
52 *	benchmark_fini
53 */
54
55
56
57#ifdef	__sun
58#pragma ident	"@(#)lmbench_bw_file_rd.c	1.0	08/17/06 Apple Inc."
59#endif
60
61
62
63#include <unistd.h>
64#include <stdlib.h>
65#include <stdio.h>
66#include <stdbool.h>
67#include <string.h>
68// add additional headers needed here.
69#include <fcntl.h>
70
71#include "../libmicro.h"
72
73#if DEBUG
74# define debug(fmt, args...)	(void) fprintf(stderr, fmt "\n" , ##args)
75#else
76# define debug(fmt, args...)
77#endif
78
79/*
80 *	Your state variables should live in the tsd_t struct below
81 */
82typedef struct {
83	char filename[256];
84	int fd;
85	int clone;
86	bool open_read_close;
87} tsd_t;
88
89/*
90 * You can have any lower-case option you want to define.
91 * options are specified in the lm_optstr as either a
92 * single lower-case letter, or a single lower case letter
93 * with a colon after it.  In this example, you can optionally
94 * specify -c {str} -e or -t {number}
95 *    -c takes a string (quote the string if blanks)
96 *    -e is a boolean
97 *    -t takes a numeric
98 * argument.
99 */
100static char 	optf[256];
101static bool 	opti = false;	// io_only or read and i/o (default read and i/o)
102
103#define	CHK(x)		if ((int)(x) == -1) { perror(#x); exit(1); }
104#ifndef	MIN
105#define	MIN(a, b)	((a) < (b) ? (a) : (b))
106#endif
107
108#define	TYPE	int
109#define	MINSZ	(sizeof(TYPE) * 128)
110
111void	*buf;		/* do the I/O here */
112size_t	xfersize;	/* do it in units of this */
113size_t	count;		/* bytes to move (can't be modified) */
114
115/* analogous to bzero, bcopy, etc., except that it just reads
116 * data into the processor
117 */
118long
119bread(void* buf, long nbytes)
120{
121	long sum = 0;
122	register long *p, *next;
123	register char *end;
124
125	p = (long*)buf;
126	end = (char*)buf + nbytes;
127	for (next = p + 128; (void*)next <= (void*)end; p = next, next += 128) {
128		sum +=
129			p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+
130			p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+
131			p[15]+p[16]+p[17]+p[18]+p[19]+p[20]+p[21]+
132			p[22]+p[23]+p[24]+p[25]+p[26]+p[27]+p[28]+
133			p[29]+p[30]+p[31]+p[32]+p[33]+p[34]+p[35]+
134			p[36]+p[37]+p[38]+p[39]+p[40]+p[41]+p[42]+
135			p[43]+p[44]+p[45]+p[46]+p[47]+p[48]+p[49]+
136			p[50]+p[51]+p[52]+p[53]+p[54]+p[55]+p[56]+
137			p[57]+p[58]+p[59]+p[60]+p[61]+p[62]+p[63]+
138			p[64]+p[65]+p[66]+p[67]+p[68]+p[69]+p[70]+
139			p[71]+p[72]+p[73]+p[74]+p[75]+p[76]+p[77]+
140			p[78]+p[79]+p[80]+p[81]+p[82]+p[83]+p[84]+
141			p[85]+p[86]+p[87]+p[88]+p[89]+p[90]+p[91]+
142			p[92]+p[93]+p[94]+p[95]+p[96]+p[97]+p[98]+
143			p[99]+p[100]+p[101]+p[102]+p[103]+p[104]+
144			p[105]+p[106]+p[107]+p[108]+p[109]+p[110]+
145			p[111]+p[112]+p[113]+p[114]+p[115]+p[116]+
146			p[117]+p[118]+p[119]+p[120]+p[121]+p[122]+
147			p[123]+p[124]+p[125]+p[126]+p[127];
148	}
149	for (next = p + 16; (void*)next <= (void*)end; p = next, next += 16) {
150		sum +=
151			p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+
152			p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+
153			p[15];
154	}
155	for (next = p + 1; (void*)next <= (void*)end; p = next, next++) {
156		sum += *p;
157	}
158	return sum;
159}
160
161void doit(int fd)
162{
163	size_t	size, chunk;
164
165	size = count;
166	chunk = xfersize;
167	while (size >= 0) {
168		if (size < chunk) chunk = size;
169		if (read(fd, buf, MIN(size, chunk)) <= 0) {
170			break;
171		}
172		bread(buf, MIN(size, xfersize));
173		size -= chunk;
174	}
175}
176
177
178int
179benchmark_init()
180{
181	debug("benchmark_init");
182	/*
183	 *	the lm_optstr must be defined here or no options for you
184	 *
185	 * 	...and the framework will throw an error
186	 *
187	 */
188	(void) sprintf(lm_optstr, "f:i");
189	/*
190	 * 	tsd_t is the state info struct that we pass around
191	 *
192	 *	lm_tsdsize will allocate the space we need for this
193	 *	structure throughout the rest of the framework
194	 */
195	lm_tsdsize = sizeof (tsd_t);
196
197	(void) sprintf(lm_usage,
198		"		[-f filename]\n"
199		"		[-i] io_only (no open/close)\n"
200	    "notes: read and sum file via read(2) interface");
201	sprintf(optf, "/tmp/%d", (int)getpid());
202	return (0);
203}
204
205/*
206 * This is where you parse your lower-case arguments.
207 * the format was defined in the lm_optstr assignment
208 * in benchmark_init
209 */
210int
211benchmark_optswitch(int opt, char *optarg)
212{
213	debug("benchmark_optswitch");
214
215	switch (opt) {
216	case 'f':
217		strncpy(optf, optarg, 255);
218		debug("optf = %s\n", optf);
219		break;
220	case 'i':
221		opti = true;
222		debug("opti = %s\n", opte? "true": "false");
223		break;
224	default:
225		return (-1);
226	}
227	return (0);
228}
229
230int
231benchmark_initrun()
232{
233	debug("benchmark_initrun");
234	return (0);
235}
236
237int
238benchmark_initworker(void *tsd)
239{
240	/*
241	 *	initialize your state variables here first
242	 */
243	tsd_t			*ts = (tsd_t *)tsd;
244	strncpy(ts->filename, optf, 255);
245	ts->open_read_close = opti;
246	debug("benchmark_initworker: ts_once = %i\n",ts->ts_once);
247	return (0);
248}
249
250/*ARGSUSED*/
251int
252benchmark_initbatch(void *tsd)
253{
254	debug("benchmark_initbatch");
255	return (0);
256}
257
258int
259benchmark(void *tsd, result_t *res)
260{
261	/*
262	 *	try not to initialize things here.  This is the main
263	 *  loop of things to get timed.  Start a server in
264	 *  benchmark_initbatch
265	 */
266	tsd_t	*ts = (tsd_t *)tsd;
267	int		i;
268	int		fd;
269
270	debug("in to benchmark - optB = %i", lm_optB);
271	for (i = 0; i < lm_optB; i++) {
272		if (ts->open_read_close) {
273			fd = open(ts->filename, O_RDONLY);
274			doit(fd);
275			close(fd);
276		} else {
277			doit(fd);
278		}
279	}
280	res->re_count = i;
281	debug("out of benchmark - optB = %i", lm_optB);
282
283	return (0);
284}
285
286int
287benchmark_finibatch(void *tsd)
288{
289	debug("benchmark_finibatch");
290	return (0);
291}
292
293int
294benchmark_finiworker(void *tsd)
295{
296	debug("benchmark_finiworker");
297	return (0);
298}
299
300char *
301benchmark_result()
302{
303	static char		result = '\0';
304	debug("benchmark_result");
305	return (&result);
306}
307
308int
309benchmark_finirun()
310{
311	debug("benchmark_finirun");
312	return (0);
313}
314
315
316int
317benchmark_fini()
318{
319	debug("benchmark_fini");
320	return (0);
321}
322
323