Home | History | Annotate | Download | only in ffsb-6.0-rc2
      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