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 * To port to libmicro, I had to add options for
57 * some items which were just arguments before.
58 * -s is the size (more than 512)
59 * -x is the command to execute (rd wr rdwr cp fwr frd fcp bzero bcopy)
60 * see usage string for command options.
61 */
62
63#ifdef	__sun
64#pragma ident	"@(#)lmbench_bw_mem.c	1.0 20060814 Apple Inc."
65#endif
66
67
68#include <unistd.h>
69#include <stdlib.h>
70#include <stdio.h>
71#include <stdint.h>
72#include <string.h>
73
74#include "../libmicro.h"
75
76#define	TRIES		11	// value from bench.h in lmbench
77#define TYPE    	int
78
79/* Added as part of the fix for <rdar://problem/7508837> */
80static volatile u_int64_t       use_result_dummy;
81void use_int(int result) { use_result_dummy += result; }
82
83/*
84 * rd - 4 byte read, 32 byte stride
85 * wr - 4 byte write, 32 byte stride
86 * rdwr - 4 byte read followed by 4 byte write to same place, 32 byte stride
87 * cp - 4 byte read then 4 byte write to different place, 32 byte stride
88 * fwr - write every 4 byte word
89 * frd - read every 4 byte word
90 * fcp - copy every 4 byte word
91 *
92 * All tests do 512 byte chunks in a loop.
93 *
94 * XXX - do a 64bit version of this.
95 */
96void	rd(iter_t iterations, void *cookie);
97void	wr(iter_t iterations, void *cookie);
98void	rdwr(iter_t iterations, void *cookie);
99void	mcp(iter_t iterations, void *cookie);
100void	fwr(iter_t iterations, void *cookie);
101void	frd(iter_t iterations, void *cookie);
102void	fcp(iter_t iterations, void *cookie);
103void	loop_bzero(iter_t iterations, void *cookie);
104void	loop_bcopy(iter_t iterations, void *cookie);
105void	init_overhead(iter_t iterations, void *cookie);
106void	init_loop(iter_t iterations, void *cookie);
107void	cleanup(iter_t iterations, void *cookie);
108
109typedef struct _state {
110	double	overhead;
111	size_t	nbytes;
112	int	need_buf2;
113	int	aligned;
114	TYPE	*buf;
115	TYPE	*buf2;
116	TYPE	*buf2_orig;
117	TYPE	*lastone;
118	size_t	N;
119} state_t;
120
121
122/*
123 *	Your state variables should live in the tsd_t struct below
124 */
125typedef struct {
126	double	overhead;
127	size_t	nbytes;
128	int	need_buf2;
129	int	aligned;
130	TYPE	*buf;
131	TYPE	*buf2;
132	TYPE	*buf2_orig;
133	TYPE	*lastone;
134	size_t	N;
135	int	parallel;
136	int	warmup;
137	int	repetitions;
138} tsd_t;
139
140
141static int 	optp = 1;
142static int	optw = 0;
143static int	optn = TRIES;
144static int	opt_size = 0;
145static char	*opt_what;	// maximum "what" command string size
146
147void
148init_overhead(iter_t iterations, void *cookie)
149{
150}
151
152void
153init_loop(iter_t iterations, void *cookie)
154{
155	tsd_t			*ts = (tsd_t *)cookie;
156
157	if (iterations) return;
158
159    ts->buf = (TYPE *)valloc(ts->nbytes);
160	ts->buf2_orig = NULL;
161	ts->lastone = (TYPE*)ts->buf - 1;
162	ts->lastone = (TYPE*)((char *)ts->buf + ts->nbytes - 512);
163	ts->N = ts->nbytes;
164
165	if (!ts->buf) {
166		perror("malloc");
167		exit(1);
168	}
169	bzero((void*)ts->buf, ts->nbytes);
170
171	if (ts->need_buf2 == 1) {
172		ts->buf2_orig = ts->buf2 = (TYPE *)valloc(ts->nbytes + 2048);
173		if (!ts->buf2) {
174			perror("malloc");
175			exit(1);
176		}
177
178		/* default is to have stuff unaligned wrt each other */
179		/* XXX - this is not well tested or thought out */
180		if (ts->aligned) {
181			char	*tmp = (char *)ts->buf2;
182
183			tmp += 2048 - 128;
184			ts->buf2 = (TYPE *)tmp;
185		}
186	}
187}
188
189void
190cleanup(iter_t iterations, void *cookie)
191{
192	tsd_t			*ts = (tsd_t *)cookie;
193
194	if (iterations) return;
195
196	free(ts->buf);
197	if (ts->buf2_orig) free(ts->buf2_orig);
198}
199
200void
201rd(iter_t iterations, void *cookie)
202{
203	tsd_t			*ts = (tsd_t *)cookie;
204	register TYPE *lastone = ts->lastone;
205	register int sum = 0;
206
207	while (iterations-- > 0) {
208	    register TYPE *p = ts->buf;
209	    while (p <= lastone) {
210		sum +=
211#define	DOIT(i)	p[i]+
212		DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24)
213		DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52)
214		DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76)
215		DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100)
216		DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120)
217		p[124];
218		p +=  128;
219	    }
220	}
221	use_int(sum);
222}
223#undef	DOIT
224
225void
226wr(iter_t iterations, void *cookie)
227{
228	tsd_t			*ts = (tsd_t *)cookie;
229	register TYPE *lastone = ts->lastone;
230
231	while (iterations-- > 0) {
232	    register TYPE *p = ts->buf;
233	    while (p <= lastone) {
234#define	DOIT(i)	p[i] = 1;
235		DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24)
236		DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52)
237		DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76)
238		DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100)
239		DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120) DOIT(124);
240		p +=  128;
241	    }
242	}
243}
244#undef	DOIT
245
246void
247rdwr(iter_t iterations, void *cookie)
248{
249	tsd_t			*ts = (tsd_t *)cookie;
250	register TYPE *lastone = ts->lastone;
251	register int sum = 0;
252
253	while (iterations-- > 0) {
254	    register TYPE *p = ts->buf;
255	    while (p <= lastone) {
256#define	DOIT(i)	sum += p[i]; p[i] = 1;
257		DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24)
258		DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52)
259		DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76)
260		DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100)
261		DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120) DOIT(124);
262		p +=  128;
263	    }
264	}
265	use_int(sum);
266}
267#undef	DOIT
268
269void
270mcp(iter_t iterations, void *cookie)
271{
272	tsd_t			*ts = (tsd_t *)cookie;
273	register TYPE *lastone = ts->lastone;
274	TYPE* p_save = NULL;
275
276	while (iterations-- > 0) {
277	    register TYPE *p = ts->buf;
278	    register TYPE *dst = ts->buf2;
279	    while (p <= lastone) {
280#define	DOIT(i)	dst[i] = p[i];
281		DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24)
282		DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52)
283		DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76)
284		DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100)
285		DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120) DOIT(124);
286		p += 128;
287		dst += 128;
288	    }
289	    p_save = p;
290	}
291}
292#undef	DOIT
293
294void
295fwr(iter_t iterations, void *cookie)
296{
297	tsd_t			*ts = (tsd_t *)cookie;
298	register TYPE *lastone = ts->lastone;
299	TYPE* p_save = NULL;
300
301	while (iterations-- > 0) {
302	    register TYPE *p = ts->buf;
303	    while (p <= lastone) {
304#define	DOIT(i)	p[i]=
305		DOIT(0) DOIT(1) DOIT(2) DOIT(3) DOIT(4) DOIT(5) DOIT(6)
306		DOIT(7) DOIT(8) DOIT(9) DOIT(10) DOIT(11) DOIT(12)
307		DOIT(13) DOIT(14) DOIT(15) DOIT(16) DOIT(17) DOIT(18)
308		DOIT(19) DOIT(20) DOIT(21) DOIT(22) DOIT(23) DOIT(24)
309		DOIT(25) DOIT(26) DOIT(27) DOIT(28) DOIT(29) DOIT(30)
310		DOIT(31) DOIT(32) DOIT(33) DOIT(34) DOIT(35) DOIT(36)
311		DOIT(37) DOIT(38) DOIT(39) DOIT(40) DOIT(41) DOIT(42)
312		DOIT(43) DOIT(44) DOIT(45) DOIT(46) DOIT(47) DOIT(48)
313		DOIT(49) DOIT(50) DOIT(51) DOIT(52) DOIT(53) DOIT(54)
314		DOIT(55) DOIT(56) DOIT(57) DOIT(58) DOIT(59) DOIT(60)
315		DOIT(61) DOIT(62) DOIT(63) DOIT(64) DOIT(65) DOIT(66)
316		DOIT(67) DOIT(68) DOIT(69) DOIT(70) DOIT(71) DOIT(72)
317		DOIT(73) DOIT(74) DOIT(75) DOIT(76) DOIT(77) DOIT(78)
318		DOIT(79) DOIT(80) DOIT(81) DOIT(82) DOIT(83) DOIT(84)
319		DOIT(85) DOIT(86) DOIT(87) DOIT(88) DOIT(89) DOIT(90)
320		DOIT(91) DOIT(92) DOIT(93) DOIT(94) DOIT(95) DOIT(96)
321		DOIT(97) DOIT(98) DOIT(99) DOIT(100) DOIT(101) DOIT(102)
322		DOIT(103) DOIT(104) DOIT(105) DOIT(106) DOIT(107)
323		DOIT(108) DOIT(109) DOIT(110) DOIT(111) DOIT(112)
324		DOIT(113) DOIT(114) DOIT(115) DOIT(116) DOIT(117)
325		DOIT(118) DOIT(119) DOIT(120) DOIT(121) DOIT(122)
326		DOIT(123) DOIT(124) DOIT(125) DOIT(126) DOIT(127) 1;
327		p += 128;
328	    }
329	    p_save = p;
330	}
331}
332#undef	DOIT
333
334void
335frd(iter_t iterations, void *cookie)
336{
337	tsd_t			*ts = (tsd_t *)cookie;
338	register int sum = 0;
339	register TYPE *lastone = ts->lastone;
340
341	while (iterations-- > 0) {
342	    register TYPE *p = ts->buf;
343	    while (p <= lastone) {
344		sum +=
345#define	DOIT(i)	p[i]+
346		DOIT(0) DOIT(1) DOIT(2) DOIT(3) DOIT(4) DOIT(5) DOIT(6)
347		DOIT(7) DOIT(8) DOIT(9) DOIT(10) DOIT(11) DOIT(12)
348		DOIT(13) DOIT(14) DOIT(15) DOIT(16) DOIT(17) DOIT(18)
349		DOIT(19) DOIT(20) DOIT(21) DOIT(22) DOIT(23) DOIT(24)
350		DOIT(25) DOIT(26) DOIT(27) DOIT(28) DOIT(29) DOIT(30)
351		DOIT(31) DOIT(32) DOIT(33) DOIT(34) DOIT(35) DOIT(36)
352		DOIT(37) DOIT(38) DOIT(39) DOIT(40) DOIT(41) DOIT(42)
353		DOIT(43) DOIT(44) DOIT(45) DOIT(46) DOIT(47) DOIT(48)
354		DOIT(49) DOIT(50) DOIT(51) DOIT(52) DOIT(53) DOIT(54)
355		DOIT(55) DOIT(56) DOIT(57) DOIT(58) DOIT(59) DOIT(60)
356		DOIT(61) DOIT(62) DOIT(63) DOIT(64) DOIT(65) DOIT(66)
357		DOIT(67) DOIT(68) DOIT(69) DOIT(70) DOIT(71) DOIT(72)
358		DOIT(73) DOIT(74) DOIT(75) DOIT(76) DOIT(77) DOIT(78)
359		DOIT(79) DOIT(80) DOIT(81) DOIT(82) DOIT(83) DOIT(84)
360		DOIT(85) DOIT(86) DOIT(87) DOIT(88) DOIT(89) DOIT(90)
361		DOIT(91) DOIT(92) DOIT(93) DOIT(94) DOIT(95) DOIT(96)
362		DOIT(97) DOIT(98) DOIT(99) DOIT(100) DOIT(101) DOIT(102)
363		DOIT(103) DOIT(104) DOIT(105) DOIT(106) DOIT(107)
364		DOIT(108) DOIT(109) DOIT(110) DOIT(111) DOIT(112)
365		DOIT(113) DOIT(114) DOIT(115) DOIT(116) DOIT(117)
366		DOIT(118) DOIT(119) DOIT(120) DOIT(121) DOIT(122)
367		DOIT(123) DOIT(124) DOIT(125) DOIT(126) p[127];
368		p += 128;
369	    }
370	}
371	use_int(sum);
372}
373#undef	DOIT
374
375void
376fcp(iter_t iterations, void *cookie)
377{
378	tsd_t			*ts = (tsd_t *)cookie;
379	register TYPE *lastone = ts->lastone;
380
381	while (iterations-- > 0) {
382	    register TYPE *p = ts->buf;
383	    register TYPE *dst = ts->buf2;
384	    while (p <= lastone) {
385#define	DOIT(i)	dst[i]=p[i];
386		DOIT(0) DOIT(1) DOIT(2) DOIT(3) DOIT(4) DOIT(5) DOIT(6)
387		DOIT(7) DOIT(8) DOIT(9) DOIT(10) DOIT(11) DOIT(12)
388		DOIT(13) DOIT(14) DOIT(15) DOIT(16) DOIT(17) DOIT(18)
389		DOIT(19) DOIT(20) DOIT(21) DOIT(22) DOIT(23) DOIT(24)
390		DOIT(25) DOIT(26) DOIT(27) DOIT(28) DOIT(29) DOIT(30)
391		DOIT(31) DOIT(32) DOIT(33) DOIT(34) DOIT(35) DOIT(36)
392		DOIT(37) DOIT(38) DOIT(39) DOIT(40) DOIT(41) DOIT(42)
393		DOIT(43) DOIT(44) DOIT(45) DOIT(46) DOIT(47) DOIT(48)
394		DOIT(49) DOIT(50) DOIT(51) DOIT(52) DOIT(53) DOIT(54)
395		DOIT(55) DOIT(56) DOIT(57) DOIT(58) DOIT(59) DOIT(60)
396		DOIT(61) DOIT(62) DOIT(63) DOIT(64) DOIT(65) DOIT(66)
397		DOIT(67) DOIT(68) DOIT(69) DOIT(70) DOIT(71) DOIT(72)
398		DOIT(73) DOIT(74) DOIT(75) DOIT(76) DOIT(77) DOIT(78)
399		DOIT(79) DOIT(80) DOIT(81) DOIT(82) DOIT(83) DOIT(84)
400		DOIT(85) DOIT(86) DOIT(87) DOIT(88) DOIT(89) DOIT(90)
401		DOIT(91) DOIT(92) DOIT(93) DOIT(94) DOIT(95) DOIT(96)
402		DOIT(97) DOIT(98) DOIT(99) DOIT(100) DOIT(101) DOIT(102)
403		DOIT(103) DOIT(104) DOIT(105) DOIT(106) DOIT(107)
404		DOIT(108) DOIT(109) DOIT(110) DOIT(111) DOIT(112)
405		DOIT(113) DOIT(114) DOIT(115) DOIT(116) DOIT(117)
406		DOIT(118) DOIT(119) DOIT(120) DOIT(121) DOIT(122)
407		DOIT(123) DOIT(124) DOIT(125) DOIT(126) DOIT(127)
408		p += 128;
409		dst += 128;
410	    }
411	}
412}
413
414void
415loop_bzero(iter_t iterations, void *cookie)
416{
417	tsd_t			*ts = (tsd_t *)cookie;
418	register TYPE *p = ts->buf;
419	register size_t  N = ts->N;
420
421	while (iterations-- > 0) {
422		bzero(p, N);
423	}
424}
425
426void
427loop_bcopy(iter_t iterations, void *cookie)
428{
429	tsd_t			*ts = (tsd_t *)cookie;
430	register TYPE *p = ts->buf;
431	register TYPE *dst = ts->buf2;
432	register size_t  N = ts->N;
433
434	while (iterations-- > 0) {
435		bcopy(p,dst,N);
436	}
437}
438
439#pragma mark libmicro routines
440
441/*ARGSUSED*/
442int
443benchmark_initbatch(void *tsd)
444{
445	/*
446	 * initialize your state variables here second
447	 */
448	tsd_t			*ts = (tsd_t *)tsd;
449    ts->buf = (TYPE *)valloc(ts->nbytes);
450	ts->buf2_orig = NULL;
451	ts->lastone = (TYPE*)ts->buf - 1;
452	ts->lastone = (TYPE*)((char *)ts->buf + ts->nbytes - 512);
453	ts->N = ts->nbytes;
454
455	if (!ts->buf) {
456		perror("malloc");
457		exit(1);
458	}
459	bzero((void*)ts->buf, ts->nbytes);
460
461	if (ts->need_buf2 == 1) {
462		ts->buf2_orig = ts->buf2 = (TYPE *)valloc(ts->nbytes + 2048);
463		if (!ts->buf2) {
464			perror("malloc");
465			exit(1);
466		}
467
468		/* default is to have stuff unaligned wrt each other */
469		/* XXX - this is not well tested or thought out */
470		if (ts->aligned) {
471			char	*tmp = (char *)ts->buf2;
472
473			tmp += 2048 - 128;
474			ts->buf2 = (TYPE *)tmp;
475		}
476	}
477	return (0);
478}
479
480int
481benchmark_finirun()
482{
483	return (0);
484}
485
486int
487benchmark_init()
488{
489	/*
490	 *	the lm_optstr must be defined here or no options for you
491	 *
492	 * 	...and the framework will throw an error
493	 *
494	 */
495	(void) sprintf(lm_optstr, "p:w:n:s:x:");
496	/*
497	 *	working hypothesis:
498	 *
499	 * 	tsd_t is the struct that we can pass around our
500	 *	state info in
501	 *
502	 *	lm_tsdsize will allocate the space we need for this
503	 *	structure throughout the rest of the framework
504	 */
505	lm_tsdsize = sizeof (tsd_t);
506	opt_what = (char *)malloc(30);
507
508	(void) sprintf(lm_usage,
509	    "	[-p <parallelism>]\n"
510	    "	[-w <warmup>]\n"
511	    "	[-n <repetitions>]\n"
512	    "	-s <size>\n"
513	    "		<size> must be larger than 512"
514	    "	-x what\n"
515	    " 		what: rd wr rdwr cp fwr frd fcp bzero bcopy\n"
516	    "	  [conflict] -- unknown option?\n"
517	);
518	return (0);
519}
520
521int
522benchmark_fini()
523{
524	free(opt_what);
525	return (0);
526}
527
528int
529benchmark_finibatch(void *tsd)
530{
531	return (0);
532}
533
534char *
535benchmark_result()
536{
537	static char		result = '\0';
538	return (&result);
539}
540
541int
542benchmark_finiworker(void *tsd)
543{
544	tsd_t			*ts = (tsd_t *)tsd;
545	free(ts->buf);
546	if (ts->buf2_orig) free(ts->buf2_orig);
547	return (0);
548}
549
550/* return -1 to display usage (i.e. if can't parse arguments */
551int
552benchmark_optswitch(int opt, char *optarg)
553{
554
555	switch (opt) {
556		case 'p':
557			optp = sizetoint(optarg);
558			if (optp <= 0)
559				return (-1);
560			break;
561		case 'w':
562			optw = sizetoint(optarg);
563			break;
564		case 'n':
565			optn = sizetoint(optarg);
566			break;
567		case 's':
568			opt_size = sizetoint(optarg);
569			break;
570		case 'x':
571			strcpy(opt_what, optarg);
572			break;
573		default:
574			return(-1);
575			break;
576	}
577//	(void) fprintf(stderr, "optp = %i optw = %i optn = %i opt_size = %i\n",
578//						optp, optw, optn, opt_size);
579//	(void) fprintf(stderr, "opt_what = %s\n", opt_what);
580	return (0);
581}
582
583int
584benchmark_initworker(void *tsd)
585{
586	/*
587	 *	initialize your state variables here first
588	 */
589	tsd_t			*ts = (tsd_t *)tsd;
590	ts->parallel = optp;
591	ts->warmup = optw;
592	ts->repetitions = optn;
593	return (0);
594}
595
596int
597benchmark_initrun()
598{
599	return (0);
600}
601
602int
603benchmark(void *tsd, result_t *res)
604{
605	/*
606	 *	initialize your state variables here last
607	 *
608	 * 	and realize that you are paying for your initialization here
609	 *	and it is really a bad idea
610	 */
611	tsd_t			*ts = (tsd_t *)tsd;
612	size_t	nbytes;
613	int	i;
614
615	ts->overhead = 0;
616
617
618	/* should have two, possibly three [indicates align] arguments left */
619	ts->aligned = ts->need_buf2 = 0;
620
621	nbytes = ts->nbytes = opt_size;
622	if (ts->nbytes < 512) { /* this is the number of bytes in the loop */
623		return(-1);
624	}
625
626	if (STREQ(opt_what, "cp") ||
627	    STREQ(opt_what, "fcp") || STREQ(opt_what, "bcopy")) {
628		ts->need_buf2 = 1;
629	}
630
631	for (i = 0 ; i < lm_optB ; i++)
632	{
633		if (STREQ(opt_what, "rd")) {
634			rd( ts->repetitions, tsd );
635		} else if (STREQ(opt_what, "wr")) {
636			wr( ts->repetitions, tsd );
637		} else if (STREQ(opt_what, "rdwr")) {
638			rdwr( ts->repetitions, tsd );
639		} else if (STREQ(opt_what, "cp")) {
640			mcp( ts->repetitions, tsd );
641		} else if (STREQ(opt_what, "frd")) {
642			frd( ts->repetitions, tsd );
643		} else if (STREQ(opt_what, "fwr")) {
644			fwr( ts->repetitions, tsd );
645		} else if (STREQ(opt_what, "fcp")) {
646			fcp( ts->repetitions, tsd );
647		} else if (STREQ(opt_what, "bzero")) {
648			loop_bzero( ts->repetitions, tsd );
649		} else if (STREQ(opt_what, "bcopy")) {
650			loop_bcopy( ts->repetitions, tsd );
651		} else {
652			return(-1);
653		}
654	}
655	res->re_count = i;
656
657	return (0);
658}
659