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 37 uint64_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 52 void *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 60 void *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 74 void *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 82 char *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 91 size_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 */ 104 void 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 111 char *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 125 void 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 134 struct 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 144 struct 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 154 double tvtodouble(struct timeval *t) 155 { 156 return ((double)t->tv_sec * (1000000.0f) + (double)t->tv_usec) / 157 1000000.0f; 158 } 159 160 double 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 173 double 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 */ 187 float 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 199 uint64_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 207 int 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 235 void 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 247 void 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 263 void 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 272 void 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 281 void 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 289 void 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 304 void 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 313 void 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 330 void 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