diff options
author | Chris Cleeland <chris.cleeland@gmail.com> | 2007-01-03 22:36:23 +0000 |
---|---|---|
committer | Chris Cleeland <chris.cleeland@gmail.com> | 2007-01-03 22:36:23 +0000 |
commit | 1eb2cd7af4556c39dcd17045f05cd18279bfa4cb (patch) | |
tree | 6b246ecd5901bef5c0af9981d78609ad1c1573a6 | |
parent | d0ea0eddf73a559b1fdcf722b5c408cdb9b95b9b (diff) | |
download | ATCD-1eb2cd7af4556c39dcd17045f05cd18279bfa4cb.tar.gz |
ChangeLogTag: Wed Jan 3 22:31:05 UTC 2007 Chris Cleeland <cleeland_c@ociweb.com>
Merged in RT 8678 from OCITAO related to thr_*_concurrency() changes from
Solaris 9 onwards.
M ACE/ace/OS_NS_Thread.cpp
M ACE/ace/config-sunos5.9.h
M ACE/ace/README
M ACE/tests/run_test.lst
M ACE/tests/tests.mpc
AM ACE/tests/Thread_Creation_Threshold_Test.cpp
M ACE/NEWS
M ACE/ChangeLog
-rw-r--r-- | ACE/ChangeLog | 35 | ||||
-rw-r--r-- | ACE/NEWS | 5 | ||||
-rw-r--r-- | ACE/ace/OS_NS_Thread.cpp | 2 | ||||
-rw-r--r-- | ACE/ace/README | 11 | ||||
-rw-r--r-- | ACE/ace/config-sunos5.9.h | 1 | ||||
-rw-r--r-- | ACE/tests/Thread_Creation_Threshold_Test.cpp | 230 | ||||
-rw-r--r-- | ACE/tests/run_test.lst | 1 | ||||
-rw-r--r-- | ACE/tests/tests.mpc | 7 |
8 files changed, 292 insertions, 0 deletions
diff --git a/ACE/ChangeLog b/ACE/ChangeLog index 19cc4cc216d..7cef163b240 100644 --- a/ACE/ChangeLog +++ b/ACE/ChangeLog @@ -1,3 +1,38 @@ +Wed Jan 3 22:31:05 UTC 2007 Chris Cleeland <cleeland_c@ociweb.com> + + This entry merges in changes from OCITAO 1.4a which were + originally part of RT 8678. + + * ace/README: + * ace/config-sunos5.9.h: + + Added new compiler macro, ACE_LACKS_THR_CONCURRENCY_FUNCS, to + accomodate the deprecation of thr_concurrency() in Solaris 9 + onwards. The functions still exist, but the call semantics have + changed slightly such that values for which they would + previously succeed now fail despite the fact that they are + effectively no-ops in Solaris >= 9. This would cause + thr_create(THR_NEW_LWP) to fail in a process when invoked for + the 65536th (or greater) time. + + Currently this macro is only defined on Solaris 9+, but, since I + believ this function was only ever present on Solaris anyway, it + could probably be defined in general, and simply #undef'd on + Solaris 8 and prior. + + * ace/OS_NS_Thread.cpp (thr_create): + + Conditionally removed THR_NEW_LWP section when + ACE_LACKS_THR_CONCURRENCY_FUNCS is defined. + + * tests/Thread_Creation_Threshold_Test.cpp: + * tests/run_test.lst: + * tests/tests.mpc: + + Added a new test to check the threshold of thread creation. + This simply verifies that more than 2^15 threads can be created + sequentially (not simultaneously). + Wed Jan 3 22:10:54 UTC 2007 Chris Cleeland <cleeland_c@ociweb.com> * ace/CDR_Stream.inl (adjust): @@ -17,6 +17,11 @@ PLANNED CHANGES FOR "ACE-5.5.5" USER VISIBLE CHANGES BETWEEN ACE-5.5.4 and ACE-5.5.5 ==================================================== +. Fixed a problem where, on Solaris 9 onwards, calling + ACE_OS::thr_create(THR_NEW_LWP) more than 2^15 (65535) times in a + process will fail. See changelog entry from "Wed Jan 3 22:31:05 UTC + 2007 Chris Cleeland <cleeland_c@ociweb.com>" for more information. + . Fixed a bug in ACE_QtReactor where the two select() calls in that function might select on different handler sets. diff --git a/ACE/ace/OS_NS_Thread.cpp b/ACE/ace/OS_NS_Thread.cpp index 6e7e97d748f..dd8283c40de 100644 --- a/ACE/ace/OS_NS_Thread.cpp +++ b/ACE/ace/OS_NS_Thread.cpp @@ -4241,6 +4241,7 @@ ACE_OS::thr_create (ACE_THR_FUNC func, } # endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */ +# if ! defined(ACE_LACKS_THR_CONCURRENCY_FUNCS) if (ACE_BIT_ENABLED (flags, THR_NEW_LWP)) { // Increment the number of LWPs by one to emulate the @@ -4267,6 +4268,7 @@ ACE_OS::thr_create (ACE_THR_FUNC func, return -1; } } +# endif /* ! ACE_LACKS_THR_CONCURRENCY_FUNCS */ } # if defined (ACE_HAS_PTHREADS_DRAFT4) diff --git a/ACE/ace/README b/ACE/ace/README index c36e8defe3e..cc2ccf1cfcd 100644 --- a/ACE/ace/README +++ b/ACE/ace/README @@ -1111,6 +1111,17 @@ ACE_LACKS_TELLDIR Platform uses ACE_HAS_DIRENT ACE_LACKS_THREAD_STACK_SIZE Platform lacks pthread_attr_setstacksize() (e.g., Linux pthreads) +ACE_LACKS_THR_CONCURRENCY_FUNCS (ONLY APPLIES TO SOLARIS) + Platform does not support + thr_getconcurrency/thr_setconcurrency + functions, or their implementation + is effectively a "no-op". This + notably applies for Solaris >= 5.9. + Note that if you build on Solaris 8 + and run on Solaris 9+, you can + encounter thread creation errors + unless you rebuild on the target + platform. ACE_LACKS_TIMEDWAIT_PROTOTYPES MIT pthreads platform lacks the timedwait prototypes ACE_LACKS_TIMESPEC_T Platform does not define diff --git a/ACE/ace/config-sunos5.9.h b/ACE/ace/config-sunos5.9.h index fd2cdd82acb..42043928fec 100644 --- a/ACE/ace/config-sunos5.9.h +++ b/ACE/ace/config-sunos5.9.h @@ -13,5 +13,6 @@ #include "ace/config-sunos5.8.h" #define ACE_HAS_SENDFILE +#define ACE_LACKS_THR_CONCURRENCY_FUNCS #endif /* ACE_CONFIG_H */ diff --git a/ACE/tests/Thread_Creation_Threshold_Test.cpp b/ACE/tests/Thread_Creation_Threshold_Test.cpp new file mode 100644 index 00000000000..7145b5350be --- /dev/null +++ b/ACE/tests/Thread_Creation_Threshold_Test.cpp @@ -0,0 +1,230 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Thread_Creation_Threshold_Test.cpp +// +// = DESCRIPTION +// This test program stresses how many threads can be +// consecutively (not simultaneously) created on a platform. +// Rather than testing exhaustively, it establishes a +// semi-arbitrary upper limit (MAX_THREAD)of threads. The limit +// is only partly arbitrary because it was chosen as a value that +// exceeded an observed upper limit on the values that Solaris 9 +// will accept as arguments to thr_concurrency(), used by +// ACE_OS::thr_create(THR_NEW_LWP). +// +// = AUTHOR +// Chris Cleeland <cleeland@ociweb.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Task.h" + +ACE_RCSID(tests, Thread_Pool_Test, "$Id$") + +#if defined (ACE_HAS_THREADS) +#include "ace/Lock_Adapter_T.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_unistd.h" + +// Number of iterations to run the test. +const int THREADS_PER_POOL = 1000; +const unsigned long MAX_THREAD = 100000; + +namespace +{ + // Change this to 'true' if you want lots of debugging messages in the log + const bool DEBUG = true; +}; + +class Thread_Pool : public ACE_Task<ACE_MT_SYNCH> +{ + // = TITLE + // Defines a thread pool abstraction based on the <ACE_Task>. +public: + Thread_Pool (int n_threads); + // Create the thread pool containing <n_threads>. + + ~Thread_Pool (void); + // Destructor... + + virtual int svc (void); + // Iterate <n_iterations> time printing off a message and "waiting" + // for all other threads to complete this iteration. + + void start(); + // Start the threads in the pool. + + unsigned long total_threads() + { + return this->total_activated_threads_.value(); + } + + int n_threads_; + // Number of threads to spawn. + + bool operator! (); + // Returns true iff failed_ == false. + +private: + virtual int open (void * = 0); + // Spawn the threads in the pool. + + virtual int close (u_long); + // Close hook. + + ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> total_activated_threads_; + // Total number of threads activated through this thread pool ever. + + bool doprint_; + // Flag set only in worker threads to indicate whether they should print + // debug messages. + + bool failed_; + // Flag indicating that start() failed. +}; + +bool +Thread_Pool::operator!() +{ + return ! this->failed_; +} + +Thread_Pool::~Thread_Pool (void) +{ +} + +int +Thread_Pool::close (u_long) +{ + if (this->doprint_) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) worker thread closing down\n"))); + return 0; +} + +Thread_Pool::Thread_Pool (int n_threads) + : n_threads_ (n_threads) + , total_activated_threads_ (0) + , doprint_ (false) + , failed_ (false) +{ +} + +void +Thread_Pool::start () +{ + this->failed_ = false; + if (this->open () == -1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) thread activation ") + ACE_TEXT ("failed after %u threads\n"), + this->total_threads())); + this->failed_ = true; + } +} + +int +Thread_Pool::svc (void) +{ + unsigned long t = ++this->total_activated_threads_; + if (DEBUG) // change this to 'true' for debugging + this->doprint_ = (t > 65530); + + if (this->doprint_) + ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" (%P|%t) thread started.\n"))); + + // Note that the <ACE_Task::svc_run> method automatically removes us + // from the <ACE_Thread_Manager> when the thread exits. + return 0; +} + +namespace { + void no_op() { } +}; + +int +Thread_Pool::open (void *) +{ + if (DEBUG) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) pool start %d threads..."), + this->n_threads_)); + + if (this->total_activated_threads_ >= (65534 - this->n_threads_)) + no_op (); + + // Create a pool of worker threads. + if (this->activate (THR_NEW_LWP, + this->n_threads_) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("activate failed")), + -1); + + return 0; +} + +#endif /* ACE_HAS_THREADS */ + + +int +run_main (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("Thread_Creation_Threshold_Test")); + +#if defined (ACE_HAS_THREADS) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) will try to start and kill up") + ACE_TEXT (" to %u threads sequentially\n"), + MAX_THREAD)); + int initial_pool_size = 50; + + // Create the worker tasks. + Thread_Pool thread_pool (initial_pool_size); + + while (!thread_pool && thread_pool.total_threads() < MAX_THREAD) + { + // Activate the task's thread pool, produce the messages that are, + // produce the messages that are consumed by the threads in the + // thread pool, and demonstrate how to shutdown by enqueueing + // "empty" messages into the queue. + thread_pool.start (); + + // Wait for all the threads to reach their exit point, at which + // point the barrier in the destructor of the <ACE_Task> portion of + // <Thread_Pool> will return. + if (thread_pool.wait () == -1) + return 1; + + if (DEBUG) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%u total threads\n"), + thread_pool.total_threads())); + + int& n_threads = thread_pool.n_threads_; + const unsigned long THREAD_THRESHOLD = 63336; + if (thread_pool.total_threads() >= (THREAD_THRESHOLD - n_threads)) + n_threads = 1; + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%u total threads successfully started and died;") + ACE_TEXT (" expected %u.\n"), + thread_pool.total_threads (), + MAX_THREAD)); +#else + ACE_ERROR ((LM_INFO, + ACE_TEXT ("threads not supported on this platform\n"))); +#endif /* ACE_HAS_THREADS */ + ACE_END_TEST; + return 0; +} diff --git a/ACE/tests/run_test.lst b/ACE/tests/run_test.lst index c381737cb05..4568e8ba530 100644 --- a/ACE/tests/run_test.lst +++ b/ACE/tests/run_test.lst @@ -151,6 +151,7 @@ Thread_Mutex_Test: !DISABLE_ToFix_LynxOS_PPC Thread_Pool_Reactor_Resume_Test: !DISABLE_ToFix_LynxOS_PPC !ST Thread_Pool_Reactor_Test: !DISABLE_ToFix_LynxOS_PPC Thread_Pool_Test: !DISABLE_ToFix_LynxOS_PPC +Thread_Creation_Threshold_Test Time_Service_Test: !STATIC !DISABLED !missing_netsvcs TOKEN !Unicos Time_Value_Test Timeprobe_Test diff --git a/ACE/tests/tests.mpc b/ACE/tests/tests.mpc index 4b6a8b01990..64b74caa8aa 100644 --- a/ACE/tests/tests.mpc +++ b/ACE/tests/tests.mpc @@ -999,6 +999,13 @@ project(Thread Pool Test) : acetest { } } +project(Thread Creation Threshold Test) : acetest { + exename = Thread_Creation_Threshold_Test + Source_Files { + Thread_Creation_Threshold_Test.cpp + } +} + project(Timeprobe Test) : acetest { exename = Timeprobe_Test Source_Files { |