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