Index: include/rw_thread.h =================================================================== --- include/rw_thread.h (revision 654243) +++ include/rw_thread.h (working copy) @@ -32,8 +32,6 @@ #include -extern "C" { - struct rw_thread_attr_t; struct rw_thread_t @@ -43,12 +41,16 @@ void* handle; // thread handle }; +extern "C" { + typedef void* (*rw_thread_proc_t)(void*); +} // extern "C" + // same as POSIX pthread_create() _TEST_EXPORT int rw_thread_create (rw_thread_t*, rw_thread_attr_t*, - void* (*)(void*), + rw_thread_proc_t, void*); @@ -64,21 +66,33 @@ // returned from each thread // if (nthreads == SIZE_MAX), sets nthreads to the positive result // of rw_get_processors() plus 1, or to 2 otherwise +// if (timeout != 0), then a timer will be started, and the function +// rw_thread_pool_timeout_expired() will return true after that number +// of seconds has passed. there is only one timer, so use timeouts +// with caution. if you provide tidarray, you should join threads +// before starting another pool, otherwise threads from the first +// pool may not exit until the threads from a later second pool are +// signalled to stop. // returns 0 on success, or a non-zero value indicating the thread // number that failed to create on error _TEST_EXPORT int rw_thread_pool (rw_thread_t* /* tidarray */, _RWSTD_SIZE_T /* nthreads */, rw_thread_attr_t* /* attr */, - void* (*)(void*) /* thr_proc */, - void** /* argarray */); + rw_thread_proc_t /* thr_proc */, + void** /* argarray */, + _RWSTD_SIZE_T /* timeout */ = 0); +// returns non-zero if the thread timeout flag has been set. should +// be polled periodically by threads created by rw_thread_pool() so +// that they know that the soft timeout has expired +// see notes above for details +_TEST_EXPORT int +rw_thread_pool_timeout_expired (); + // returns the number of logical processors/cores on the system, // or -1 on error _TEST_EXPORT int rw_get_cpus (); - -} // extern "C" - #endif // RW_RWTHREAD_H_INCLUDED Index: localization/22.locale.codecvt.mt.cpp =================================================================== --- localization/22.locale.codecvt.mt.cpp (revision 654243) +++ localization/22.locale.codecvt.mt.cpp (working copy) @@ -45,19 +45,22 @@ // default number of threads (will be adjusted to the number // of processors/cores later) -int rw_opt_nthreads = 1; +int opt_nthreads = 1; // the number of times each thread should iterate (unless specified // otherwise on the command line) -int rw_opt_nloops = 5000; +int opt_nloops = 5000; // number of locales to use -int rw_opt_nlocales = MAX_THREADS; +int opt_nlocales = MAX_THREADS; // should all threads share the same set of locale objects instead // of creating their own? -int rw_opt_shared_locale; +int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -314,15 +317,18 @@ const int ni = RW_COUNT_OF (nsrc); const int wi = RW_COUNT_OF (wsrc); - for (int i = 0; i != rw_opt_nloops; ++i) { + for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + const int inx = i % nlocales; const MyCodecvtData& data = my_codecvt_data [inx]; // construct a named locale, get a reference to the codecvt // facet from it and use it to format a random money value const std::locale loc = - rw_opt_shared_locale ? data.locale_ + opt_shared_locale ? data.locale_ : std::locale (data.locale_name_); const MyCodecvtData::CvtId op = @@ -460,7 +466,7 @@ run_test_fill (loc, wsrc [inx % wi], nsrc [inx % ni], data.wchar_data_); - if (rw_opt_shared_locale) + if (opt_shared_locale) data.locale_ = loc; nlocales += 1; @@ -471,7 +477,7 @@ "failed to create locale(%#s)", name); } - if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales)) + if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales)) break; } @@ -482,8 +488,8 @@ rw_info (0, 0, 0, "testing std::codecvt with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", - rw_opt_nthreads, 1 != rw_opt_nthreads, - rw_opt_nloops, 1 != rw_opt_nloops, + opt_nthreads, 1 != opt_nthreads, + opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); /////////////////////////////////////////////////////////////////////// @@ -495,11 +501,12 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); /////////////////////////////////////////////////////////////////////// @@ -509,11 +516,12 @@ test_wchar = true; result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); /////////////////////////////////////////////////////////////////////// @@ -524,11 +532,12 @@ test_wchar = true; result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); return result; } @@ -541,24 +550,26 @@ // set nthreads to the greater of the number of processors // and 2 (for uniprocessor systems) by default - rw_opt_nthreads = rw_get_cpus (); - if (rw_opt_nthreads < 2) - rw_opt_nthreads = 2; + opt_nthreads = rw_get_cpus (); + if (opt_nthreads < 2) + opt_nthreads = 2; #endif // _RWSTD_REENTRANT return rw_test (argc, argv, __FILE__, "lib.locale.codecvt", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", - &rw_opt_nloops, + &opt_timeout, + &opt_nloops, int (MAX_THREADS), - &rw_opt_nthreads, - &rw_opt_nlocales, + &opt_nthreads, + &opt_nlocales, &rw_opt_setlocales, - &rw_opt_shared_locale); + &opt_shared_locale); } Index: localization/22.locale.cons.mt.cpp =================================================================== --- localization/22.locale.cons.mt.cpp (revision 654243) +++ localization/22.locale.cons.mt.cpp (working copy) @@ -50,6 +50,9 @@ // command line option int opt_combine; +// default timeout used by each threaded section of this test +int opt_timeout = 120; + /**************************************************************************/ // array of locale names to use for testing @@ -85,6 +88,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // compute an index into the array of locales const std::size_t linx = i % nlocales; @@ -183,7 +189,7 @@ // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - test_ctors, 0); + test_ctors, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -210,10 +216,12 @@ "lib.locale.cons", "thread safety", run_test, "|-combine~ " + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-locales=", // must be provided &opt_combine, + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.ctype.mt.cpp =================================================================== --- localization/22.locale.ctype.mt.cpp (revision 654243) +++ localization/22.locale.ctype.mt.cpp (working copy) @@ -66,6 +66,9 @@ // of creating their own? int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -118,6 +121,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + const std::size_t inx = std::size_t (i) % nlocales; // save the name of the locale @@ -260,7 +266,8 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -276,7 +283,8 @@ // start a pool of threads to exercise the thread safety // of the wchar_t specialization result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -293,7 +301,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -321,11 +330,13 @@ return rw_test (argc, argv, __FILE__, "lib.locale.ctype", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // arg must be non-negative "|-nthreads#0-* " // arg must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // arg must be provided "|-shared-locale# ", + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.globals.mt.cpp =================================================================== --- localization/22.locale.globals.mt.cpp (revision 654243) +++ localization/22.locale.globals.mt.cpp (working copy) @@ -73,6 +73,9 @@ // disable exceptions? int opt_no_exceptions; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -149,6 +152,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // save the name of the locale const char* const locale_name = locales [i % nlocales]; @@ -395,6 +401,10 @@ const std::locale classic (std::locale::classic ()); for (int i = 0; i != opt_nloops; ++i) { + + if (rw_thread_pool_timeout_expired ()) + break; + try { use_facet_loop (classic, i); } @@ -510,7 +520,7 @@ // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - test_has_facet, 0); + test_has_facet, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -554,7 +564,7 @@ // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - test_use_facet, 0); + test_use_facet, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -586,6 +596,7 @@ "thread safety", run_test, "|-has_facet~ " "|-use_facet~ " + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // arg must be non-negative "|-nthreads#0-* " // arg must be in [0, MAX_THREADS] "|-locales= " // argument must be provided @@ -605,6 +616,7 @@ "|-time_put~ ", &opt_has_facet, &opt_use_facet, + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.messages.mt.cpp =================================================================== --- localization/22.locale.messages.mt.cpp (revision 654243) +++ localization/22.locale.messages.mt.cpp (working copy) @@ -54,6 +54,9 @@ // otherwise on the command line) int opt_nloops = 10000; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + #if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32) // number of locales to use @@ -196,6 +199,9 @@ for (int i = 0; i < opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + const MyMessageData& data = my_message_data [i % nlocales]; // construct a named locale, get a reference to the money_get @@ -409,7 +415,7 @@ int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - thread_func, 0); + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -426,7 +432,7 @@ result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - thread_func, 0); + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -442,7 +448,7 @@ result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - thread_func, 0); + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -474,9 +480,11 @@ return rw_test (argc, argv, __FILE__, "lib.locale.messages", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-ncatalogs#0-* " // must be non-negative "|-nthreads#0-* ", // must be in [0, MAX_THREADS] + &opt_timeout, &opt_nloops, int (MAX_CATALOGS), &opt_ncatalogs, Index: localization/22.locale.money.get.mt.cpp =================================================================== --- localization/22.locale.money.get.mt.cpp (revision 654243) +++ localization/22.locale.money.get.mt.cpp (working copy) @@ -67,6 +67,9 @@ // of creating their own? int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -176,6 +179,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // save the name of the locale const MyMoneyData& data = my_money_data [i % nlocales]; @@ -464,11 +470,13 @@ return rw_test (argc, argv, __FILE__, "lib.locale.money.get", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.money.put.mt.cpp =================================================================== --- localization/22.locale.money.put.mt.cpp (revision 654243) +++ localization/22.locale.money.put.mt.cpp (working copy) @@ -67,6 +67,9 @@ // of creating their own? int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -184,6 +187,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // save the name of the locale const MyMoneyData& data = my_money_data [i % nlocales]; @@ -409,7 +415,8 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -424,7 +431,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -442,7 +450,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -470,11 +479,13 @@ return rw_test (argc, argv, __FILE__, "lib.locale.money.put", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.moneypunct.mt.cpp =================================================================== --- localization/22.locale.moneypunct.mt.cpp (revision 654243) +++ localization/22.locale.moneypunct.mt.cpp (working copy) @@ -43,15 +43,18 @@ // default number of threads (will be adjusted to the number // of processors/cores later) -int rw_opt_nthreads = 1; +int opt_nthreads = 1; // the default number of times for each thread to iterate #define DFLT_LOOPS 10000 // the number of times each thread should iterate (will be set to // DFLT_LOOPS unless explicitly specified on the command line) -int rw_opt_nloops = -1; +int opt_nloops = -1; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // number of locales to test @@ -240,8 +243,11 @@ static void* thread_func (void*) { - for (int i = 0; i != rw_opt_nloops; ++i) { + for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + thread_loop_body (std::size_t (i)); } @@ -388,13 +394,13 @@ // unless the number of iterations was explicitly specified // on the command line, decrease the number to equal the number // of excericsed locales when only one thread is being tested - if (1 == rw_opt_nthreads && rw_opt_nloops < 0) - rw_opt_nloops = int (nlocales); + if (1 == opt_nthreads && opt_nloops < 0) + opt_nloops = int (nlocales); // when the number of iterations wasn't explicitly specified // on the command line set it to the default value - if (rw_opt_nloops < 0) - rw_opt_nloops = DFLT_LOOPS; + if (opt_nloops < 0) + opt_nloops = DFLT_LOOPS; rw_fatal (0 < nlocales, 0, __LINE__, "must have at least one valid locale to test"); @@ -402,8 +408,8 @@ rw_info (0, 0, 0, "testing std::moneypunct with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", - rw_opt_nthreads, 1 != rw_opt_nthreads, - rw_opt_nloops, 1 != rw_opt_nloops, + opt_nthreads, 1 != opt_nthreads, + opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::moneypunct"); @@ -413,11 +419,12 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T @@ -429,11 +436,12 @@ // start a pool of threads to exercise the thread safety // of the wchar_t specialization result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time @@ -447,11 +455,12 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T @@ -466,20 +475,22 @@ // set nthreads to the greater of the number of processors // and 2 (for uniprocessor systems) by default - rw_opt_nthreads = rw_get_cpus (); - if (rw_opt_nthreads < 2) - rw_opt_nthreads = 2; + opt_nthreads = rw_get_cpus (); + if (opt_nthreads < 2) + opt_nthreads = 2; #endif // _RWSTD_REENTRANT return rw_test (argc, argv, __FILE__, "lib.locale.moneypunct", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-locales=", // must be provided - &rw_opt_nloops, + &opt_timeout, + &opt_nloops, int (MAX_THREADS), - &rw_opt_nthreads, + &opt_nthreads, &rw_opt_setlocales); } Index: localization/22.locale.num.get.mt.cpp =================================================================== --- localization/22.locale.num.get.mt.cpp (revision 654247) +++ localization/22.locale.num.get.mt.cpp (working copy) @@ -64,6 +64,9 @@ // of creating their own? int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -342,6 +345,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // fill in the value and results for this locale const MyNumData& data = my_num_data [i % nlocales]; @@ -564,11 +570,13 @@ return rw_test (argc, argv, __FILE__, "lib.locale.num.get", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.num.put.mt.cpp =================================================================== --- localization/22.locale.num.put.mt.cpp (revision 654243) +++ localization/22.locale.num.put.mt.cpp (working copy) @@ -64,6 +64,9 @@ // of creating their own? int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -238,6 +241,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // fill in the value and results for this locale const MyNumData& data = my_num_data [i % nlocales]; @@ -394,7 +400,8 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -409,7 +416,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -426,7 +434,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -454,11 +463,13 @@ return rw_test (argc, argv, __FILE__, "lib.locale.num.put", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.numpunct.mt.cpp =================================================================== --- localization/22.locale.numpunct.mt.cpp (revision 654243) +++ localization/22.locale.numpunct.mt.cpp (working copy) @@ -47,7 +47,7 @@ // the number of times each thread should iterate (unless specified // otherwise on the command line) -int rw_opt_nloops = 200000; +int opt_nloops = 200000; #if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32) @@ -66,6 +66,9 @@ // of creating their own? int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -111,8 +114,11 @@ static void* thread_func (void*) { - for (int i = 0; i != rw_opt_nloops; ++i) { + for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + const std::size_t inx = std::size_t (i) % nlocales; const NumPunctData& data = punct_data[inx]; @@ -250,7 +256,7 @@ "testing std::numpunct with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, - rw_opt_nloops, 1 != rw_opt_nloops, + opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::numpunct"); @@ -260,7 +266,8 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -276,7 +283,8 @@ // start a pool of threads to exercise the thread safety // of the wchar_t specialization result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -293,7 +301,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -321,12 +330,14 @@ return rw_test (argc, argv, __FILE__, "lib.locale.numpunct", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", - &rw_opt_nloops, + &opt_timeout, + &opt_nloops, int (MAX_THREADS), &opt_nthreads, &opt_nlocales, Index: localization/22.locale.statics.mt.cpp =================================================================== --- localization/22.locale.statics.mt.cpp (revision 654243) +++ localization/22.locale.statics.mt.cpp (working copy) @@ -47,6 +47,9 @@ // otherwise on the command line) int opt_nloops = 20000; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + int opt_classic; int opt_global; @@ -92,6 +95,9 @@ { for (std::size_t i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + const std::size_t inx = i % nlocales; const std::locale last (std::locale::global (locales [inx])); @@ -125,7 +131,7 @@ // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - test_classic, 0); + test_classic, 0, opt_timeout); } if (rw_note (0 <= opt_global, 0, __LINE__, @@ -161,7 +167,7 @@ // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, - test_global, 0); + test_global, 0, opt_timeout); } return result; @@ -187,11 +193,13 @@ run_test, "|-classic~ " "|-global~ " + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // arg must be non-negative "|-nthreads#0-* " // arg must be in [0, MAX_THREADS] "|-locales= ", // argument must be provided &opt_classic, &opt_global, + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: localization/22.locale.time.get.mt.cpp =================================================================== --- localization/22.locale.time.get.mt.cpp (revision 654243) +++ localization/22.locale.time.get.mt.cpp (working copy) @@ -43,18 +43,21 @@ // default number of threads (will be adjusted to the number // of processors/cores later) -int rw_opt_nthreads = 1; +int opt_nthreads = 1; // the number of times each thread should iterate -int rw_opt_nloops = 50000; +int opt_nloops = 50000; // number of locales to use -int rw_opt_nlocales = MAX_THREADS; +int opt_nlocales = MAX_THREADS; // should all threads share the same set of locale objects instead // of creating their own? -int rw_opt_shared_locale; +int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -162,8 +165,11 @@ std::ios_base::iostate state = std::ios_base::goodbit; std::tm local; - for (int i = 0; i != rw_opt_nloops; ++i) { + for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // save the name of the locale const MyTimeData& data = my_time_data [i % nlocales]; @@ -171,8 +177,8 @@ // facet from it and use it to format a random time value // using a random conversion specifier const std::locale loc = - rw_opt_shared_locale ? data.locale_ - : std::locale (data.locale_name_); + opt_shared_locale ? data.locale_ + : std::locale (data.locale_name_); if (test_char) { // exercise the narrow char specialization of the facet @@ -420,7 +426,7 @@ #endif // _RWSTD_NO_WCHAR_T - if (rw_opt_shared_locale) + if (opt_shared_locale) data.locale_ = loc; nlocales += 1; @@ -431,7 +437,7 @@ "failed to create locale(%#s)", name); } - if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales)) + if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales)) break; } @@ -442,8 +448,8 @@ rw_info (0, 0, 0, "testing std::time_get with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", - rw_opt_nthreads, 1 != rw_opt_nthreads, - rw_opt_nloops, 1 != rw_opt_nloops, + opt_nthreads, 1 != opt_nthreads, + opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::time_get"); @@ -453,11 +459,12 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T @@ -468,11 +475,12 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time @@ -485,11 +493,12 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", - rw_opt_nthreads, thread_func); + opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T @@ -504,24 +513,26 @@ // set nthreads to the greater of the number of processors // and 2 (for uniprocessor systems) by default - rw_opt_nthreads = rw_get_cpus (); - if (rw_opt_nthreads < 2) - rw_opt_nthreads = 2; + opt_nthreads = rw_get_cpus (); + if (opt_nthreads < 2) + opt_nthreads = 2; #endif // _RWSTD_REENTRANT return rw_test (argc, argv, __FILE__, "lib.locale.time.get", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", - &rw_opt_nloops, + &opt_timeout, + &opt_nloops, int (MAX_THREADS), - &rw_opt_nthreads, - &rw_opt_nlocales, + &opt_nthreads, + &opt_nlocales, &rw_opt_setlocales, - &rw_opt_shared_locale); + &opt_shared_locale); } Index: localization/22.locale.time.put.mt.cpp =================================================================== --- localization/22.locale.time.put.mt.cpp (revision 654243) +++ localization/22.locale.time.put.mt.cpp (working copy) @@ -67,6 +67,9 @@ // of creating their own? int opt_shared_locale; +// default timeout used by each threaded section of this test +int opt_timeout = 60; + /**************************************************************************/ // array of locale names to use for testing @@ -157,6 +160,9 @@ for (int i = 0; i != opt_nloops; ++i) { + if (rw_thread_pool_timeout_expired ()) + break; + // save the name of the locale const MyTimeData& data = my_time_data [i % nlocales]; @@ -331,7 +337,8 @@ // create and start a pool of threads and wait for them to finish int result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -346,7 +353,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -363,7 +371,8 @@ // start a pool of threads to exercise wstring thread safety result = - rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); + rw_thread_pool (0, std::size_t (opt_nthreads), 0, + thread_func, 0, opt_timeout); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", @@ -391,11 +400,13 @@ return rw_test (argc, argv, __FILE__, "lib.locale.time.put", "thread safety", run_test, + "|-soft-timeout#0 " // must be non-negative "|-nloops#0 " // must be non-negative "|-nthreads#0-* " // must be in [0, MAX_THREADS] "|-nlocales#0 " // arg must be non-negative "|-locales= " // must be provided "|-shared-locale# ", + &opt_timeout, &opt_nloops, int (MAX_THREADS), &opt_nthreads, Index: src/thread.cpp =================================================================== --- src/thread.cpp (revision 654243) +++ src/thread.cpp (working copy) @@ -30,6 +30,9 @@ #define _RWSTD_TEST_SRC #include +#include // for rw_alarm() +#include // for rw_warn() + #include // for size_t #include // for memset() @@ -48,20 +51,42 @@ #endif // _RWSTD_NO_PURE_C_HEADERS + /**************************************************************************/ static long maxthreads; +/************************************************************************/ +static volatile int +_rw_timeout_expired = 0; + +/************************************************************************/ + +_TEST_EXPORT int +rw_thread_pool_timeout_expired () +{ + return _rw_timeout_expired != 0; +} + +/************************************************************************/ + +static void +_rw_timeout_handler (int) +{ + _rw_timeout_expired = 1; +} + +/************************************************************************/ + + #if defined (_RWSTD_POSIX_THREADS) # include -extern "C" { - _TEST_EXPORT int rw_thread_create (rw_thread_t *thr_id, rw_thread_attr_t*, - void* (*thr_proc)(void*), + rw_thread_proc_t thr_proc, void *thr_arg) { #ifdef _RWSTD_OS_SUNOS @@ -109,19 +134,15 @@ return result; } -} // extern "C" - /**************************************************************************/ #elif defined (_RWSTD_SOLARIS_THREADS) # include -extern "C" { - _TEST_EXPORT int rw_thread_create (rw_thread_t *thr_id, rw_thread_attr_t*, - void* (*thr_proc)(void*), + rw_thread_proc_t thr_proc, void *thr_arg) { static int concurrency_set; @@ -170,8 +191,6 @@ return result; } -} // extern "C" - /**************************************************************************/ #elif defined (_RWSTD_DEC_THREADS) @@ -179,13 +198,10 @@ # include # include - -extern "C" { - _TEST_EXPORT int rw_thread_create (rw_thread_t *thr_id, rw_thread_attr_t*, - void* (*thr_proc)(void*), + rw_thread_proc_t thr_proc, void *thr_arg) { rw_thread_t tmpid; @@ -244,19 +260,15 @@ return status; } -} // extern "C" - /**************************************************************************/ #elif defined (_WIN32) && defined (_MT) # include // for _beginthreadex() -extern "C" { - _TEST_EXPORT int rw_thread_create (rw_thread_t *thr_id, rw_thread_attr_t*, - void* (*thr_proc)(void*), + rw_thread_proc_t thr_proc, void *thr_arg) { int result = 0; @@ -324,8 +336,6 @@ return result; } -} // extern "C" - /**************************************************************************/ #else // unknown/missing threads environment @@ -352,12 +362,10 @@ # endif # endif // ENOTSUP -extern "C" { - _TEST_EXPORT int rw_thread_create (rw_thread_t*, rw_thread_attr_t*, - void* (*)(void*), + rw_thread_proc_t, void*) { _RWSTD_UNUSED (maxthreads); @@ -372,8 +380,6 @@ return ENOTSUP; } -} // extern "C" - #endif // threads environment /**************************************************************************/ @@ -471,16 +477,20 @@ /**************************************************************************/ -extern "C" { - - _TEST_EXPORT int rw_thread_pool (rw_thread_t *thr_id, size_t nthrs, rw_thread_attr_t*, - void* (*thr_proc)(void*), - void* *thr_arg) + rw_thread_proc_t thr_proc, + void* *thr_arg, + size_t timeout) { + // apply timeout if one was specified + if (0 != timeout) { + _rw_timeout_expired = 0; + rw_alarm (timeout, _rw_timeout_handler); + } + // small buffer for thread ids when invoked with (thr_id == 0) rw_thread_t id_buf [16]; @@ -575,5 +585,3 @@ return 0; } - -} // extern "C"