X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/a0b4f637ba1a6c3c5651b61a69303b029bacf7d3..2ca993e82fb37b597a3c73ecd1586a139a6579c5:/icuSources/test/threadtest/threadtest.cpp?ds=inline diff --git a/icuSources/test/threadtest/threadtest.cpp b/icuSources/test/threadtest/threadtest.cpp deleted file mode 100644 index 85e53a55..00000000 --- a/icuSources/test/threadtest/threadtest.cpp +++ /dev/null @@ -1,537 +0,0 @@ -// -//******************************************************************** -// Copyright (C) 2002-2011, International Business Machines -// Corporation and others. All Rights Reserved. -//******************************************************************** -// -// File threadtest.cpp -// - -#include -#include -#include - -#include "unicode/utypes.h" -#include "unicode/uclean.h" -#include "umutex.h" -#include "threadtest.h" - -AbstractThreadTest::~AbstractThreadTest() {} - -//------------------------------------------------------------------------------ -// -// Factory functions for creating different test types. -// -//------------------------------------------------------------------------------ -extern AbstractThreadTest *createStringTest(); -extern AbstractThreadTest *createConvertTest(); - - - -//------------------------------------------------------------------------------ -// -// Windows specific code for starting threads -// -//------------------------------------------------------------------------------ -#if U_PLATFORM_USES_ONLY_WIN32_API - -#include "Windows.h" -#include "process.h" - - - -typedef void (*ThreadFunc)(void *); - -class ThreadFuncs // This class isolates OS dependent threading -{ // functions from the rest of ThreadTest program. -public: - static void Sleep(int millis) {::Sleep(millis);}; - static void startThread(ThreadFunc, void *param); - static unsigned long getCurrentMillis(); - static void yield() {::Sleep(0);}; -}; - -void ThreadFuncs::startThread(ThreadFunc func, void *param) -{ - unsigned long x; - x = _beginthread(func, 0x10000, param); - if (x == -1) - { - fprintf(stderr, "Error starting thread. Errno = %d\n", errno); - exit(-1); - } -} - -unsigned long ThreadFuncs::getCurrentMillis() -{ - return (unsigned long)::GetTickCount(); -} - - - - -// #elif defined (POSIX) -#else - -//------------------------------------------------------------------------------ -// -// UNIX specific code for starting threads -// -//------------------------------------------------------------------------------ -#include -#include -#include -#include -#include - - -extern "C" { - - -typedef void (*ThreadFunc)(void *); -typedef void *(*pthreadfunc)(void *); - -class ThreadFuncs // This class isolates OS dependent threading -{ // functions from the rest of ThreadTest program. -public: - static void Sleep(int millis); - static void startThread(ThreadFunc, void *param); - static unsigned long getCurrentMillis(); - static void yield() {sched_yield();}; -}; - -void ThreadFuncs::Sleep(int millis) -{ - int seconds = millis/1000; - if (seconds <= 0) seconds = 1; - ::sleep(seconds); -} - - -void ThreadFuncs::startThread(ThreadFunc func, void *param) -{ - unsigned long x; - - pthread_t tId; - //thread_t tId; -#if defined(_HP_UX) && defined(XML_USE_DCE) - x = pthread_create( &tId, pthread_attr_default, (pthreadfunc)func, param); -#else - pthread_attr_t attr; - pthread_attr_init(&attr); - x = pthread_create( &tId, &attr, (pthreadfunc)func, param); -#endif - if (x == -1) - { - fprintf(stderr, "Error starting thread. Errno = %d\n", errno); - exit(-1); - } -} - -unsigned long ThreadFuncs::getCurrentMillis() { - timeb aTime; - ftime(&aTime); - return (unsigned long)(aTime.time*1000 + aTime.millitm); -} -} - - -// #else -// #error This platform is not supported -#endif - - - -//------------------------------------------------------------------------------ -// -// struct runInfo Holds the info extracted from the command line and data -// that is shared by all threads. -// There is only one of these, and it is static. -// During the test, the threads will access this info without -// any synchronization. -// -//------------------------------------------------------------------------------ -const int MAXINFILES = 25; -struct RunInfo -{ - bool quiet; - bool verbose; - int numThreads; - int totalTime; - int checkTime; - AbstractThreadTest *fTest; - bool stopFlag; - bool exitFlag; - int32_t runningThreads; -}; - - -//------------------------------------------------------------------------------ -// -// struct threadInfo Holds information specific to an individual thread. -// One of these is set up for each thread in the test. -// The main program monitors the threads by looking -// at the status stored in these structs. -// -//------------------------------------------------------------------------------ -struct ThreadInfo -{ - bool fHeartBeat; // Set true by the thread each time it finishes - // a test. - unsigned int fCycles; // Number of cycles completed. - int fThreadNum; // Identifying number for this thread. - ThreadInfo() { - fHeartBeat = false; - fCycles = 0; - fThreadNum = -1; - } -}; - - -// -//------------------------------------------------------------------------------ -// -// Global Data -// -//------------------------------------------------------------------------------ -RunInfo gRunInfo; -ThreadInfo *gThreadInfo; -UMTX gStopMutex; // Lets main thread suspend test threads. -UMTX gInfoMutex; // Synchronize access to data passed between - // worker threads and the main thread - - -//---------------------------------------------------------------------- -// -// parseCommandLine Read through the command line, and save all -// of the options in the gRunInfo struct. -// -// Display the usage message if the command line -// is no good. -// -// Probably ought to be a member function of RunInfo. -// -//---------------------------------------------------------------------- - -void parseCommandLine(int argc, char **argv) -{ - gRunInfo.quiet = false; // Set up defaults for run. - gRunInfo.verbose = false; - gRunInfo.numThreads = 2; - gRunInfo.totalTime = 0; - gRunInfo.checkTime = 10; - - try // Use exceptions for command line syntax errors. - { - int argnum = 1; - while (argnum < argc) - { - if (strcmp(argv[argnum], "-quiet") == 0) - gRunInfo.quiet = true; - else if (strcmp(argv[argnum], "-verbose") == 0) - gRunInfo.verbose = true; - else if (strcmp(argv[argnum], "--help") == 0 || - (strcmp(argv[argnum], "?") == 0)) {throw 1; } - - else if (strcmp(argv[argnum], "-threads") == 0) - { - ++argnum; - if (argnum >= argc) - throw 1; - gRunInfo.numThreads = atoi(argv[argnum]); - if (gRunInfo.numThreads < 0) - throw 1; - } - else if (strcmp(argv[argnum], "-time") == 0) - { - ++argnum; - if (argnum >= argc) - throw 1; - gRunInfo.totalTime = atoi(argv[argnum]); - if (gRunInfo.totalTime < 1) - throw 1; - } - else if (strcmp(argv[argnum], "-ctime") == 0) - { - ++argnum; - if (argnum >= argc) - throw 1; - gRunInfo.checkTime = atoi(argv[argnum]); - if (gRunInfo.checkTime < 1) - throw 1; - } - else if (strcmp(argv[argnum], "string") == 0) - { - gRunInfo.fTest = createStringTest(); - } - else if (strcmp(argv[argnum], "convert") == 0) - { - gRunInfo.fTest = createConvertTest(); - } - else - { - fprintf(stderr, "Unrecognized command line option. Scanning \"%s\"\n", - argv[argnum]); - throw 1; - } - argnum++; - } - // We've reached the end of the command line parameters. - // Fail if no test name was specified. - if (gRunInfo.fTest == NULL) { - fprintf(stderr, "No test specified.\n"); - throw 1; - } - - } - catch (int) - { - fprintf(stderr, "usage: threadtest [-threads nnn] [-time nnn] [-quiet] [-verbose] test-name\n" - " -quiet Suppress periodic status display. \n" - " -verbose Display extra messages. \n" - " -threads nnn Number of threads. Default is 2. \n" - " -time nnn Total time to run, in seconds. Default is forever.\n" - " -ctime nnn Time between extra consistency checks, in seconds. Default 10\n" - " testname string | convert\n" - ); - exit(1); - } -} - - - - - -//---------------------------------------------------------------------- -// -// threadMain The main function for each of the swarm of test threads. -// Run in a loop, executing the runOnce() test function each time. -// -// -//---------------------------------------------------------------------- - -extern "C" { - -void threadMain (void *param) -{ - ThreadInfo *thInfo = (ThreadInfo *)param; - - if (gRunInfo.verbose) - printf("Thread #%d: starting\n", thInfo->fThreadNum); - umtx_atomic_inc(&gRunInfo.runningThreads); - - // - // - while (true) - { - if (gRunInfo.verbose ) - printf("Thread #%d: starting loop\n", thInfo->fThreadNum); - - // - // If the main thread is asking us to wait, do so by locking gStopMutex - // which will block us, since the main thread will be holding it already. - // - umtx_lock(&gInfoMutex); - UBool stop = gRunInfo.stopFlag; // Need mutex for processors with flakey memory models. - umtx_unlock(&gInfoMutex); - - if (stop) { - if (gRunInfo.verbose) { - fprintf(stderr, "Thread #%d: suspending\n", thInfo->fThreadNum); - } - umtx_atomic_dec(&gRunInfo.runningThreads); - while (gRunInfo.stopFlag) { - umtx_lock(&gStopMutex); - umtx_unlock(&gStopMutex); - } - umtx_atomic_inc(&gRunInfo.runningThreads); - if (gRunInfo.verbose) { - fprintf(stderr, "Thread #%d: restarting\n", thInfo->fThreadNum); - } - } - - // - // The real work of the test happens here. - // - gRunInfo.fTest->runOnce(); - - umtx_lock(&gInfoMutex); - thInfo->fHeartBeat = true; - thInfo->fCycles++; - UBool exitNow = gRunInfo.exitFlag; - umtx_unlock(&gInfoMutex); - - // - // If main thread says it's time to exit, break out of the loop. - // - if (exitNow) { - break; - } - } - - umtx_atomic_dec(&gRunInfo.runningThreads); - - // Returning will kill the thread. - return; -} - -} - - - - -//---------------------------------------------------------------------- -// -// main -// -//---------------------------------------------------------------------- - -int main (int argc, char **argv) -{ - // - // Parse the command line options, and create the specified kind of test. - // - parseCommandLine(argc, argv); - - - // - // Fire off the requested number of parallel threads - // - - if (gRunInfo.numThreads == 0) - exit(0); - - gRunInfo.exitFlag = FALSE; - gRunInfo.stopFlag = TRUE; // Will cause the new threads to block - umtx_lock(&gStopMutex); - - gThreadInfo = new ThreadInfo[gRunInfo.numThreads]; - int threadNum; - for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) - { - gThreadInfo[threadNum].fThreadNum = threadNum; - ThreadFuncs::startThread(threadMain, &gThreadInfo[threadNum]); - } - - - unsigned long startTime = ThreadFuncs::getCurrentMillis(); - int elapsedSeconds = 0; - int timeSinceCheck = 0; - - // - // Unblock the threads. - // - gRunInfo.stopFlag = FALSE; // Unblocks the worker threads. - umtx_unlock(&gStopMutex); - - // - // Loop, watching the heartbeat of the worker threads. - // Each second, - // display "+" if all threads have completed at least one loop - // display "." if some thread hasn't since previous "+" - // Each "ctime" seconds, - // Stop all the worker threads at the top of their loop, then - // call the test's check function. - // - while (gRunInfo.totalTime == 0 || gRunInfo.totalTime > elapsedSeconds) - { - ThreadFuncs::Sleep(1000); // We sleep while threads do their work ... - - if (gRunInfo.quiet == false && gRunInfo.verbose == false) - { - char c = '+'; - int threadNum; - umtx_lock(&gInfoMutex); - for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) - { - if (gThreadInfo[threadNum].fHeartBeat == false) - { - c = '.'; - break; - }; - } - umtx_unlock(&gInfoMutex); - fputc(c, stdout); - fflush(stdout); - if (c == '+') - for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) - gThreadInfo[threadNum].fHeartBeat = false; - } - - // - // Update running times. - // - timeSinceCheck -= elapsedSeconds; - elapsedSeconds = (ThreadFuncs::getCurrentMillis() - startTime) / 1000; - timeSinceCheck += elapsedSeconds; - - // - // Call back to the test to let it check its internal validity - // - if (timeSinceCheck >= gRunInfo.checkTime) { - if (gRunInfo.verbose) { - fprintf(stderr, "Main: suspending all threads\n"); - } - umtx_lock(&gStopMutex); // Block the worker threads at the top of their loop - gRunInfo.stopFlag = TRUE; - for (;;) { - umtx_lock(&gInfoMutex); - UBool done = gRunInfo.runningThreads == 0; - umtx_unlock(&gInfoMutex); - if (done) { break;} - ThreadFuncs::yield(); - } - - - - gRunInfo.fTest->check(); - if (gRunInfo.quiet == false && gRunInfo.verbose == false) { - fputc('C', stdout); - } - - if (gRunInfo.verbose) { - fprintf(stderr, "Main: starting all threads.\n"); - } - gRunInfo.stopFlag = FALSE; // Unblock the worker threads. - umtx_unlock(&gStopMutex); - timeSinceCheck = 0; - } - }; - - // - // Time's up, we are done. (We only get here if this was a timed run) - // Tell the threads to exit. - // - gRunInfo.exitFlag = true; - for (;;) { - umtx_lock(&gInfoMutex); - UBool done = gRunInfo.runningThreads == 0; - umtx_unlock(&gInfoMutex); - if (done) { break;} - ThreadFuncs::yield(); - } - - // - // Tally up the total number of cycles completed by each of the threads. - // - double totalCyclesCompleted = 0; - for (threadNum=0; threadNum < gRunInfo.numThreads; threadNum++) { - totalCyclesCompleted += gThreadInfo[threadNum].fCycles; - } - - double cyclesPerMinute = totalCyclesCompleted / (double(gRunInfo.totalTime) / double(60)); - printf("\n%8.1f cycles per minute.", cyclesPerMinute); - - // - // Memory should be clean coming out - // - delete gRunInfo.fTest; - delete [] gThreadInfo; - umtx_destroy(&gInfoMutex); - umtx_destroy(&gStopMutex); - u_cleanup(); - - return 0; -} - -