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#include <unistd.h> 30#include <stdlib.h> 31#include <stdio.h> 32#include <stdbool.h> 33#include <errno.h> 34#include <string.h> 35 36// add additional headers needed here. 37 38#include "../libmicro.h" 39#include <membership.h> 40#include <grp.h> 41 42#if DEBUG 43# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) 44#else 45# define debug(fmt, args...) 46#endif 47 48 49// Correct use case 50// 51// getgrgid -E -L -S -W -B 200 -C 10 -g 1211-1213 52// 53// libMicro default benchmark run options are "-E -L -S -W -C 200" 54// 55// -B is batch size: loop iteration per each benchmark run. Needs to match # of 56// real lookups. This is total number of lookups to issue. 57// -C is min sample number: how many benchmark needs to run to get proper sample 58// 1 is mimumum, but you get at least 3 benchmark run 59// samples. Do not set to zero. Default is 200 for most 60// runs in libMicro. 61// -g gid range in the form of "min-max". For example, -g 1211-1213 62// 63 64extern int gL1CacheEnabled; 65 66/* 67 * Your state variables should live in the tsd_t struct below 68 */ 69typedef struct { 70} tsd_t; 71 72// temporary buffer size 73#define BUFSIZE 200 74#define INVALID_ID -1 75 76static gid_t gid_min = INVALID_ID; 77static int gid_range = 0; // gid_max = gid_min + gid_range 78 79int 80benchmark_init() 81{ 82 debug("benchmark_init"); 83 (void) sprintf(lm_optstr, "l:g:"); 84 85 lm_tsdsize = sizeof (tsd_t); 86 lm_defB = 100; 87 88 (void) sprintf(lm_usage, 89 "\n ------- getgrgid specific options (default: *)\n" 90 " [-g GID range (min-max)]\n" 91 "\n" ); 92 return (0); 93} 94 95 96int 97parse_range(gid_t *min, int *offset, char *buf) 98{ 99 char *value, *tmp_ptr = strdup(buf); 100 int range=0; 101 debug("parse_range"); 102 103 value = strsep(&tmp_ptr, "-"); 104 *min = atoi(value); 105 debug("min = %d", *min); 106 if (tmp_ptr) { 107 value = strsep(&tmp_ptr, "-"); 108 range = atoi(value); 109 if (range < *min) { 110 printf("max id should be larger than min id\n"); 111 return -1; 112 } 113 *offset = range - *min + 1; 114 debug("range = %d", *offset); 115 } 116 else { 117 printf("argument should be in the form of min-max\n"); 118 return -1; 119 } 120 121 return 0; 122 123} 124 125/* 126 * This is where you parse your lower-case arguments. 127 */ 128int 129benchmark_optswitch(int opt, char *optarg) 130{ 131 debug("benchmark_optswitch"); 132 133 switch (opt) { 134 case 'l': 135 gL1CacheEnabled = atoi(optarg); 136 break; 137 138 case 'g': // GID range 139 return parse_range( &gid_min, &gid_range, optarg); 140 break; 141 142 default: 143 return -1; 144 } 145 146 return 0; 147} 148 149 150// Initialize all structures that will be used in benchmark() 151// moved template init from benchmark_initworker -> benchmark_initrun 152// 153int 154benchmark_initrun() 155{ 156 debug("\nbenchmark_initrun"); 157 158 return (0); 159} 160 161 162int 163benchmark(void *tsd, result_t *res) 164{ 165 int i, err; 166 struct group *grp = NULL; 167 168 res->re_errors = 0; 169 170 debug("in to benchmark - optB = %i", lm_optB); 171 for (i = 0; i < lm_optB; i++) { 172 gid_t gid = gid_min + random() % gid_range ; 173 174 if (lm_optT > 1) { 175 struct group gd; 176 struct group *grp_ptr = &gd; 177 struct group *tmp_ptr; 178 char gbuf[BUFSIZE]; 179 180 err = getgrgid_r( gid, grp_ptr, gbuf, BUFSIZE, &tmp_ptr); 181 if (err) { 182 debug("error: GID %d -> %s", gid, strerror(err)); 183 res->re_errors++; 184 } 185 else if (!tmp_ptr) { 186 debug("not found: GID %d", gid); 187 res->re_errors++; 188 } 189 } 190 else { 191 errno = 0; 192 grp = getgrgid( gid ); 193 194 if (!grp) { 195 if (errno) { 196 debug("error: GID %d -> %s", gid, strerror(errno)); 197 res->re_errors++; 198 } 199 else { 200 debug("not found: GID %d", gid); 201 res->re_errors++; 202 } 203 } 204 } 205 } 206 res->re_count = i; 207 208 return (0); 209} 210 211// We need to release all the structures we allocated in benchmark_initrun() 212int 213benchmark_finirun(void *tsd) 214{ 215 // tsd_t *ts = (tsd_t *)tsd; 216 debug("benchmark_finirun "); 217 218 return (0); 219} 220 221char * 222benchmark_result() 223{ 224 static char result = '\0'; 225 debug("benchmark_result"); 226 return (&result); 227} 228 229