summaryrefslogtreecommitdiff
path: root/performance-tests/Misc/context_switch_time.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'performance-tests/Misc/context_switch_time.cpp')
-rw-r--r--performance-tests/Misc/context_switch_time.cpp1320
1 files changed, 0 insertions, 1320 deletions
diff --git a/performance-tests/Misc/context_switch_time.cpp b/performance-tests/Misc/context_switch_time.cpp
deleted file mode 100644
index 0178b04c427..00000000000
--- a/performance-tests/Misc/context_switch_time.cpp
+++ /dev/null
@@ -1,1320 +0,0 @@
-// $Id$
-
-// ============================================================================
-//
-// = LIBRARY
-// (none)
-//
-// = FILENAME
-// context_switch_time.cpp
-//
-// = DESCRIPTION
-// Program that calculates context switch time between threads.
-// The Suspend-Resume test is based on the Task Context Switching
-// measurement approach described in:
-// Darren Cathey<br>
-// "RTOS Benchmarking -- All Things Considered . . ."<br>
-// <a href="http://www.realtime-info.be"><em>Real-Time Magazine</em></a>,
-// Second Quarter 1993,
-// <em>reprinted by <a href="http://www.wrs.com/artreqfm.html">Wind River
-// Systems</a></em><p>
-// which in turn is based on Superconducting Super Collider (SSC)
-// Laboratory Ping Suspend/Resume Task and Suspend/Resume Task benchmarks.
-// It measures two different times:
-// 1) The time to resume a blocked high priority task, which does
-// nothing other than block immediately. A lower priority task
-// resumes the high priority task, so the elapsed time includes
-// two context switches, one task suspend, and one task resume.
-// 2) The time to suspend and resume a low priority task that does
-// nothing. There is no context switching. This time is subtracted
-// from the one described in 1) above, and the result is divided by
-// two to yield the context switch time.
-//
-// Notes:
-// On Solaris 2.5.1, it appears that the lowest context switching times,
-// at least on a single-CPU machine, are obtained _without_ creating new
-// LWPs for new threads (THR_NEW_LWP). The -n option enables the use of
-// THR_NEW_LWP for testing.
-//
-// = CREATION DATE
-// 17 January 1997
-//
-// = AUTHOR
-// David L. Levine
-//
-// ============================================================================
-
-static const char usage [] = "[-? |\n"
- " [-c <repeat count, 0 means forever>]\n"
- " [-n to spawn a new LWP with each thread\n"
- "[<iterations>]]";
-
-#include "ace/Task.h"
-#include "ace/Sched_Params.h"
-#include "ace/Stats.h"
-#include "ace/High_Res_Timer.h"
-#include "ace/Get_Opt.h"
-#include "ace/Synch.h"
-
-ACE_RCSID(Misc, context_switch_time, "$Id$")
-
-#if defined (ACE_HAS_THREADS)
-
-#if !defined (DEBUG)
-# define DEBUG 0
-#endif /* DEBUG */
-
-static const u_int LOW_PRIORITY = ACE_THR_PRI_FIFO_DEF;
-static u_int HIGH_PRIORITY;
-
-// Global test configuration parameters.
-static ACE_UINT32 count = 1;
-static ACE_UINT32 num_iterations = 1000;
-static ACE_UINT32 new_lwp = 0;
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class Low_Priority_Null_Task
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class Low_Priority_Null_Task : public ACE_Task<ACE_MT_SYNCH>
-{
-public:
- Low_Priority_Null_Task ();
- virtual ~Low_Priority_Null_Task ();
-
- virtual int svc ();
-
- // Called by other task: it returns when this task is ready to
- // continue.
- void ready () { initialized_.acquire (); }
-
- void done ();
-
- ACE_hthread_t thread_id () const { return thread_id_; }
-private:
- ACE_hthread_t thread_id_;
- ACE_Semaphore initialized_; // Blocks until thread_id_ is assigned.
- ACE_Semaphore blocked_semaphore_;
-
- // Force proper construction of independent instances.
- Low_Priority_Null_Task (const Low_Priority_Null_Task &);
- Low_Priority_Null_Task &operator= (const Low_Priority_Null_Task &);
-};
-
-inline
-Low_Priority_Null_Task::Low_Priority_Null_Task() :
- ACE_Task<ACE_MT_SYNCH> (ACE_Thread_Manager::instance ()),
- initialized_ (0), // initialize to locked, then unlock when ready
- blocked_semaphore_ (0)
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Low_Priority_Null_Task ctor\n"));
-#endif /* DEBUG */
-
- if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
- 1, 0, LOW_PRIORITY))
- ACE_OS::perror ("activate");
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Low_Priority_Null_Task ctor, activated\n"));
-#endif /* DEBUG */
-}
-
-Low_Priority_Null_Task::~Low_Priority_Null_Task()
-{
-}
-
-int
-Low_Priority_Null_Task::svc ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Low_Priority_Null_Task::svc (), entering"));
-#endif /* DEBUG */
-
- ACE_Thread_Manager::instance ()->thr_self (thread_id_);
- initialized_.release ();
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id_));
-#endif /* DEBUG */
-
- // This task must never actually execute, so just have it block
- // on a semaphore forever . . .
- blocked_semaphore_.acquire ();
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Low_Priority_Task::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-void
-Low_Priority_Null_Task::done ()
-{
- blocked_semaphore_.release ();
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class Suspend_Resume_Test
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class Suspend_Resume_Test : public ACE_Task<ACE_MT_SYNCH>
-{
-public:
- Suspend_Resume_Test (const ACE_UINT32 iterations);
- virtual ~Suspend_Resume_Test ();
-
- virtual int svc ();
-
- ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
-private:
- const ACE_UINT32 iterations_;
-
- Low_Priority_Null_Task low_;
-
- ACE_High_Res_Timer timer_;
-
- ACE_hrtime_t elapsed_time_;
-
- // Force proper construction of independent instances.
- Suspend_Resume_Test ();
- Suspend_Resume_Test (const Suspend_Resume_Test &);
- Suspend_Resume_Test &operator= (const Suspend_Resume_Test &);
-};
-
-Suspend_Resume_Test::Suspend_Resume_Test (const ACE_UINT32 iterations) :
- ACE_Task<ACE_MT_SYNCH> (),
- iterations_ (iterations),
- low_ (),
- timer_ ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test ctor\n"));
-#endif /* DEBUG */
-
- if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
- 1, 0, HIGH_PRIORITY))
- ACE_OS::perror ("activate");
-}
-
-Suspend_Resume_Test::~Suspend_Resume_Test()
-{
-}
-
-int
-Suspend_Resume_Test::svc ()
-{
-#if DEBUG > 0
- ACE_hthread_t thread_id;
- ACE_Thread_Manager::instance ()->thr_self (thread_id);
-
- ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test::svc (), thread ID is %d\n",
- thread_id));
-#endif /* DEBUG */
-
- low_.ready ();
-
- // For information: the cost of the just the loop itself below,
- // without the suspend and resume calls, on a 166 MHz Ultrasparc
- // is about 12.3 nanoseconds per iteration.
-
- timer_.start ();
-
- for (ACE_UINT32 i = 0; i < iterations_; ++i)
- {
-#if DEBUG > 0
- if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
- ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test::svc (), iteration %u\n",
- i));
-#endif /* DEBUG */
-
- if (ACE_OS::thr_suspend (low_.thread_id ()) != 0)
- {
- ACE_ERROR ((LM_ERROR, "%p\n", "thr_suspend"));
- low_.done ();
- return -1;
- }
-
- if (ACE_OS::thr_continue (low_.thread_id ()) != 0 &&
- errno != EINVAL)
- // EINVAL is OK: it just means that the thread needs to be joined.
- {
- ACE_ERROR ((LM_ERROR, "%p\n", "thr_continue"));
- low_.done ();
- return -1;
- }
- }
-
- timer_.stop ();
- timer_.elapsed_microseconds (elapsed_time_);
-
- low_.done ();
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class High_Priority_Simple_Task
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class High_Priority_Simple_Task : public ACE_Task<ACE_MT_SYNCH>
-{
-public:
- High_Priority_Simple_Task ();
- virtual ~High_Priority_Simple_Task ();
-
- virtual int svc ();
-
- // called by other task: it returns when this task is ready to
- // continue
- void ready () { initialized_.acquire (); }
-
- void done ();
-
- ACE_hthread_t thread_id () const { return thread_id_; }
- ACE_UINT32 iterations () const { return iterations_; }
-private:
- ACE_hthread_t thread_id_;
- ACE_Semaphore initialized_; // Block until thread_id_ is assigned.
- int terminate_;
- ACE_UINT32 iterations_;
-
- // Force proper construction of independent instances.
- High_Priority_Simple_Task (const High_Priority_Simple_Task &);
- High_Priority_Simple_Task &operator= (const High_Priority_Simple_Task &);
-};
-
-inline
-High_Priority_Simple_Task::High_Priority_Simple_Task() :
- ACE_Task<ACE_MT_SYNCH> (ACE_Thread_Manager::instance ()),
- initialized_ (0), // Initialize to locked, then unlock when ready.
- terminate_ (0),
- iterations_ (0)
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task ctor\n"));
-#endif /* DEBUG */
-
- if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
- 1, 0, HIGH_PRIORITY))
- ACE_OS::perror ("activate");
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task ctor, activated\n"));
-#endif /* DEBUG */
-}
-
-High_Priority_Simple_Task::~High_Priority_Simple_Task()
-{
-}
-
-int
-High_Priority_Simple_Task::svc ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc (), entering"));
-#endif /* DEBUG */
-
- ACE_Thread_Manager::instance ()->thr_self (thread_id_);
- initialized_.release ();
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id_));
-#endif /* DEBUG */
-
- for (ACE_UINT32 i = 0; ! terminate_; ++i)
- {
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc, suspend self ("
- "%u)\n", thread_id_));
-#endif /* DEBUG */
-
- ++iterations_;
-
- // immediately suspend self
- if (ACE_OS::thr_suspend (thread_id_) != 0)
- {
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "thr_suspend"), -1);
- }
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc, resumed (%u)\n",
- thread_id_));
-#endif /* DEBUG */
- }
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-inline
-void
-High_Priority_Simple_Task::done ()
-{
- terminate_ = 1;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class Ping_Suspend_Resume_Test
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class Ping_Suspend_Resume_Test : public ACE_Task<ACE_MT_SYNCH>
-{
-public:
- Ping_Suspend_Resume_Test (const ACE_UINT32 iterations);
- virtual ~Ping_Suspend_Resume_Test ();
-
- virtual int svc ();
-
- ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
-private:
- const ACE_UINT32 iterations_;
-
- High_Priority_Simple_Task high_;
-
- ACE_High_Res_Timer timer_;
-
- ACE_hrtime_t elapsed_time_;
-
- // Force proper construction of independent instances.
- Ping_Suspend_Resume_Test ();
- Ping_Suspend_Resume_Test (const Ping_Suspend_Resume_Test &);
- Ping_Suspend_Resume_Test &operator= (const Ping_Suspend_Resume_Test &);
-};
-
-Ping_Suspend_Resume_Test::Ping_Suspend_Resume_Test (
- const ACE_UINT32 iterations)
-:
- ACE_Task<ACE_MT_SYNCH> (),
- iterations_ (iterations),
- high_ (),
- timer_ ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test ctor\n"));
-#endif /* DEBUG */
-
- if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
- 1, 0, LOW_PRIORITY))
- ACE_OS::perror ("activate");
-}
-
-Ping_Suspend_Resume_Test::~Ping_Suspend_Resume_Test()
-{
-}
-
-int
-Ping_Suspend_Resume_Test::svc ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc (), entering"));
-
- ACE_hthread_t thread_id;
- ACE_Thread_Manager::instance ()->thr_self (thread_id);
-
- ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id));
-#endif /* DEBUG */
-
- high_.ready ();
-
-#if DEBUG > 0
- int priority, high_priority;
- ACE_OS::thr_getprio (thread_id, priority);
- ACE_OS::thr_getprio (high_.thread_id (), high_priority);
- ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc (), priority is %d, "
- ", high thread priority is %d\n",
- priority, high_priority));
-#endif /* DEBUG */
-
- // For information: the cost of the just the loop itself below,
- // without the suspend and resume calls, on a 166 MHz Ultrasparc
- // is about 12.3 nanoseconds per iteration.
-
- timer_.start ();
-
- ACE_UINT32 i;
-
- for (i = 0; i < iterations_; ++i)
- {
-#if DEBUG > 0
- if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
- {
- ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc (), iteration "
- "%d, continue high-priority thread %u\n",
- i, high_.thread_id ()));
- }
-#endif /* DEBUG */
- if (ACE_OS::thr_continue (high_.thread_id ()) != 0 &&
- errno != EINVAL)
- // EINVAL is OK: it just means that the thread needs to be joined.
- {
- ACE_ERROR ((LM_ERROR, "%p\n", "thr_continue"));
- high_.done ();
- return -1;
- }
- }
-
- timer_.stop ();
- timer_.elapsed_microseconds (elapsed_time_);
-
- high_.done ();
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc: told high priority "
- "task to terminate\n"));
-#endif /* DEBUG */
-
- // Resume the thread until thr_continue fails, indicating that it has
- // finished.
- for (i = 0; i < 10000 && ! ACE_OS::thr_continue (high_.thread_id ());
- ++i) /* null */;
-
- // Don't count the one iteration that was used to allow the high-priority
- // thread to terminate.
- if (high_.iterations () < iterations_)
- ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test: high priority task "
- "executed only %u iterations!\n",
- high_.iterations ()));
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class Yield_Test
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class Yield_Test : public ACE_Task<ACE_MT_SYNCH>
-{
-public:
- Yield_Test (const ACE_UINT32 iterations);
- virtual ~Yield_Test ();
-
- virtual int svc ();
-
- ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
-private:
- const ACE_UINT32 iterations_;
-#if defined (VXWORKS)
- ACE_Thread_Mutex mutex_;
- u_int started_;
- u_int stopped_;
-#else /* ! VXWORKS */
- ACE_Barrier timer_barrier_;
-#endif /* ! VXWORKS */
- ACE_High_Res_Timer timer_;
- ACE_hrtime_t elapsed_time_;
-
- // Force proper construction of independent instances.
- Yield_Test ();
- Yield_Test (const Yield_Test &);
- Yield_Test &operator= (const Yield_Test &);
-};
-
-Yield_Test::Yield_Test (const ACE_UINT32 iterations) :
- ACE_Task<ACE_MT_SYNCH> (),
- iterations_ (iterations),
-#if defined (VXWORKS)
- mutex_ (),
- started_ (0),
- stopped_ (0),
-#else /* ! VXWORKS */
- timer_barrier_ (3),
-#endif /* ! VXWORKS */
- timer_ ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Yield_Test ctor\n"));
-#endif /* DEBUG */
-
-#if !defined (VXWORKS)
- timer_.start ();
-#endif /* ! VXWORKS */
-
- if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
- 2, 0, LOW_PRIORITY))
- ACE_OS::perror ("activate");
-
-#if !defined (VXWORKS)
- timer_barrier_.wait ();
- timer_.stop ();
-#endif /* ! VXWORKS */
-
- timer_.elapsed_microseconds (elapsed_time_);
-}
-
-Yield_Test::~Yield_Test()
-{
-}
-
-int
-Yield_Test::svc ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Yield_Test::svc (), entering"));
-
- ACE_hthread_t thread_id;
- ACE_Thread_Manager::instance ()->thr_self (thread_id);
-
- int priority;
- ACE_OS::thr_getprio (thread_id, priority);
-
- ACE_DEBUG ((LM_DEBUG, "; thread ID is %u, priority is %u\n", thread_id,
- priority));
-#endif /* DEBUG */
-
-#if defined (VXWORKS)
- // Start the timer, if it hasn't already been started.
- if (! started_)
- {
- // Double-check.
- ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
-
- if (! started_)
- {
- started_ = 1;
- timer_.start ();
- }
- }
-#endif /* VXWORKS */
-
- for (ACE_UINT32 i = 0; i < iterations_; ++i)
- {
-#if DEBUG > 0
- if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
- {
- ACE_DEBUG ((LM_DEBUG, "Yield_Test::svc () [%u], iteration %u\n",
- thread_id, i));
- }
-#endif /* DEBUG */
-
- ACE_OS::thr_yield ();
- }
-
-#if defined (VXWORKS)
- // Stop the timer, if it hasn't already been started.
- if (! stopped_)
- {
- // Maybe it would be better to read the clock before grabbing
- // the mutex. Then, only apply the clock reading below, instead
- // of reading the clock after grabbing the mutex.
-
- // Double-check.
- ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
-
- if (! stopped_)
- {
- stopped_ = 1;
- timer_.stop ();
- timer_.elapsed_time (elapsed_time_); /* nanoseconds */
- }
- }
-#else /* ! VXWORKS */
- timer_barrier_.wait ();
-#endif /* ! VXWORKS */
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Yield_Test::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class Mutex_Acquire_Release_Test
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class Mutex_Acquire_Release_Test
-{
-public:
- Mutex_Acquire_Release_Test (const ACE_UINT32 iterations);
- virtual ~Mutex_Acquire_Release_Test ();
-
- virtual int svc ();
-
- ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
-private:
- ACE_Thread_Mutex mutex_;
- // Mutex used for acquire/release time measurement.
-
- ACE_Thread_Semaphore sem_;
- // Semaphore used for acquire/release time measurement.
-
- const ACE_UINT32 iterations_;
-
- ACE_High_Res_Timer timer_;
-
- ACE_hrtime_t elapsed_time_;
-
- // Force proper construction of independent instances.
- Mutex_Acquire_Release_Test ();
- Mutex_Acquire_Release_Test (const Mutex_Acquire_Release_Test &);
- Mutex_Acquire_Release_Test &operator= (const Mutex_Acquire_Release_Test &);
-};
-
-Mutex_Acquire_Release_Test::Mutex_Acquire_Release_Test (
- const ACE_UINT32 iterations) :
- mutex_ (),
- sem_ (),
- iterations_ (iterations),
- timer_ ()
-{
-}
-
-Mutex_Acquire_Release_Test::~Mutex_Acquire_Release_Test()
-{
-}
-
-int
-Mutex_Acquire_Release_Test::svc ()
-{
-#if DEBUG > 0
- ACE_hthread_t thread_id;
- ACE_Thread_Manager::instance ()->thr_self (thread_id);
-
- ACE_DEBUG ((LM_DEBUG,
- "Mutex_Acquire_Release_Test::svc (), thread ID is %d\n",
- thread_id));
-#endif /* DEBUG */
-
- timer_.start ();
-
- for (ACE_UINT32 i = 0; i < iterations_; ++i)
- {
- // Block on the mutex.
- ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
-
- // Release the mutex so that the low priority thread can
- // proceed. The ACE_GUARD_RETURN macro implicity releases the
- // mutex.
- }
-
- timer_.stop ();
- timer_.elapsed_time (elapsed_time_); /* nanoseconds */
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Mutex_Acquire_Release_Test::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class High_Priority_Synchronized_Task
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class High_Priority_Synchronized_Task : public ACE_Task<ACE_MT_SYNCH>
-{
-public:
- High_Priority_Synchronized_Task (ACE_Thread_Semaphore &sem,
- ACE_Thread_Mutex &mutex,
- ACE_High_Res_Timer &timer);
- virtual ~High_Priority_Synchronized_Task ();
-
- virtual int svc ();
-
- void ready () { initialized_.acquire (); }
- // Called by other task: it returns when this task is ready to
- // continue
-
- void done ();
-
- ACE_UINT32 average_context_switch_time () const;
-
- ACE_hthread_t thread_id () const { return thread_id_; }
- ACE_UINT32 iterations () const { return iterations_; }
-private:
- ACE_hthread_t thread_id_;
- ACE_Semaphore initialized_; // Block until thread_id_ is assigned.
- int terminate_;
- ACE_UINT32 iterations_;
-
- ACE_Thread_Semaphore &sem_;
- // Semaphore used to resume the task.
-
- ACE_Thread_Mutex &mutex_;
- // Mutex used to block the task.
-
- ACE_High_Res_Timer &timer_;
- // Clock shared between low and high priority tasks.
-
- ACE_hrtime_t total_time_;
- // Running total context switch time, nsec.
-
- // Force proper construction of independent instances.
- High_Priority_Synchronized_Task ();
- High_Priority_Synchronized_Task (const High_Priority_Synchronized_Task &);
- High_Priority_Synchronized_Task &
- operator= (const High_Priority_Synchronized_Task &);
-};
-
-High_Priority_Synchronized_Task::High_Priority_Synchronized_Task (
- ACE_Thread_Semaphore &sem,
- ACE_Thread_Mutex &mutex,
- ACE_High_Res_Timer &timer) :
- ACE_Task<ACE_MT_SYNCH> (ACE_Thread_Manager::instance ()),
- initialized_ (0), // Initialize to locked, then unlock when ready.
- terminate_ (0),
- iterations_ (0),
- sem_ (sem),
- mutex_ (mutex),
- timer_ (timer),
- total_time_ (0)
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task ctor\n"));
-#endif /* DEBUG */
-
- if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
- 1, 0, HIGH_PRIORITY))
- ACE_OS::perror ("activate");
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task ctor, activated\n"));
-#endif /* DEBUG */
-}
-
-High_Priority_Synchronized_Task::~High_Priority_Synchronized_Task()
-{
-}
-
-int
-High_Priority_Synchronized_Task::svc ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task::svc (), entering"));
-#endif /* DEBUG */
-
- ACE_Thread_Manager::instance ()->thr_self (thread_id_);
-
- ACE_UINT32 mutex_acquire_release_time = 0;
- {
- Mutex_Acquire_Release_Test mutex_acquire_release_test (num_iterations);
- mutex_acquire_release_test.svc ();
- mutex_acquire_release_time =
- ACE_static_cast (ACE_UINT32,
- mutex_acquire_release_test.elapsed_time () /
- num_iterations);
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "mutex_acquire_release: %u nsec\n",
- mutex_acquire_release_time));
-#endif /* DEBUG */
- }
-
- initialized_.release ();
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id_));
-#endif /* DEBUG */
-
- for (ACE_UINT32 i = 0; ! terminate_; ++i)
- {
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG,
- "High_Priority_Synchronized_Task::svc, wait on sem ("
- "%u)\n", thread_id_));
-#endif /* DEBUG */
-
- if (sem_.acquire () != 0)
- {
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "sem_.acquire"), -1);
- }
-
- {
- // Block on the mutex.
- ACE_GUARD_RETURN (ACE_Thread_Mutex, guard, mutex_, -1);
-
- timer_.stop ();
-
- ++iterations_;
-
- ACE_hrtime_t nsec;
- timer_.elapsed_time (nsec);
- const ACE_UINT32 context_switch_time =
- ACE_U64_TO_U32 (nsec) >= mutex_acquire_release_time ?
- ACE_U64_TO_U32 (nsec) - mutex_acquire_release_time : 0;
-
- total_time_ += context_switch_time;
-
- // Release the mutex so that the low priority thread can
- // proceed. The ACE_GUARD_RETURN macro implicity releases the
- // mutex.
- }
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG,
- "High_Priority_Synchronized_Task::svc, resumed (%u)\n",
- thread_id_));
-#endif /* DEBUG */
- }
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-inline
-void
-High_Priority_Synchronized_Task::done ()
-{
- terminate_ = 1;
-}
-
-ACE_UINT32
-High_Priority_Synchronized_Task:: average_context_switch_time () const
-{
- return iterations_ > 0 ? ACE_static_cast (ACE_UINT32,
- total_time_ / iterations_)
- : 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// class Synchronized_Suspend_Resume_Test
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-class Synchronized_Suspend_Resume_Test : public ACE_Task<ACE_MT_SYNCH>
-{
-public:
- Synchronized_Suspend_Resume_Test (const ACE_UINT32 iterations);
- virtual ~Synchronized_Suspend_Resume_Test ();
-
- virtual int svc ();
-
- ACE_UINT32 average_context_switch_time ();
-
- ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
-private:
- const ACE_UINT32 iterations_;
-
- ACE_Thread_Semaphore sem_;
- // Used by the low priority thread to resume the high priority thread.
-
- ACE_Thread_Mutex mutex_;
- // Used by the low priority thread to block the high priority thread.
-
- ACE_High_Res_Timer timer_;
- // Clock shared between low and high priority tasks.
-
- High_Priority_Synchronized_Task high_;
- // The high priority task.
-
- ACE_hrtime_t elapsed_time_;
-
- ACE_UINT32 mutex_acquire_release_time_;
-
- // Force proper construction of independent instances.
- Synchronized_Suspend_Resume_Test ();
- Synchronized_Suspend_Resume_Test (const Synchronized_Suspend_Resume_Test &);
- Synchronized_Suspend_Resume_Test &
- operator= (const Synchronized_Suspend_Resume_Test &);
-};
-
-Synchronized_Suspend_Resume_Test::Synchronized_Suspend_Resume_Test (
- const ACE_UINT32 iterations)
-:
- ACE_Task<ACE_MT_SYNCH> (),
- iterations_ (iterations),
- sem_ (0),
- mutex_ (),
- timer_ (),
- high_ (sem_, mutex_, timer_),
- mutex_acquire_release_time_ (0)
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Synchronized_Suspend_Resume_Test ctor\n"));
-#endif /* DEBUG */
-
- if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
- 1, 0, LOW_PRIORITY))
- ACE_OS::perror ("activate");
-}
-
-Synchronized_Suspend_Resume_Test::~Synchronized_Suspend_Resume_Test()
-{
-}
-
-int
-Synchronized_Suspend_Resume_Test::svc ()
-{
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Synchronized_Suspend_Resume_Test::svc (), entering"));
-
- ACE_hthread_t thread_id;
- ACE_Thread_Manager::instance ()->thr_self (thread_id);
-
- ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id));
-#endif /* DEBUG */
-
- {
- Mutex_Acquire_Release_Test mutex_acquire_release_test (num_iterations);
- mutex_acquire_release_test.svc ();
- mutex_acquire_release_time_ =
- ACE_static_cast (ACE_UINT32,
- mutex_acquire_release_test.elapsed_time () /
- num_iterations);
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "mutex_acquire_release: %u nsec\n",
- mutex_acquire_release_time_));
-#endif /* DEBUG */
- }
-
- high_.ready ();
-
-#if DEBUG > 0
- int priority, high_priority;
- ACE_OS::thr_getprio (thread_id, priority);
- ACE_OS::thr_getprio (high_.thread_id (), high_priority);
- ACE_DEBUG ((LM_DEBUG,
- "Synchronized_Suspend_Resume_Test::svc (), priority is %d, "
- ", high thread priority is %d\n",
- priority, high_priority));
-#endif /* DEBUG */
-
- // For information: the cost of the just the loop itself below,
- // without the suspend and resume calls, on a 166 MHz Ultrasparc
- // is about 12.3 nanoseconds per iteration.
-
- ACE_UINT32 i;
-
- for (i = 0; i < iterations_; ++i)
- {
-#if DEBUG > 0
- if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
- {
- ACE_DEBUG ((LM_DEBUG,
- "Synchronized_Suspend_Resume_Test::svc (), iteration "
- "%d, continue high-priority thread %u\n",
- i, high_.thread_id ()));
- }
-#endif /* DEBUG */
-
- {
- // Acquire the mutex so that the high priority thread will
- // block after we signal it via the condition variable.
- ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
-
- // Release the semaphore so that the high priority thread can
- // proceed.
- if (sem_.release () != 0)
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "sem_.release"), -1);
-
- timer_.start ();
-
- // Release the mutex so that the high priority thread can
- // proceed. The ACE_GUARD_RETURN macro implicity releases
- // the mutex.
- }
- }
-
- high_.done ();
-
- // The high priority thread will be block on the semaphore, so
- // release it.
- if (sem_.release () != 0)
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "sem_.release"), -1);
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG,
- "Synchronized_Suspend_Resume_Test::svc: told high priority "
- "task to terminate\n"));
-#endif /* DEBUG */
-
- // Resume the thread until thr_continue fails, indicating that it has
- // finished.
- for (i = 0; i < 10000 && ! ACE_OS::thr_continue (high_.thread_id ());
- ++i) /* null */;
-
-#if DEBUG > 0
- ACE_DEBUG ((LM_DEBUG, "Synchronized_Suspend_Resume_Test::svc, finishing\n"));
-#endif /* DEBUG */
-
- return 0;
-}
-
-ACE_UINT32
-Synchronized_Suspend_Resume_Test::average_context_switch_time ()
-{
- return high_.average_context_switch_time ();
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// function get_options
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-static
-u_int
-get_options (int argc, char *argv[])
-{
- ACE_Get_Opt get_opt (argc, argv, "c:n?");
- int opt;
- while ((opt = get_opt ()) != EOF) {
- switch (opt) {
- case 'c':
- if (ACE_OS::atoi (get_opt.optarg) >= 0)
- {
- count = ACE_OS::atoi (get_opt.optarg);
- }
- else
- {
- ACE_DEBUG ((LM_ERROR, "%n: count must be >= 0\n"));
- return 1;
- }
- break;
- case 'n':
- new_lwp = THR_NEW_LWP;
- break;
- case '?':
- ACE_DEBUG ((LM_ERROR, "usage: %n %s\n%a", usage, 0));
- break;
- default:
- ACE_DEBUG ((LM_ERROR, "%n: unknown arg, %c\n", opt));
- ACE_DEBUG ((LM_ERROR, "usage: %n %s\n", usage));
- return 1;
- }
- }
-
- switch (argc - get_opt.optind) {
- case 0:
- // use default number of iterations
- break;
- case 1:
- if (ACE_OS::atoi (argv [get_opt.optind]) > 0)
- {
- num_iterations = ACE_OS::atoi (argv [get_opt.optind]);
- }
- else
- {
- ACE_DEBUG ((LM_ERROR, "%n: iterations must be > 0\n"));
- return 1;
- }
- break;
- default:
- ACE_DEBUG ((LM_ERROR, "%n: too many arguments\n"));
- ACE_DEBUG ((LM_ERROR, "usage: %n %s\n", usage));
- return 1;
- }
-
- return 0;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-// function main
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-int
-main (int argc, char *argv [])
-{
- ACE_LOG_MSG->open (argv[0] > 0 ? argv[0] : "context_switch_time");
-
- if (get_options (argc, argv))
- ACE_OS::exit (-1);
-
- // Disable LM_DEBUG.
- ACE_Log_Msg::instance ()->priority_mask (ACE_LOG_MSG->priority_mask () ^
- LM_DEBUG);
-
-#if defined (ACE_HAS_PENTIUM) && \
- !defined (ACE_HAS_HI_RES_TIMER) && !defined (ACE_WIN32)
- // Just to verify that ACE_High_Res_Timer::global_scale_factor ()
- // correctly determines the clock speed.
- ACE_DEBUG ((LM_INFO, "clock speed: %u MHz\n",
- ACE_High_Res_Timer::global_scale_factor ()));
-#endif /* ACE_HAS_PENTIUM && ! ACE_HAS_HI_RES_TIMER && ! ACE_WIN32 */
-
- if (ACE_OS::sched_params (
- ACE_Sched_Params (
- ACE_SCHED_FIFO,
- ACE_Sched_Params::priority_min (ACE_SCHED_FIFO),
- ACE_SCOPE_PROCESS)) != 0)
- {
- if (ACE_OS::last_error () == EPERM)
- {
- ACE_DEBUG ((LM_MAX, "context_switch_time: user is not superuser, "
- "so remain in time-sharing class\n"));
- }
- else
- {
- ACE_OS::perror ("context_switch_time");
- ACE_OS::exit (-1);
- }
- }
-
- HIGH_PRIORITY = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
- LOW_PRIORITY);
- ACE_DEBUG ((LM_INFO, "low priority: %d, high priority: %d\n",
- LOW_PRIORITY, HIGH_PRIORITY));
-
- // Set the priority of this thread so that it's higher than any of
- // the test threads. That might help avoid problems when waiting on
- // those threads, below. It also seems to help the times
- // significantly on LynxOS.
- ACE_hthread_t self;
- ACE_OS::thr_self (self);
- ACE_OS::thr_setprio (ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
- HIGH_PRIORITY));
-
- int forever = count == 0;
-
- ACE_Stats context_switch_test_stats;
- ACE_Stats yield_test_stats;
- ACE_Stats synchronized_suspend_resume_test_stats;
-
- int suspend_resume_supported = 0;
- // Check to see if thr_continue (), and therefore thr_suspend (),
- // probably, are supported.
- if (ACE_OS::thr_continue (self) == 0 || errno != ENOTSUP)
- suspend_resume_supported = 1;
-
- while (forever || count-- > 0)
- {
- if (suspend_resume_supported)
- {
- // Run suspend/resume test first . . .
- Suspend_Resume_Test suspend_resume_test (num_iterations);
- // Wait for all tasks to exit.
- ACE_Thread_Manager::instance ()->wait ();
-
- // Then Ping Suspend/Resume test.
- Ping_Suspend_Resume_Test ping_suspend_resume_test (num_iterations);
- // Wait for all tasks to exit.
- ACE_Thread_Manager::instance ()->wait ();
-
- if (ping_suspend_resume_test.elapsed_time () >
- suspend_resume_test.elapsed_time ())
- {
- context_switch_test_stats.
- sample (ACE_U64_TO_U32 (
- ping_suspend_resume_test.elapsed_time () -
- suspend_resume_test.elapsed_time ()));
-
- ACE_DEBUG ((LM_INFO, "context switch time is (%.3f - %.3f)/2 = "
- "%.3f microseconds\n",
- (double) ACE_UINT64_DBLCAST_ADAPTER (
- ping_suspend_resume_test.elapsed_time ()) /
- num_iterations,
- (double) ACE_UINT64_DBLCAST_ADAPTER (
- suspend_resume_test.elapsed_time ()) /
- num_iterations,
- (double) ACE_UINT64_DBLCAST_ADAPTER (
- ping_suspend_resume_test.elapsed_time () -
- suspend_resume_test.elapsed_time ()) /
- num_iterations / 2u));
- }
- else
- {
- ACE_DEBUG ((LM_INFO, "ping suspend/resume time of %u usec was "
- "less than suspend/resume time of %u\n",
- ping_suspend_resume_test.elapsed_time () /
- num_iterations,
- suspend_resume_test.elapsed_time () /
- num_iterations));
- }
- }
-
-#if !defined (VXWORKS)
- // Then Yield test.
- Yield_Test yield_test (num_iterations);
- // Wait for all tasks to exit.
- ACE_Thread_Manager::instance ()->wait ();
-
- yield_test_stats.sample (ACE_U64_TO_U32 (yield_test.elapsed_time ()));
-
- // Try _really_ hard not to use floating point.
- ACE_DEBUG ((LM_INFO, "context switch time from yield test is %u.%03u "
- "microseconds\n",
- (ACE_UINT32)
- (yield_test.elapsed_time () / num_iterations / 2u),
- (ACE_UINT32)
- (yield_test.elapsed_time () % (num_iterations * 2u)) *
- 1000u / num_iterations / 2u));
-#endif /* ! VXWORKS */
-
- Synchronized_Suspend_Resume_Test
- synchronized_suspend_resume_test (num_iterations);
- // Wait for all tasks to exit.
- ACE_Thread_Manager::instance ()->wait ();
-
- synchronized_suspend_resume_test_stats.sample (
- synchronized_suspend_resume_test.average_context_switch_time ());
-
- ACE_DEBUG ((LM_INFO, "context switch time from synch susp/resume test "
- "is %u.%03u microseconds\n",
- synchronized_suspend_resume_test.
- average_context_switch_time () / 1000u,
- synchronized_suspend_resume_test.
- average_context_switch_time () % 1000u));
-
- // Give, e.g., Draft 4 Posix platforms a chance to cleanup threads.
- const ACE_Time_Value half_sec (0L, 500000L);
- ACE_OS::sleep (half_sec);
- }
-
- if (suspend_resume_supported)
- {
- ACE_OS::printf ("suspend-resume test: ");
- context_switch_test_stats.print_summary (3, num_iterations * 2u);
- }
-
-#if !defined (VXWORKS)
- ACE_OS::printf ("\nyield_test: ");
- yield_test_stats.print_summary (3, num_iterations * 2u);
-#endif /* ! VXWORKS */
-
- ACE_OS::printf ("\nsynchronized suspend-resume test: ");
- synchronized_suspend_resume_test_stats.print_summary (3,
- 1000u /* nsec/usec */);
-
- return 0;
-}
-#else
-int
-main (int, char *[])
-{
- ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
- return 0;
-}
-#endif /* ACE_HAS_THREADS */
-
-
-// EOF