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 "@(#)trivial.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 <sys/socket.h> 70#include <signal.h> 71 72#include "../libmicro.h" 73 74void writer(int controlfd, int writefd, char* buf, void* cookie); 75void touch(char *buf, int nbytes); 76 77#if DEBUG 78# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) 79#else 80# define debug(fmt, args...) 81#endif 82 83/* 84 * Your state variables should live in the tsd_t struct below 85 */ 86typedef struct { 87 int pid; 88 size_t xfer; /* bytes to read/write per "packet" */ 89 size_t bytes; /* bytes to read/write in one iteration */ 90 char *buf; /* buffer memory space */ 91 int pipes[2]; 92 int control[2]; 93 int initerr; 94 int parallel; 95 int warmup; 96 int repetitions; 97} tsd_t; 98 99size_t XFER = 10*1024*1024; 100#ifndef XFERSIZE 101#define XFERSIZE (64*1024) /* all bandwidth I/O should use this */ 102#endif 103 104/* 105 * You can have any lower-case option you want to define. 106 * options are specified in the lm_optstr as either a 107 * single lower-case letter, or a single lower case letter 108 * with a colon after it. In this example, you can optionally 109 * specify -c {str} -e or -t {number} 110 * -c takes a string (quote the string if blanks) 111 * -e is a boolean 112 * -t takes a numeric 113 * argument. 114 */ 115static int optm = XFERSIZE; 116static int opts = 10*1024*1024; 117static int optw = 0; 118 119int 120benchmark_init() 121{ 122 debug("benchmark_init\n"); 123 /* 124 * the lm_optstr must be defined here or no options for you 125 * 126 * ...and the framework will throw an error 127 * 128 */ 129 (void) sprintf(lm_optstr, "m:s:w:"); 130 /* 131 * 132 * tsd_t is the state_information struct 133 * 134 * lm_tsdsize will allocate the space we need for this 135 * structure throughout the rest of the framework 136 */ 137 lm_tsdsize = sizeof (tsd_t); 138 139 (void) sprintf(lm_usage, 140 " [-m <message size>]\n" 141 " [-s <total bytes>]\n" 142 " [-w <warmup>]\n"); 143 144 return (0); 145} 146 147/* 148 * This is where you parse your lower-case arguments. 149 * the format was defined in the lm_optstr assignment 150 * in benchmark_init 151 */ 152int 153benchmark_optswitch(int opt, char *optarg) 154{ 155 debug("benchmark_optswitch\n"); 156 157 switch (opt) { 158 case 'm': 159 optm = atoi(optarg); 160 break; 161 case 's': 162 opts = atoi(optarg); 163 break; 164 case 'w': 165 optw = atoi(optarg); 166 break; 167 default: 168 return (-1); 169 } 170 return (0); 171} 172 173int 174benchmark_initrun() 175{ 176 debug("benchmark_initrun\n"); 177 return (0); 178} 179 180int 181benchmark_initworker(void *tsd) 182{ 183 /* 184 * initialize your state variables here first 185 */ 186 tsd_t *state = (tsd_t *)tsd; 187 state->xfer = optm; 188 state->bytes = opts; 189 state->parallel = lm_optP; 190 state->warmup = optw; 191 state->repetitions = lm_optB; 192 debug("benchmark_initworker: repetitions = %i\n",state->repetitions); 193 return (0); 194} 195 196/*ARGSUSED*/ 197int 198benchmark_initbatch(void *tsd) 199{ 200 tsd_t *state = (tsd_t *)tsd; 201 202 state->buf = valloc(XFERSIZE); 203 touch(state->buf, XFERSIZE); 204 state->initerr = 0; 205 if (socketpair(AF_UNIX, SOCK_STREAM, 0, state->pipes) == -1) { 206 perror("socketpair"); 207 state->initerr = 1; 208 return(0); 209 } 210 if (pipe(state->control) == -1) { 211 perror("pipe"); 212 state->initerr = 2; 213 return(0); 214 } 215// handle_scheduler(benchmp_childid(), 0, 1); 216 switch (state->pid = fork()) { 217 case 0: 218// handle_scheduler(benchmp_childid(), 1, 1); 219 close(state->control[1]); 220 close(state->pipes[0]); 221 writer(state->control[0], state->pipes[1], state->buf, state); 222 return (0); 223 /*NOTREACHED*/ 224 225 case -1: 226 perror("fork"); 227 state->initerr = 3; 228 return (0); 229 /*NOTREACHED*/ 230 231 default: 232 break; 233 } 234 close(state->control[0]); 235 close(state->pipes[1]); 236 return (0); 237} 238 239int 240benchmark(void *tsd, result_t *res) 241{ 242 /* 243 * try not to initialize things here. This is the main 244 * loop of things to get timed. Start a server in 245 * benchmark_initbatch 246 */ 247 tsd_t *state = (tsd_t *)tsd; 248 size_t done, n; 249 size_t todo = state->bytes; 250 int i; 251 252 debug("in to benchmark - optB = %i : repetitions = %i\n", lm_optB, state->repetitions); 253 for (i = 0; i < lm_optB; i++) { 254 write(state->control[1], &todo, sizeof(todo)); 255 for (done = 0; done < todo; done += n) { 256 if ((n = read(state->pipes[0], state->buf, state->xfer)) <= 0) { 257 /* error! */ 258 debug("error (n = %d) exiting now\n", n); 259 exit(1); 260 } 261 } 262 } 263 res->re_count = i; 264 debug("out of benchmark - optB = %i : repetitions = %i\n", lm_optB, state->repetitions); 265 266 return (0); 267} 268 269int 270benchmark_finibatch(void *tsd) 271{ 272 tsd_t *state = (tsd_t *)tsd; 273 274 close(state->control[1]); 275 close(state->pipes[0]); 276 if (state->pid > 0) { 277 kill(state->pid, SIGKILL); 278 waitpid(state->pid, NULL, 0); 279 } 280 state->pid = 0; 281 return (0); 282} 283 284int 285benchmark_finiworker(void *tsd) 286{ 287 tsd_t *ts = (tsd_t *)tsd; 288 // useless code to show what you can do. 289 ts->repetitions++; 290 ts->repetitions--; 291 debug("benchmark_finiworker: repetitions = %i\n",ts->repetitions); 292 return (0); 293} 294 295char * 296benchmark_result() 297{ 298 static char result = '\0'; 299 debug("benchmark_result\n"); 300 return (&result); 301} 302 303int 304benchmark_finirun() 305{ 306 debug("benchmark_finirun\n"); 307 return (0); 308} 309 310 311int 312benchmark_fini() 313{ 314 debug("benchmark_fini\n"); 315 return (0); 316} 317 318/* 319 * functions from bw_unix.c 320 */ 321void 322writer(int controlfd, int writefd, char* buf, void* cookie) 323{ 324 size_t todo, n, done; 325 tsd_t *state = (tsd_t *)cookie; 326 327 for ( ;; ) { 328 read(controlfd, &todo, sizeof(todo)); 329 for (done = 0; done < todo; done += n) { 330#ifdef TOUCH 331 touch(buf, XFERSIZE); 332#endif 333 if ((n = write(writefd, buf, state->xfer)) < 0) { 334 /* error! */ 335 exit(1); 336 } 337 } 338 } 339} 340 341void 342touch(char *buf, int nbytes) 343{ 344 static int psize; 345 346 if (!psize) { 347 psize = getpagesize(); 348 } 349 while (nbytes > 0) { 350 *buf = 1; 351 buf += psize; 352 nbytes -= psize; 353 } 354} 355 356