#ifdef _WIN32 #include #else #include #include #include extern int errno; #endif #include #include #include #define equal !strcmp #define equaln !strncmp #define MAXCOUNT 100000 #ifdef _WIN32 #define SLASHC '\\' #define SLASHSTR "\\" #else #define SLASHC '/' #define SLASHSTR "/" #endif // // pipe [maxcount] // // This program does pipes. // // We create two execution environments and pass a token back and forth // between them as fast as we can. We count the number and time and // produce a context switches per second number. // size_t atoik(char *); void *Malloc(size_t sz); void tstart(void); void tend(void); double tval(void); unsigned long maxcount = MAXCOUNT; size_t nbytes = 4; char *applname = ""; int mult = 1; unsigned long *token; unsigned long *rtoken; unsigned long amount = 0; unsigned long ramount = 0; unsigned long readtot = 0; unsigned long writetot = 0; unsigned long x; #ifdef _WIN32 char *pipeAdult = "\\\\.\\pipe\\pipe2"; HANDLE handleA; HANDLE handleB; int twentyfour = 24; #else int fd1[2]; // pipe file descriptors #endif int main(int ac, char *av[]) { int i; double t; applname = av[0]; if(strchr(applname,SLASHC)) applname = strrchr(applname,SLASHC) + 1; if(ac == 1) { printf("USAGE: %s [-x mult] count [bytes]\n", applname); printf("\t-x mult - mult*bytes is the size of the input\n"); printf("\t and output buffers (default=1).\n"); printf("\tcount - the number of loops.\n"); printf("\tbytes - the amount written through each pass.\n"); return 0; } while(ac > 1 && av[1][0] == '-') { if(equaln(av[1],"-x",2)) { if(av[1][2]) mult = atoik(&av[1][2]); else { ac--; av++; mult = atoik(av[1]); } } #ifdef _WIN32 else if(equal(av[1],"-24")) { twentyfour = 0; } #endif ac--; av++; } if(ac > 1 && isdigit(av[1][0])) { maxcount = atoik(av[1]); ac--; av++; if(maxcount == 0) maxcount = 1; } if(ac > 1 && isdigit(av[1][0])) { nbytes = atoik(av[1]); ac--; av++; if(nbytes <= 0) nbytes = 1; } token = (unsigned long *)Malloc(nbytes); rtoken = (unsigned long *)Malloc(nbytes); memset(token, '\0', nbytes); memset(rtoken, '\0', nbytes); #ifdef _WIN32 // // Let's see you find this number somewhere in the documentation. // x = mult*nbytes + twentyfour; handleA = CreateNamedPipe(pipeAdult, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 2, x, x, INFINITE, NULL); if(handleA == INVALID_HANDLE_VALUE) { printf("CreateNamedPipe() FAILED: err=%d\n", GetLastError()); return 1; } handleB = CreateFile(pipeAdult, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(handleB == INVALID_HANDLE_VALUE) { printf("CreateFile() FAILED: err=%d\n", GetLastError()); return 1; } if(WriteFile(handleB, &token[0], 1, &amount, NULL) == 0) { printf("initial WriteFile failed: err=%d\n", GetLastError()); return 1; } if(ReadFile(handleA, &token[0], 1, &amount, NULL) == 0) { printf("initial ReadFile failed: err=%d\n", GetLastError()); return 1; } #else if(pipe(fd1)) { printf("pipe() FAILED: errno=%d\n",errno); return 1; } #endif tstart(); for(i = 0; i < maxcount; i++) { writetot = 0; while(writetot < nbytes) { #ifdef _WIN32 if(WriteFile(handleB, &token[writetot], nbytes-writetot, &amount, NULL) == 0) { printf("WriteFile failed: err=%d\n", GetLastError()); return 1; } #else amount = write(fd1[1], &token[writetot],nbytes-writetot); if(amount == -1) { printf("write FAILED: errno=%d\n",errno); return 1; } //printf("write ret=%d\n",amount); #endif writetot += amount; } readtot = 0; while(readtot < nbytes) { #ifdef _WIN32 if(ReadFile(handleA, &rtoken[readtot], nbytes-readtot, &ramount, NULL) == 0) { printf("ReadFile failed: err=%d\n", GetLastError()); return 1; } #else ramount = read(fd1[0], &rtoken[readtot], nbytes-readtot); if(ramount == -1) { printf("read FAILED: errno=%d\n",errno); return 1; } else if(ramount == 0) break; //printf("read ret=%d (nbytes=%d)\n",ramount,nbytes); #endif readtot += ramount; } } tend(); t = tval(); printf("%s ",applname); printf("-x %d ",mult); printf("%d %d %8.3f Seconds", maxcount,nbytes,t); printf(" -- %8.3f MB/sec\n", (((double)maxcount*(double)nbytes)/t)/1e6); return 0; } #include size_t atoik(char *s) { size_t ret = 0; size_t base; if(*s == '0') { base = 8; if(*++s == 'x' || *s == 'X') { base = 16; s++; } } else base = 10; for(; isxdigit(*s); s++) { if(base == 16) if(isalpha(*s)) ret = base*ret + (toupper(*s) - 'A'); else ret = base*ret + (*s - '0'); else if(isdigit(*s)) ret = base*ret + (*s - '0'); else break; } for(; isalpha(*s); s++) { switch(toupper(*s)) { case 'K': ret *= 1024; break; case 'M': ret *= 1024*1024; break; default: return ret; } } return ret; } void *Malloc(size_t sz) { char *p; p = (char *)malloc(sz); if(p == NULL) { (void)printf("malloc(%d) failed\n",sz); exit(1); } return (void *)p; } #ifdef _WIN32 static LARGE_INTEGER _tstart, _tend; static LARGE_INTEGER freq; void tstart(void) { static int first = 1; if(first) { QueryPerformanceFrequency(&freq); first = 0; } QueryPerformanceCounter(&_tstart); } void tend(void) { QueryPerformanceCounter(&_tend); } double tval() { return ((double)_tend.QuadPart - (double)_tstart.QuadPart)/((double)freq.QuadPart); } #else static struct timeval _tstart, _tend; static struct timezone tz; void tstart(void) { gettimeofday(&_tstart, &tz); } void tend(void) { gettimeofday(&_tend,&tz); } double tval() { double t1, t2; t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000); t2 = (double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000); return t2-t1; } #endif