1/* 2 * Copyright (c) International Business Machines Corp., 2001-2004 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#include <sys/types.h> 19#include <sys/stat.h> 20#include <sys/resource.h> 21#include <sys/wait.h> 22#include <sys/time.h> 23#include <sys/select.h> 24#include <stdio.h> 25#include <unistd.h> 26#include <stdlib.h> 27#include <assert.h> 28#include <string.h> 29#include <limits.h> 30#include <errno.h> 31#include <pthread.h> 32 33#include "config.h" 34#include "fh.h" 35#include "util.h" 36 37uint64_t ffsb_get_filesize(char *name) 38{ 39#ifndef HAVE_STAT64 40#define STAT(a, b) do { stat((a), (b)); } while (0) 41 struct stat filestat; 42#else 43#define STAT(a, b) do { stat64((a), (b)); } while (0) 44 struct stat64 filestat; 45#endif 46 47 STAT(name, &filestat); 48 return (uint64_t) filestat.st_size; 49#undef STAT 50} 51 52void *ffsb_malloc(size_t size) 53{ 54 void *ptr = malloc((size)); 55 assert(ptr != NULL); 56 memset(ptr, 0, size); 57 return ptr; 58} 59 60void *ffsb_realloc(void *ptr, size_t size) 61{ 62 void *tmp; 63 /* printf("ffsb_realloc: ptr = %p size = %ld\n",ptr,size); */ 64 65 if (ptr == NULL) 66 return ffsb_malloc(size); 67 68 tmp = realloc(ptr, size); 69 assert(ptr != NULL); 70 ptr = tmp; 71 return ptr; 72} 73 74void *ffsb_align_4k(void *ptr) 75{ 76 unsigned long mask = ~(0xfff); /* 12 zeros at the end */ 77 void *ret = (void *)((unsigned long)ptr & mask); 78 /* printf("align_4k got %p returning %p\n",ptr,ret); */ 79 return ret; 80} 81 82char *ffsb_strdup(const char *str) 83{ 84 int len = strlen(str); 85 char *dup = ffsb_malloc(len + 1); 86 /* !!! am I off by one here ?? */ 87 strncpy(dup, str, len + 1); 88 return dup; 89} 90 91size_t ffsb_strnlen(const char *str, size_t maxlen) 92{ 93 size_t index = 0; 94 95 while (index < maxlen) { 96 if (str[index] == '\0') 97 break; 98 index++; 99 } 100 return index; 101} 102 103/* not perfect, in case we are somehow interrupted it's borked */ 104void ffsb_sleep(unsigned secs) 105{ 106 struct timeval tv = { 0, 0 }; 107 tv.tv_sec = secs; 108 select(0, NULL, NULL, NULL, &tv); 109} 110 111char *ffsb_printsize(char *buf, double size, int bufsize) 112{ 113 if (size >= 1024 * 1024 * 1024) 114 snprintf(buf, bufsize, "%.3gGB", size / (1024 * 1024 * 1024)); 115 else if (size >= 1024 * 1024) 116 snprintf(buf, bufsize, "%.3gMB", size / (1024 * 1024)); 117 else if (size >= 1024) 118 snprintf(buf, bufsize, "%.3gKB", size / 1024); 119 else 120 snprintf(buf, bufsize, "%.3gB", size); 121 122 return buf; 123} 124 125void ffsb_mkdir(char *dirname) 126{ 127 if (mkdir(dirname, S_IRWXU) < 0) { 128 fprintf(stderr, "Error creating %s\n", dirname); 129 perror("mkdir"); 130 exit(1); 131 } 132} 133 134struct timeval tvsub(struct timeval t1, struct timeval t0) 135{ 136 struct timeval tdiff; 137 tdiff.tv_sec = t1.tv_sec - t0.tv_sec; 138 tdiff.tv_usec = t1.tv_usec - t0.tv_usec; 139 if (tdiff.tv_usec < 0) 140 tdiff.tv_sec--, tdiff.tv_usec += 1000000; 141 return tdiff; 142} 143 144struct timeval tvadd(struct timeval t1, struct timeval t0) 145{ 146 struct timeval tdiff; 147 tdiff.tv_sec = t1.tv_sec + t0.tv_sec; 148 tdiff.tv_usec = t1.tv_usec + t0.tv_usec; 149 if (tdiff.tv_usec > 1000000) 150 tdiff.tv_sec++, tdiff.tv_usec -= 1000000; 151 return tdiff; 152} 153 154double tvtodouble(struct timeval *t) 155{ 156 return ((double)t->tv_sec * (1000000.0f) + (double)t->tv_usec) / 157 1000000.0f; 158} 159 160double cpu_so_far(void) 161{ 162 struct rusage rusage; 163 164 getrusage(RUSAGE_SELF, &rusage); 165 166 return 167 ((double)rusage.ru_utime.tv_sec) + 168 (((double)rusage.ru_utime.tv_usec) / 1000000.0) + 169 ((double)rusage.ru_stime.tv_sec) + 170 (((double)rusage.ru_stime.tv_usec) / 1000000.0); 171} 172 173double cpu_so_far_children(void) 174{ 175 struct rusage rusage; 176 177 getrusage(RUSAGE_CHILDREN, &rusage); 178 179 return 180 ((double)rusage.ru_utime.tv_sec) + 181 (((double)rusage.ru_utime.tv_usec) / 1000000.0) + 182 ((double)rusage.ru_stime.tv_sec) + 183 (((double)rusage.ru_stime.tv_usec) / 1000000.0); 184} 185 186/* !!!! check portability */ 187float getfsutil(char *dirname) 188{ 189 struct statvfs64 fsdata; 190 191 statvfs64(dirname, &fsdata); 192 193/* return (float)(fsdata.f_blocks-fsdata.f_bfree)/ */ 194/* (float)(fsdata.f_blocks-fsdata.f_bfree+fsdata.f_bavail); */ 195 return (float)(((float)(fsdata.f_blocks - fsdata.f_bfree)) / 196 ((float)fsdata.f_blocks)); 197} 198 199uint64_t getfsutil_size(char *dirname) 200{ 201 struct statvfs64 fsdata; 202 statvfs64(dirname, &fsdata); 203 204 return (fsdata.f_blocks - fsdata.f_bfree) * fsdata.f_bsize; 205} 206 207int ffsb_system(char *command) 208{ 209 int pid = 0, status; 210 extern char **environ; 211 212 if (command == NULL) 213 return 1; 214 pid = fork(); 215 if (pid == -1) 216 return -1; 217 if (pid == 0) { 218 char *argv[4]; 219 argv[0] = "sh"; 220 argv[1] = "-c"; 221 argv[2] = command; 222 argv[3] = 0; 223 execve("/bin/sh", argv, environ); 224 exit(127); 225 } 226 do { 227 if (waitpid(pid, &status, 0) == -1) { 228 if (errno != EINTR) 229 return -1; 230 } else 231 return status; 232 } while (1); 233} 234 235void ffsb_sync() 236{ 237 struct timeval starttime, endtime, difftime; 238 printf("Syncing()..."); 239 fflush(stdout); 240 gettimeofday(&starttime, NULL); 241 sync(); 242 gettimeofday(&endtime, NULL); 243 timersub(&endtime, &starttime, &difftime); 244 printf("%ld sec\n", difftime.tv_sec); 245} 246 247void ffsb_getrusage(struct rusage *ru_self, struct rusage *ru_children) 248{ 249 int ret = 0; 250/* printf("cpu_so_far is %lf\n",cpu_so_far()); */ 251/* printf("cpu_so_far_children is %lf\n",cpu_so_far_children()); */ 252 ret = getrusage(RUSAGE_SELF, ru_self); 253 if (ret < 0) 254 perror("getrusage self"); 255 256/* printf("self returned %d\n",ret); */ 257 ret = getrusage(RUSAGE_CHILDREN, ru_children); 258 if (ret < 0) 259 perror("getrusage children"); 260/* printf("children returned %d\n",ret); */ 261} 262 263void ffsb_milli_sleep(unsigned time) 264{ 265 struct timeval tv = { 0, 0 }; 266 if (!time) 267 return; 268 tv.tv_usec = time * 1000; 269 select(0, NULL, NULL, NULL, &tv); 270} 271 272void ffsb_micro_sleep(unsigned time) 273{ 274 struct timeval tv = { 0, 0 }; 275 if (!time) 276 return; 277 tv.tv_usec = time; 278 select(0, NULL, NULL, NULL, &tv); 279} 280 281void ffsb_barrier_init(ffsb_barrier_t * fb, unsigned count) 282{ 283 memset(fb, 0, sizeof(*fb)); 284 pthread_mutex_init(&fb->plock, NULL); 285 pthread_cond_init(&fb->pcond, NULL); 286 fb->required_count = count; 287} 288 289void ffsb_barrier_wait(ffsb_barrier_t * fb) 290{ 291 pthread_mutex_lock(&fb->plock); 292 293 fb->current_count++; 294 295 if (fb->current_count == fb->required_count) 296 pthread_cond_broadcast(&fb->pcond); 297 else 298 while (fb->current_count != fb->required_count) 299 pthread_cond_wait(&fb->pcond, &fb->plock); 300 301 pthread_mutex_unlock(&fb->plock); 302} 303 304void ffsb_unbuffer_stdout(void) 305{ 306#ifndef SETVBUF_REVERSED 307 setvbuf(stdout, NULL, _IONBF, 0); 308#else 309 setvbuf(stdout, _IONBF, NULL, 0); 310#endif 311} 312 313void ffsb_bench_gettimeofday(void) 314{ 315 unsigned long i = 0; 316 uint64_t total_usec; 317 uint64_t average = 0; 318 struct timeval starttime, endtime, junk, difftime; 319 gettimeofday(&starttime, NULL); 320 for (i = 0; i < 1000000; i++) 321 gettimeofday(&junk, NULL); 322 gettimeofday(&endtime, NULL); 323 timersub(&endtime, &starttime, &difftime); 324 total_usec = difftime.tv_sec * 1000000; 325 total_usec += difftime.tv_usec; 326 average = total_usec / 1000ull; 327 printf("average time for gettimeofday(): %llu nsec\n", average); 328} 329 330void ffsb_bench_getpid(void) 331{ 332 unsigned long i = 0; 333 uint64_t total_usec; 334 uint64_t average = 0; 335 struct timeval starttime, endtime, difftime; 336 gettimeofday(&starttime, NULL); 337 for (i = 0; i < 1000000; i++) 338 getpid(); 339 gettimeofday(&endtime, NULL); 340 timersub(&endtime, &starttime, &difftime); 341 total_usec = difftime.tv_sec * 1000000; 342 total_usec += difftime.tv_usec; 343 average = total_usec / 1000ull; 344 printf("average time for getpid(): %llu nsec\n", average); 345} 346