summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Cleeland <chris.cleeland@gmail.com>2007-01-03 22:36:23 +0000
committerChris Cleeland <chris.cleeland@gmail.com>2007-01-03 22:36:23 +0000
commit1eb2cd7af4556c39dcd17045f05cd18279bfa4cb (patch)
tree6b246ecd5901bef5c0af9981d78609ad1c1573a6
parentd0ea0eddf73a559b1fdcf722b5c408cdb9b95b9b (diff)
downloadATCD-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/ChangeLog35
-rw-r--r--ACE/NEWS5
-rw-r--r--ACE/ace/OS_NS_Thread.cpp2
-rw-r--r--ACE/ace/README11
-rw-r--r--ACE/ace/config-sunos5.9.h1
-rw-r--r--ACE/tests/Thread_Creation_Threshold_Test.cpp230
-rw-r--r--ACE/tests/run_test.lst1
-rw-r--r--ACE/tests/tests.mpc7
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):
diff --git a/ACE/NEWS b/ACE/NEWS
index b80339fce75..62982370e75 100644
--- a/ACE/NEWS
+++ b/ACE/NEWS
@@ -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 {