#ifdef _WIN32 #include #define WINDEC __stdcall #else #include #include #include #include #include #include #include #define WINDEC #endif #include #include #include #define equal !strcmp #define equaln !strncmp #define MAXCOUNT 100000 #ifdef _WIN32 #define SLASHC '\\' #define SLASHSTR "\\" #define errno GetLastError() #else #define SLASHC '/' #define SLASHSTR "/" extern int errno; #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. // #ifdef _WIN32 unsigned long WINDEC Pipereader(void*); unsigned long writeId; HANDLE th1; #else unsigned long threadreturn; unsigned long Pipereader(void *); pthread_t tA; #endif 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 *rtoken2; unsigned long amount = 0; unsigned long ramount = 0; unsigned long readtot = 0; unsigned long writetot = 0; int touchread = 1; int touchwrite = 1; int wincp = 0; int linnp = 0; int wincpsize = 4096; unsigned long x; double t1,t2; #ifdef _WIN32 char *pipeAdult = "\\\\.\\pipe\\pipe2"; HANDLE handleA; HANDLE handleB; int twentyfour = 24; #else int fd1[2]; // pipe file descriptors char *pipename = "/tmp/egb-pipe"; #endif int debug = 0; int main(int ac, char *av[]) { int i; double t; if(ac > 1 && equal(av[1], "-debug")) { ac--; av++; debug = 1; } applname = av[0]; if(strchr(applname,SLASHC)) applname = strrchr(applname,SLASHC) + 1; if(ac == 1) { printf("USAGE: %s [-t[rw]] [-x mult] count [bytes]\n", applname); printf("\t-t - Touch the read (r) and write (w) buf (default)\n"); printf("\t-tr - Turn off touch read (r) buf\n"); printf("\t-tw - Turn off touch write (w) buf\n"); #ifdef _WIN32 printf("\tWINDOWS OPTION - [-wincp] [-wincpsize N]\n"); printf("\t wincp uses CreatePipe() with a size of N\n"); printf("\t (default wincpsize is 4096+24)\n"); #else printf("\tLINUX OPTION - [-linnp] - use a named pipe\n"); #endif 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]); } } else if(equaln(av[1],"-t",2)) { char *p; for(p = &av[1][2]; *p; p++) { switch(*p) { case 0: touchread = touchwrite = 1; break; case 'r': touchread = 0; break; case 'w': touchwrite = 0; break; } } } #ifdef _WIN32 else if(equal(av[1],"-24")) { twentyfour = 0; } else if(equal(av[1], "-wincp")) { wincp = 1; } else if(equaln(av[1],"-wincpsize", 10)) { if(av[1][10]) { wincpsize = atoik(&av[1][10]); } else { ac--; av++; wincpsize = atoik(av[1]); } } #endif else if(equal(av[1],"-linnp")) { linnp = 1; } 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); rtoken2 = (unsigned long *)Malloc(nbytes); memset(token, '\0', nbytes); memset(rtoken, '\0', nbytes); memset(rtoken2, '\0', nbytes); #ifdef _WIN32 // // Let's see you find this number somewhere in the documentation. // x = mult*nbytes + twentyfour; if(wincp) { if(CreatePipe(&handleA, &handleB, NULL, wincpsize) == 0) { printf("CreatePipe() FAILED: err=%d\n", GetLastError()); return 1; } } else { 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; } th1 = CreateThread(NULL, 4096, Pipereader, "W", NULL, &writeId); if(th1 == NULL) { printf("Thread Creation FAILED: err=%d\n", errno); } #else if(linnp) { if(unlink(pipename)) { if(errno != 2) { printf("unlink FAILED: err=%d\n",errno); return 1; } } if(mknod(pipename, S_IFIFO|0666, 0)) { printf("mknod(\"%s\") FAILED: err=%d\n",pipename,errno); return 1; } fd1[0] = open(pipename, O_RDONLY|O_NONBLOCK); fd1[1] = open(pipename, O_WRONLY); if(fd1[0] == -1 || fd1[1] == -1) { printf("open(\"%s\") FAILED: err=%d\n", pipename,errno); return 1; } } else if(pipe(fd1)) { printf("pipe() FAILED: errno=%d\n",errno); return 1; } # define DEC (void *(*)(void *)) if(pthread_create(&tA, NULL, DEC Pipereader, (void*)"A")) { printf("pthread_create FAILED: err=%d\n",errno); return 1; } #endif tstart(); for(i = 0; i < maxcount; i++) { writetot = 0; while(writetot < nbytes) { if(touchwrite) memset(token, i+1, nbytes); // Touch all pages. #ifdef _WIN32 if(WriteFile(handleB, &((char *)token)[writetot], nbytes-writetot, &amount, NULL) == 0) { printf("WriteFile failed: err=%d\n", GetLastError()); return 1; } #else amount = write(fd1[1], &((char *)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; } } tend(); t1 = tval(); #ifdef _WIN32 (void)WaitForSingleObject(th1,INFINITE); #else sched_yield(); if(pthread_join(tA, (void **)&threadreturn)) { printf("pthread_join FAILED: err=%d\n",errno); return 1; } #endif t2 = tval(); printf("%s ",applname); if(touchread && touchwrite) printf("-t "); else if(touchread == 0) printf("-tr "); else if(touchwrite == 0) printf("tw "); if(wincp) printf("-wincp -wincpsize %d ", wincpsize); if(linnp) printf("-linnp "); printf("-x %d ",mult); printf("%d %d %8.3f Seconds", maxcount,nbytes,t2); printf(" -- %8.3f MB/sec\n", (((double)maxcount*(double)nbytes)/t2)/1e6); return 0; } unsigned long WINDEC Pipereader(void *) { int i; for(i = 0; i < maxcount; i++) { readtot = 0; while(readtot < nbytes) { #ifdef _WIN32 if(ReadFile(handleA, &((char *)rtoken)[readtot], nbytes-readtot, &ramount, NULL) == 0) { printf("ReadFile failed: err=%d\n", GetLastError()); return 1; } #else if(debug)printf("%d: read %d bytes\n", i,nbytes-readtot); ramount = read(fd1[0], &((char *)rtoken)[readtot], nbytes-readtot); if(ramount == -1) { printf("read FAILED: errno=%d\n",errno); return 1; } else if(ramount == 0) break; #endif if(touchread) memcpy(rtoken2, rtoken, nbytes); readtot += ramount; } } #ifdef _WIN32 return 0; #else pthread_exit(0); #endif } #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