// // cl -O2 create-pt2.cpp // gcc -O2 create-pt2.cpp -o create-pt2 -lpthread // #ifdef _WIN32 #define THRDFN LPTHREAD_START_ROUTINE #include #define SLASHC '\\' #define SLASHSTR "\\" #define errno GetLastError() #define WSACLEANUP WSACleanup() #define WINDEC __stdcall #define SLEEP(n) Sleep(n*1000) #define SOCKLEN #else #define SLASHC '/' #define SLASHSTR "/" #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #define WSACLEANUP #define WINDEC #define SLEEP(n) sleep(n) #define SOCKLEN (socklen_t *) #endif #include #include #ifndef _WIN32 #include #include #include #include #include #include #include #include #include #include #include #include #include pid_t childpid; #endif #define equal !strcmp size_t atoik(char *); char *ulver(); void *Malloc(size_t sz); void tstart(void); void tend(void); double tval(void); char *applname = ""; char progname[1024]; int threads = 1; int count = 1000; long counter = 0; unsigned long threadwork(void *); #ifdef _WIN32 HANDLE t1; #else pthread_t t1; // thread handle #endif void CREATETHREAD(); void CLEANUPTHREAD(); unsigned long returncode; unsigned long threadid; int startTimedTest(volatile int *); void endTimedTest(); extern int nseconds; unsigned long WINDEC timerloop(void *); volatile int timedtestflag = 0; volatile int run_count = 0; int main(int ac, char *av[]) { int i; double t; #ifdef _WIN32 strcpy(progname,av[0]); if(strlen(progname) > 4 && !equal(&progname[strlen(progname)-4], ".exe")) strcat(progname,".exe"); #endif applname = av[0]; if(strrchr(applname,SLASHC)) applname = strrchr(applname,SLASHC) + 1; if(strlen(applname) > 6 && equal(&applname[strlen(applname)-6], "-child")) { //printf("<%s>\n",applname); exit(0); } if(ac < 2) { printf("USAGE: %s [-p] nseconds\n", applname); printf("\t-p - create processes rather than threads\n"); printf("\tnseconds = how long to run the test\n"); return 0; } if(equal(av[1], "-p")) { ac--; av++; threads = 0; } if(ac > 1 && isdigit(av[1][0])) { nseconds = atoik(av[1]); ac--; av++; if(nseconds <= 0) nseconds = 1; } if(startTimedTest(&timedtestflag)) return 1; i = 0; tstart(); while(timedtestflag) { i++; CREATETHREAD(); CLEANUPTHREAD(); } tend(); count = i; t = tval(); endTimedTest(); printf("%s: ",applname); printf("%s ", threads ? "" : "-p"); printf("%d %8.3f Seconds", count,t); printf(" -- %8.3f %s/sec\n", (double)count/t, threads ? "threads" : "processes"); return 0; } void CREATETHREAD(){ #ifdef _WIN32 if(threads) { t1 = CreateThread(NULL,4096,(THRDFN)threadwork,"L",NULL,&threadid); if(t1 == NULL) { printf("CreateThread FAILED: err=%d\n", errno); return; } } else { char buf[1024]; BOOL b; sprintf(buf, "%s-child", applname); buf[sizeof(buf)-1] = 0; STARTUPINFO startInfo; PROCESS_INFORMATION pidInfo; // // child process // startInfo.cb = sizeof(STARTUPINFO); startInfo.lpReserved = NULL; startInfo.lpTitle = buf; startInfo.lpDesktop = NULL; startInfo.dwX = 0; startInfo.dwY = 0; startInfo.dwXSize = 0; startInfo.dwYSize = 0; startInfo.dwXCountChars = 0; startInfo.dwYCountChars = 0; startInfo.dwFlags = STARTF_USESTDHANDLES; // STARTF_USESHOWWINDOW //| STARTF_USEPOSITION //| STARTF_USESIZE; startInfo.wShowWindow = 0; //SW_SHOWDEFAULT; startInfo.lpReserved2 = NULL; startInfo.cbReserved2 = 0; startInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); startInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); b = CreateProcess( progname, buf, NULL, NULL, TRUE, 0,//CREATE_NEW_CONSOLE, NULL, NULL, &startInfo, &pidInfo); if(!b) { printf("Creation of child process failed: err=%d\n", errno); printf("applname=<%s>, buf=<%s>\n",applname,buf); return; } if(CloseHandle(pidInfo.hThread) == 0) { printf("CloseHandle hThread FAILED: err=%d\n",errno); exit(1); } t1 = pidInfo.hProcess; } #else if(threads) { # define DEC ( void *(*)(void*) ) if(pthread_create(&t1, NULL, DEC threadwork, NULL)) { printf("pthread_create A failed: err=%d\n", errno); return; } } else { // process char buf[1024]; sprintf(buf, "%s-child", applname); if(childpid = fork()) { if(childpid == -1) { printf("fork failed: err=%d\n",errno); return; } } if(childpid == 0) { if(execl(applname, buf, 0) == -1) { printf("execl FAILED: err=%d\n", errno); return; } } } #endif } unsigned long threadwork(void *) { if(threads) counter++; return 0; } void CLEANUPTHREAD() { #ifdef _WIN32 // // Works for both threads and processes // if(WaitForSingleObject(t1,INFINITE) == WAIT_FAILED) { printf("WaitForSingleObject FAILED: err=%d\n", GetLastError()); return; } if(threads) { if(!GetExitCodeThread(t1,&returncode)) { printf("GetExitCodeThread FAILED: err=%d\n", GetLastError()); return; } } else { if(!GetExitCodeProcess(t1,&returncode)) { printf("GetExitCodeThread FAILED: err=%d\n", GetLastError()); return; } } if(CloseHandle(t1) == 0) { printf("CloseHandle FAILED: err=%d\n",GetLastError()); return; } #else if(threads) { int rc; rc = pthread_join(t1, (void**)&returncode); if(rc) { printf("pthread_join FAILED: err=%d\n",rc); return; } } else { pid_t pid; pid = wait(&returncode); if(pid == -1) { printf("wait FAILED: err=%d\n", errno); return; } } #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 int underbars = 0; char *ver() { #ifdef _WIN32 static char verbuf[256]; OSVERSIONINFO VersionInfo; VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo); if(GetVersionEx(&VersionInfo)) { if(strlen(VersionInfo.szCSDVersion) > 200) VersionInfo.szCSDVersion[100] = 0; sprintf(verbuf, "Windows %d.%d build%d PlatformId %d SP=\"%s\"", VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, VersionInfo.dwBuildNumber, VersionInfo.dwPlatformId, VersionInfo.szCSDVersion); if(underbars) { char *q; for(q = verbuf; *q; q++) if(*q == ' ' || *q == '\t' || *q == '\n' || *q == '\r') *q = '_'; } return verbuf; } else { return "WINDOWS UNKNOWN"; } #else struct utsname ubuf; static char verbuf[4*SYS_NMLN + 4]; if(uname(&ubuf)) return "LINUX UNKNOWN"; sprintf(verbuf,"%s %s %s %s", ubuf.sysname, ubuf.release, ubuf.version, ubuf.machine); if(underbars) { char *q; for(q = verbuf; *q; q++) if(*q == ' ' || *q == '\t' || *q == '\n' || *q == '\r') *q = '_'; } return verbuf; #endif } char *ulver() { char *p = ver(); if(p && *p) { char *q; for(q = p; *q; q++) if(*q == ' ' || *q == '\t' || *q == '\r' || *p == '\n') *q = '_'; } return p; } #ifdef _WIN32 # include # define WINDEC __stdcall # define YIELD Sleep(0) #ifndef SLEEP # define SLEEP(x) Sleep(1000*x) #endif # define LOCK EnterCriticalSection # define UNLOCK LeaveCriticalSection # define INITCRIT(x) InitializeCriticalSection(x); CRITICAL_SECTION critA; CRITICAL_SECTION lock_run_count; HANDLE mutexA; unsigned long timerId; HANDLE th1; #else # define WINDEC # define YIELD sched_yield() # define SLEEP(x) sleep(x) # define LOCK pthread_mutex_lock # define UNLOCK pthread_mutex_unlock # define INITCRIT(x) pthread_mutex_init(x,NULL); pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t lock_run_count; unsigned long threadreturn; pthread_t tA; #endif #include int startTimedTest(volatile int *); void endTimedTest(); int nseconds = 4; unsigned long WINDEC timerloop(void *); int startTimedTest(volatile int *flg) { static int first = 1; if(first) { INITCRIT(&lock_run_count); first = 0; } run_count = 0; #ifdef _WIN32 th1 = CreateThread(NULL, 4096,timerloop,(char *)flg,NULL,&timerId); if(th1 == NULL) { printf("CreateThread FAILED: err=%d\n",errno); return 1; } #else # define DEC (void *(*)(void *)) if(pthread_create(&tA, NULL, DEC timerloop, (void *)flg)) { printf("pthread_create FAILED: err=%d\n", errno); return 1; } #endif while(run_count != 1) YIELD; return 0; } unsigned long WINDEC timerloop(void *v) { int *flg = (int *)v; LOCK(&lock_run_count); run_count++; UNLOCK(&lock_run_count); *flg = 1; SLEEP(nseconds); *flg = 0; return 0; } void endTimedTest() { #ifdef _WIN32 (void)WaitForSingleObject(&th1, INFINITE); #else int err; err = pthread_join(tA, (void **)&threadreturn); if(err) { printf("pthread_join FAILED: err=%d\n",err); return; } #endif }