summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsergio <sergio@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-04-15 17:17:57 +0000
committersergio <sergio@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-04-15 17:17:57 +0000
commit760dfb3e6f33d74a68e132feeebe94745e9c4073 (patch)
treeaf7e3d31fd7ed10f0d778f6867e61a7d5e539549
parent7bd7fd7cfbd248b30263c23968542bcfb0113da5 (diff)
downloadATCD-760dfb3e6f33d74a68e132feeebe94745e9c4073.tar.gz
*** empty log message ***
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile16
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp232
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h58
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp106
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h4
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp5
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/Makefile16
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.cpp232
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.h58
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/client.cpp106
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/client.h4
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.cpp277
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.h56
-rw-r--r--TAO/tests/Cubit/TAO/MT_Cubit/server.cpp5
14 files changed, 1007 insertions, 168 deletions
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile
index 2db17eadaee..c9979b080b2 100644
--- a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile
@@ -30,13 +30,14 @@ CUBIT_SVR_OBJS = \
server.o \
cubit_i.o \
tmplinst.o
+
CUBIT_CLIENT_OBJS = \
cubitC.o \
cubitS.o \
Task_Client.o \
client.o \
Util_Thread.o \
- tmplinst.o
+ tmplinst.o
BIN = server client
BUILD = $(BIN)
@@ -62,7 +63,16 @@ include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
LDFLAGS += -L$(TAO_ROOT)/tao -L$(TAO_ROOT)/orbsvcs
CPPFLAGS += -I$(TAO_ROOT) -I$(TAO_ROOT)/orbsvcs -I$(TAO_ROOT)/tao/compat
-##POSTLINK += -lnk="-n -T $(VME_ROOT)/src/act/slots/act_s2.ld"
+
+# pccTimer will eventually get integrated into ACE. It is specific for ClassiX on VME
+ifdef CHORUS
+ SRC += pccTimer.cpp
+ CLT_OBJS += pccTimer.o
+ LDLIBS += -lOrb
+else
+ LDLIBS += -lOrb-mt
+endif
+
.PRECIOUS: cubitC.h cubitC.i cubitC.cpp cubitS.h cubitS.i cubitS.cpp
server: $(addprefix $(VDIR),$(CUBIT_SVR_OBJS))
@@ -70,7 +80,7 @@ server: $(addprefix $(VDIR),$(CUBIT_SVR_OBJS))
client: $(addprefix $(VDIR),$(CUBIT_CLIENT_OBJS))
$(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
-## -lnk="-n -T $(VME_ROOT)/src/act/slots/act_s2.ld"
+
clean:
-/bin/rm -rf *.o Log $(BIN) obj.* core Templates.DB .make.state
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
index b064265112b..782345ee83f 100644
--- a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
@@ -17,16 +17,19 @@ Task_State::Task_State (int argc, char **argv)
oneway_ (0),
use_name_service_ (1),
ior_file_ (0),
- use_sysbench_ (0)
+ grain_ (1),
+ context_switch_ (0)
{
- ACE_Get_Opt opts (argc, argv, "sn:t:d:rk:xof:y");
+ ACE_Get_Opt opts (argc, argv, "sn:t:d:rk:xof:g:");
int c;
int datatype;
while ((c = opts ()) != -1)
switch (c) {
- case 'y':
- use_sysbench_ = 1;
+ case 'g':
+ grain_ = ACE_OS::atoi (opts.optarg);
+ if (grain_ < 1)
+ grain_ = 1;
break;
case 's':
use_name_service_ = 0;
@@ -86,6 +89,7 @@ Task_State::Task_State (int argc, char **argv)
" [-x] // makes a call to servant to shutdown"
" [-o] // makes client use oneway calls instead"
" [-s] // makes client *NOT* use the name service"
+ " [-g granularity_of_request_timing]"
"\n", argv [0]));
}
@@ -130,12 +134,14 @@ Client::Client (Task_State *ts)
void
Client::put_latency (double *jitter,
double latency,
- u_int thread_id)
+ u_int thread_id,
+ u_int context_switch)
{
ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, ts_->lock_));
ts_->latency_[thread_id] = latency;
ts_->global_jitter_array_[thread_id] = jitter;
+ ts_->context_switch_ += context_switch;
#if defined (ACE_LACKS_FLOATING_POINT)
ACE_DEBUG ((LM_DEBUG,
@@ -540,6 +546,7 @@ Client::run_tests (Cubit_ptr cb,
u_int i = 0;
u_int call_count = 0;
u_int error_count = 0;
+ u_int context_switch = 0;
double *my_jitter_array;
ACE_NEW_RETURN (my_jitter_array,
@@ -550,6 +557,10 @@ Client::run_tests (Cubit_ptr cb,
double sleep_time = (1 / frequency) * (1000 * 1000);
double delta = 0;
+ int pstartTime = 0;
+ int pstopTime = 0;
+ double real_time = 0.0;
+
#if defined (USE_QUANTIFY)
quantify_stop_recording_data();
quantify_clear_data ();
@@ -559,21 +570,26 @@ Client::run_tests (Cubit_ptr cb,
for (i = 0; i < loop_count; i++)
{
+ ACE_Profile_Timer timer_for_context_switch;
ACE_High_Res_Timer timer_;
ACE_Time_Value tv (0, (long int) (sleep_time - delta));
ACE_OS::sleep (tv);
-
+
// Elapsed time will be in microseconds.
ACE_Time_Value delta_t;
-
- // use sysBench when CHORUS defined and option specified on command line
-#if defined (CHORUS)
- if (ts_->use_sysbench_ == 1)
- timer_.start (ACE_OS::ACE_HRTIMER_START);
- else
-#endif /* CHORUS */
- timer_.start ();
-
+
+#if defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)
+ ACE_Profile_Timer timer_for_context_switch;
+ ACE_Profile_Timer::Rusage usage;
+ timer_for_context_switch.start ();
+#endif /* ACE_HAS_PRUSAGE_T || ACE_HAS_GETRUSAGE */
+
+#if defined (CHORUS)
+ pstartTime = pccTime1Get();
+#else /* CHORUS */
+ timer_.start ();
+#endif /* !CHORUS */
+
if (ts_->oneway_ == 0)
{
switch (datatype)
@@ -763,35 +779,41 @@ Client::run_tests (Cubit_ptr cb,
}
}
- // use sysBench when CHORUS defined and option specified on command line
-#if defined (CHORUS)
- if (ts_->use_sysbench_ == 1)
- timer_.stop (ACE_OS::ACE_HRTIMER_STOP);
- else
-#endif /* CHORUS */
+#if defined (CHORUS)
+ if ( (loop_count % ts_->grain_) == 0)
+ pstopTime = pccTime1Get();
+#else /* CHORUS */
// if CHORUS is not defined just use plain timer_.stop ().
- timer_.stop ();
-
+ timer_.stop ();
timer_.elapsed_time (delta_t);
+#endif /* !CHORUS */
- double real_time = 0.0;
+#if defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)
+ timer_for_context_switch.stop ();
+ timer_for_context_switch.elapsed_rusage (usage);
+ // Add up the voluntary context switches & involuntary context switches
+ context_switch += usage.pr_vctx + usage.pr_ictx;
+#endif /* ACE_HAS_PRUSAGE_T || ACE_HAS_GETRUSAGE */
-#if !defined (ACE_HAS_PRUSAGE_T) && !defined (ACE_HAS_GETRUSAGE) && defined (ACE_LACKS_FLOATING_POINT)
+ // Calculate time elapsed
+#if defined (ACE_LACKS_FLOATING_POINT)
+# if defined (CHORUS)
+ real_time = pstopTime - pstartTime;
+ my_jitter_array [i/ts_->grain_] = real_time; // in units of microseconds.
+ // update the latency array, correcting the index using the granularity
+# else /* CHORUS */
// Store the time in usecs.
real_time = delta_t.sec () * ACE_ONE_SECOND_IN_USECS +
- delta_t.usec ();
-
+ delta_t.usec ();
+ my_jitter_array [i] = real_time; // in units of microseconds.
+# endif /* !CHORUS */
delta = ((40 * fabs (real_time) / 100) + (60 * delta / 100)); // pow(10,6)
latency += real_time;
- my_jitter_array [i] = real_time; // in units of microseconds.
-#else
- // Store the time in secs.
- real_time = delta_t.sec () + (double)delta_t.usec () / ACE_ONE_SECOND_IN_USECS;
-
- delta = ((40 * fabs (real_time * (1000 * 1000)) / 100) + (60 * delta / 100)); // pow(10,6)
+#else /* ACE_LACKS_FLOATING_POINT */
+ delta = ((0.4 * fabs (real_time * (1000 * 1000))) + (0.6 * delta)); // pow(10,6)
latency += real_time;
my_jitter_array [i] = real_time * 1000;
-#endif /* !defined (ACE_HAS_PRUSAGE_T) && !defined (ACE_HAS_GETRUSAGE) && defined (ACE_LACKS_FLOATING_POINT) */
+#endif /* !ACE_LACKS_FLOATING_POINT */
}
if (call_count > 0)
@@ -813,7 +835,10 @@ Client::run_tests (Cubit_ptr cb,
latency,
calls_per_second));
- this->put_latency (my_jitter_array, latency, thread_id);
+ this->put_latency (my_jitter_array,
+ latency,
+ thread_id,
+ context_switch);
#else
ACE_DEBUG ((LM_DEBUG,
"(%P|%t) cube average call ACE_OS::time\t= %f msec, \t"
@@ -822,7 +847,8 @@ Client::run_tests (Cubit_ptr cb,
1 / latency));
this->put_latency (my_jitter_array,
latency * 1000,
- thread_id);
+ thread_id,
+ context_switch);
#endif /* ! ACE_LACKS_FLOATING_POINT */
}
else
@@ -830,7 +856,8 @@ Client::run_tests (Cubit_ptr cb,
// still we have to call this function to store a valid array pointer.
this->put_latency (my_jitter_array,
0,
- thread_id);
+ thread_id,
+ context_switch);
ACE_DEBUG ((LM_DEBUG,
"*** Warning: Latency is less than or equal to zero."
" Precision may have been lost.\n"));
@@ -845,3 +872,134 @@ Client::run_tests (Cubit_ptr cb,
// cb->please_exit (env);
return 0;
}
+
+
+/////////////////////////////////////////////////////////////////////////
+// = DESCRIPTION
+// Program that calculates context switch time between threads.
+// This 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)
+// Ping Suspend/Resume Task and Suspend/Resume Task benchmarks.
+// Laboratory benchmark
+// It measures two different times:
+// 1) the time to resume a block 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.
+//
+// On Solaris 2.5.1, real-time threads must be bound to LWPs (using the
+// THR_BOUND flag), so that they can compete for system-wide resources.
+// In other words, if a thread is bound to an LWP, then the kernel is
+// aware of it.
+//
+// On Solaris 2.5.1, a call to thr_yield () is necessary after a call
+// to thr_continue () by a low-priority task. Without it, the high-priority
+// task doesn't preempt the low-priority task. This happens even with a
+// 10 nsec time quantum for the LWP. Maybe it's because with this version
+// of Solaris, the scheduling policy is SCHED_OTHER.
+//
+// All threads are created with the THR_DETACHED flag so that their
+// resources are released when they terminate.
+//
+// = CREATION DATE
+// 17 January 1997
+//
+// = AUTHOR
+// David L. Levine
+//
+// ============================================================================
+
+
+Yield_Test::Yield_Test (const unsigned long iterations) :
+ ACE_Task<ACE_MT_SYNCH> (),
+ iterations_ (iterations),
+ timer_barrier_ (3),
+ timer_ ()
+{
+ timer_.start ();
+
+ this->activate (THR_BOUND | THR_DETACHED | new_lwp, 2, 0, LOW_PRIORITY);
+
+ timer_barrier_.wait ();
+
+ timer_.stop ();
+ timer_.elapsed_microseconds (elapsed_time_);
+}
+
+Yield_Test::~Yield_Test()
+{
+}
+
+int
+Yield_Test::svc ()
+{
+ for (unsigned long i = 0; i < iterations_; ++i)
+ {
+ ACE_OS::thr_yield ();
+ }
+
+ timer_barrier_.wait ();
+
+ return 0;
+}
+
+double
+context_switch_time (void)
+{
+ const u_int iterations = 1000;
+ const u_int retries = 100;
+ double tmp = 0;
+ // Disable LM_DEBUG
+ ACE_Log_Msg::instance ()->priority_mask (ACE_LOG_MSG->priority_mask () ^
+ LM_DEBUG);
+
+ 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);
+ }
+ }
+
+ for (u_int i=0; i<100; i++)
+ {
+ LOW_PRIORITY = ACE_Sched_Params::priority_min (ACE_SCHED_FIFO);
+ HIGH_PRIORITY = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
+ LOW_PRIORITY);
+
+ // then Yield test
+ Yield_Test yield_test (iterations);
+ // Wait for all tasks to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ tmp += (double) (yield_test.elapsed_time ()/ (ACE_UINT32) 1u) /iterations /2;
+ }
+ return tmp/retries;
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h
index 5e36a39edf0..534270e81bd 100644
--- a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h
@@ -23,12 +23,26 @@
#include "ace/Get_Opt.h"
#include "ace/Profile_Timer.h"
#include "ace/ARGV.h"
+#include "ace/Sched_Params.h"
+#include "ace/Task.h"
+#include "ace/High_Res_Timer.h"
#include "orbsvcs/CosNamingC.h"
#include "cubitC.h"
+#if defined (CHORUS)
+#include "pccTimer.h"
+#endif /* CHORUS */
+
#include <math.h>
+static unsigned int LOW_PRIORITY;
+static unsigned int HIGH_PRIORITY;
+
+// global test configuration parameters
+static unsigned long num_iterations = 1000;
+static unsigned int new_lwp = 0;
+
// @@ Should we put this into a more general file, e.g., OS.h?
//
// I will integrate this, together with the sqrt() function when
@@ -160,9 +174,14 @@ public:
char *ior_file_;
// Name of the filename that the server used to store the iors.
- u_int use_sysbench_;
- // flag that indicates that we are going to use the sysBench() call
- // to time calls. This only applies to the CHORUS ClassiX OS.
+ u_int grain_;
+ // this is the granularity of the timing of the CORBA requests. A
+ // value of 5 represents that we will take time every 5 requests,
+ // instead of the default of every request (1).
+
+ u_int context_switch_;
+ // stores the total number of context switches incurred by the
+ // program while making CORBA requests
};
class Client : public ACE_Task<ACE_SYNCH>
@@ -197,7 +216,8 @@ private:
void put_latency (double *jitter,
double latency,
- u_int);
+ u_int thread_id,
+ u_int context_switch);
// Records the latencies in the <Task_State>.
int parse_args (int, char **);
@@ -213,4 +233,34 @@ private:
// Object reference to the cubit context "MT_Cubit".
};
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Yield_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Yield_Test : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Yield_Test (const unsigned long iterations);
+ virtual ~Yield_Test ();
+
+ virtual int svc ();
+
+ ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
+private:
+ const unsigned long iterations_;
+ ACE_Barrier timer_barrier_;
+ 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 &);
+};
+
+double
+context_switch_time (void);
+
#endif /* !defined (TASK_CLIENT_H) */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp
index bc54d42718c..5e1a58a1666 100644
--- a/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp
@@ -39,6 +39,8 @@ initialize (void)
int
do_priority_inversion_test (Task_State &ts)
{
+ u_int i;
+
// Create the clients.
Client high_priority_client (&ts);
Client low_priority_client (&ts);
@@ -72,8 +74,10 @@ do_priority_inversion_test (Task_State &ts)
"activate failed",
priority));
- u_int i;
-
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating 1 client with high priority of %d\n",
+ priority));
+
// Drop the priority, so that the priority of clients will increase
// with increasing client number.
for (i = 0; i < ts.thread_count_; i++)
@@ -82,9 +86,10 @@ do_priority_inversion_test (Task_State &ts)
ACE_SCOPE_THREAD);
ACE_DEBUG ((LM_DEBUG,
- "Creating %d clients with low priority of %d\n",
+ "Creating %d clients with low priority ranging from %d to %d\n",
ts.thread_count_ - 1,
- priority));
+ priority,
+ priority + ts.thread_count_ - 2));
for (i = 0; i < ts.thread_count_ - 1; i++)
{
@@ -111,7 +116,8 @@ do_priority_inversion_test (Task_State &ts)
ACE_OS::printf ("Test done.\n"
"High priority client latency : %d usec\n"
"Low priority client latency : %d usec\n",
- high_priority_client.get_high_priority_latency (),
+
+ high_priority_client.get_high_priority_latency (),
low_priority_client.get_low_priority_latency ());
#elif defined (CHORUS)
ACE_OS::printf ("Test done.\n"
@@ -126,47 +132,49 @@ do_priority_inversion_test (Task_State &ts)
FILE *latency_file_handle = 0;
char latency_file[BUFSIZ];
char buffer[BUFSIZ];
-
- sprintf (latency_file,
- "cb%d%s%d.txt",
- ACE_OS::getpid (),
- ts.use_sysbench_ == 1? "SB": "__",
- ts.thread_count_);
- ACE_DEBUG ((LM_DEBUG,
- "--->Output file for latency data is \"%s\"\n",
- latency_file));
-
+
+ ACE_OS::sprintf (latency_file,
+ "cb__%d.txt",
+ ts.thread_count_);
+
+ ACE_OS::fprintf(stderr,
+ "--->Output file for latency data is \"%s\"\n",
+ latency_file);
+
latency_file_handle = ACE_OS::fopen (latency_file, "w");
-
- // @@ What does this loop do?
+
+ // This loop visits each client. start_count_ is the number of clients.
for (u_int j = 0; j < ts.start_count_; j ++)
{
- sprintf (buffer,
- "%s #%d",
- j == 0 ? "High Priority": "Low Priority",
- j);
-
- for (u_int i = 0; i < ts.loop_count_; i ++)
- {
- sprintf (buffer + ACE_OS::strlen (buffer),
- "\t%u\n", ts.global_jitter_array_[j][i]);
- ACE_OS::fputs (buffer,
- latency_file_handle);
- buffer[0] = 0;
- }
+ ACE_OS::sprintf(buffer,
+ "%s #%d",
+ j==0? "High Priority": "Low Priority",
+ j);
+ // this loop visits each request latency from a client
+ for (u_int i = 0; i < ts.loop_count_/ts.grain_; i ++)
+ {
+ ACE_OS::sprintf(buffer+strlen(buffer),
+ "\t%u\n",
+ ts.global_jitter_array_[j][i]);
+ fputs (buffer, latency_file_handle);
+ buffer[0]=0;
+ }
}
-
- ACE_OS::fclose (latency_file_handle);
-
-#else /* !defined (CHORUS) */
+
+ ACE_OS::fclose (latency_file_handle);
+#else /* !CHORUS */
ACE_DEBUG ((LM_DEBUG, "Test done.\n"
"High priority client latency : %f msec, jitter: %f msec\n"
- "Low priority client latency : %f msec, jitter: %f msec\n",
+ "Low priority client latency : %f msec, jitter: %f msec\n"
+ "# of context switches: %d\n"
+ "total context switch time: %f\n",
high_priority_client.get_high_priority_latency (),
high_priority_client.get_high_priority_jitter (),
low_priority_client.get_low_priority_latency (),
- low_priority_client.get_low_priority_jitter ()));
-#endif /* !defined (VXWORKS) && !defined (CHORUS) */
+ low_priority_client.get_low_priority_jitter (),
+ ts.context_switch_,
+ context_switch_time () * ts.context_switch_ ));
+#endif /* !VXWORKS && !CHORUS */
// signal the utilization thread to finish with its work..
util_thread.done_ = 1;
@@ -292,11 +300,33 @@ main (int argc, char *argv [])
initialize ();
Task_State ts (argc, argv);
+
+#if defined (CHORUS)
+ // start the pccTimer for chorus classix
+ int pTime;
+
+ // Initialize the PCC timer Chip
+ pccTimerInit();
+
+ if(pccTimer(PCC2_TIMER1_START,&pTime) !=K_OK)
+ {
+ printf("pccTimer has a pending benchmark\n");
+ }
+#endif /* CHORUS */
+
if (ts.thread_per_rate_ == 0)
do_priority_inversion_test (ts);
else
do_thread_per_rate_test (ts);
-#else
+
+#if defined (CHORUS)
+ if(pccTimer(PCC2_TIMER1_STOP,&pTime) !=K_OK)
+ {
+ printf("pccTimer has a pending bench mark\n");
+ }
+#endif /* CHORUS */
+
+#else /* !ACE_HAS_THREADS */
ACE_DEBUG ((LM_DEBUG,
"Test not run. This platform doesn't seem to have threads.\n"));
#endif /* ACE_HAS_THREADS */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h
index 064382899b4..a9386c52596 100644
--- a/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h
@@ -23,6 +23,10 @@
#include "Task_Client.h"
#include "Util_Thread.h"
+#if defined (CHORUS)
+#include "pccTimer.h"
+#endif /* CHORUS */
+
#if defined (VME_DRIVER)
#include <hostLib.h>
extern "C" STATUS vmeDrv (void);
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp
index ad072424ee9..c30f128ec04 100644
--- a/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp
@@ -6,7 +6,7 @@
// TAO/tests
//
// = FILENAME
-// svr.cpp
+// server.cpp
//
// = AUTHOR
// Andy Gokhale, Sumedh Mungee, and Sergio Flores-Gaitan
@@ -781,6 +781,7 @@ start_servants (void)
priority,
ACE_SCOPE_THREAD);
+#if 0
// Make the factory low priority task an active object.
if (factory_task->activate (THR_BOUND | ACE_SCHED_FIFO,
1,
@@ -790,7 +791,7 @@ start_servants (void)
ACE_ERROR ((LM_ERROR, "(%P|%t; %p\n",
"factory_task->activate"));
}
-
+#endif
return 0;
}
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/Makefile b/TAO/tests/Cubit/TAO/MT_Cubit/Makefile
index 2db17eadaee..c9979b080b2 100644
--- a/TAO/tests/Cubit/TAO/MT_Cubit/Makefile
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/Makefile
@@ -30,13 +30,14 @@ CUBIT_SVR_OBJS = \
server.o \
cubit_i.o \
tmplinst.o
+
CUBIT_CLIENT_OBJS = \
cubitC.o \
cubitS.o \
Task_Client.o \
client.o \
Util_Thread.o \
- tmplinst.o
+ tmplinst.o
BIN = server client
BUILD = $(BIN)
@@ -62,7 +63,16 @@ include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
LDFLAGS += -L$(TAO_ROOT)/tao -L$(TAO_ROOT)/orbsvcs
CPPFLAGS += -I$(TAO_ROOT) -I$(TAO_ROOT)/orbsvcs -I$(TAO_ROOT)/tao/compat
-##POSTLINK += -lnk="-n -T $(VME_ROOT)/src/act/slots/act_s2.ld"
+
+# pccTimer will eventually get integrated into ACE. It is specific for ClassiX on VME
+ifdef CHORUS
+ SRC += pccTimer.cpp
+ CLT_OBJS += pccTimer.o
+ LDLIBS += -lOrb
+else
+ LDLIBS += -lOrb-mt
+endif
+
.PRECIOUS: cubitC.h cubitC.i cubitC.cpp cubitS.h cubitS.i cubitS.cpp
server: $(addprefix $(VDIR),$(CUBIT_SVR_OBJS))
@@ -70,7 +80,7 @@ server: $(addprefix $(VDIR),$(CUBIT_SVR_OBJS))
client: $(addprefix $(VDIR),$(CUBIT_CLIENT_OBJS))
$(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
-## -lnk="-n -T $(VME_ROOT)/src/act/slots/act_s2.ld"
+
clean:
-/bin/rm -rf *.o Log $(BIN) obj.* core Templates.DB .make.state
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.cpp b/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
index b064265112b..782345ee83f 100644
--- a/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
@@ -17,16 +17,19 @@ Task_State::Task_State (int argc, char **argv)
oneway_ (0),
use_name_service_ (1),
ior_file_ (0),
- use_sysbench_ (0)
+ grain_ (1),
+ context_switch_ (0)
{
- ACE_Get_Opt opts (argc, argv, "sn:t:d:rk:xof:y");
+ ACE_Get_Opt opts (argc, argv, "sn:t:d:rk:xof:g:");
int c;
int datatype;
while ((c = opts ()) != -1)
switch (c) {
- case 'y':
- use_sysbench_ = 1;
+ case 'g':
+ grain_ = ACE_OS::atoi (opts.optarg);
+ if (grain_ < 1)
+ grain_ = 1;
break;
case 's':
use_name_service_ = 0;
@@ -86,6 +89,7 @@ Task_State::Task_State (int argc, char **argv)
" [-x] // makes a call to servant to shutdown"
" [-o] // makes client use oneway calls instead"
" [-s] // makes client *NOT* use the name service"
+ " [-g granularity_of_request_timing]"
"\n", argv [0]));
}
@@ -130,12 +134,14 @@ Client::Client (Task_State *ts)
void
Client::put_latency (double *jitter,
double latency,
- u_int thread_id)
+ u_int thread_id,
+ u_int context_switch)
{
ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, ts_->lock_));
ts_->latency_[thread_id] = latency;
ts_->global_jitter_array_[thread_id] = jitter;
+ ts_->context_switch_ += context_switch;
#if defined (ACE_LACKS_FLOATING_POINT)
ACE_DEBUG ((LM_DEBUG,
@@ -540,6 +546,7 @@ Client::run_tests (Cubit_ptr cb,
u_int i = 0;
u_int call_count = 0;
u_int error_count = 0;
+ u_int context_switch = 0;
double *my_jitter_array;
ACE_NEW_RETURN (my_jitter_array,
@@ -550,6 +557,10 @@ Client::run_tests (Cubit_ptr cb,
double sleep_time = (1 / frequency) * (1000 * 1000);
double delta = 0;
+ int pstartTime = 0;
+ int pstopTime = 0;
+ double real_time = 0.0;
+
#if defined (USE_QUANTIFY)
quantify_stop_recording_data();
quantify_clear_data ();
@@ -559,21 +570,26 @@ Client::run_tests (Cubit_ptr cb,
for (i = 0; i < loop_count; i++)
{
+ ACE_Profile_Timer timer_for_context_switch;
ACE_High_Res_Timer timer_;
ACE_Time_Value tv (0, (long int) (sleep_time - delta));
ACE_OS::sleep (tv);
-
+
// Elapsed time will be in microseconds.
ACE_Time_Value delta_t;
-
- // use sysBench when CHORUS defined and option specified on command line
-#if defined (CHORUS)
- if (ts_->use_sysbench_ == 1)
- timer_.start (ACE_OS::ACE_HRTIMER_START);
- else
-#endif /* CHORUS */
- timer_.start ();
-
+
+#if defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)
+ ACE_Profile_Timer timer_for_context_switch;
+ ACE_Profile_Timer::Rusage usage;
+ timer_for_context_switch.start ();
+#endif /* ACE_HAS_PRUSAGE_T || ACE_HAS_GETRUSAGE */
+
+#if defined (CHORUS)
+ pstartTime = pccTime1Get();
+#else /* CHORUS */
+ timer_.start ();
+#endif /* !CHORUS */
+
if (ts_->oneway_ == 0)
{
switch (datatype)
@@ -763,35 +779,41 @@ Client::run_tests (Cubit_ptr cb,
}
}
- // use sysBench when CHORUS defined and option specified on command line
-#if defined (CHORUS)
- if (ts_->use_sysbench_ == 1)
- timer_.stop (ACE_OS::ACE_HRTIMER_STOP);
- else
-#endif /* CHORUS */
+#if defined (CHORUS)
+ if ( (loop_count % ts_->grain_) == 0)
+ pstopTime = pccTime1Get();
+#else /* CHORUS */
// if CHORUS is not defined just use plain timer_.stop ().
- timer_.stop ();
-
+ timer_.stop ();
timer_.elapsed_time (delta_t);
+#endif /* !CHORUS */
- double real_time = 0.0;
+#if defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)
+ timer_for_context_switch.stop ();
+ timer_for_context_switch.elapsed_rusage (usage);
+ // Add up the voluntary context switches & involuntary context switches
+ context_switch += usage.pr_vctx + usage.pr_ictx;
+#endif /* ACE_HAS_PRUSAGE_T || ACE_HAS_GETRUSAGE */
-#if !defined (ACE_HAS_PRUSAGE_T) && !defined (ACE_HAS_GETRUSAGE) && defined (ACE_LACKS_FLOATING_POINT)
+ // Calculate time elapsed
+#if defined (ACE_LACKS_FLOATING_POINT)
+# if defined (CHORUS)
+ real_time = pstopTime - pstartTime;
+ my_jitter_array [i/ts_->grain_] = real_time; // in units of microseconds.
+ // update the latency array, correcting the index using the granularity
+# else /* CHORUS */
// Store the time in usecs.
real_time = delta_t.sec () * ACE_ONE_SECOND_IN_USECS +
- delta_t.usec ();
-
+ delta_t.usec ();
+ my_jitter_array [i] = real_time; // in units of microseconds.
+# endif /* !CHORUS */
delta = ((40 * fabs (real_time) / 100) + (60 * delta / 100)); // pow(10,6)
latency += real_time;
- my_jitter_array [i] = real_time; // in units of microseconds.
-#else
- // Store the time in secs.
- real_time = delta_t.sec () + (double)delta_t.usec () / ACE_ONE_SECOND_IN_USECS;
-
- delta = ((40 * fabs (real_time * (1000 * 1000)) / 100) + (60 * delta / 100)); // pow(10,6)
+#else /* ACE_LACKS_FLOATING_POINT */
+ delta = ((0.4 * fabs (real_time * (1000 * 1000))) + (0.6 * delta)); // pow(10,6)
latency += real_time;
my_jitter_array [i] = real_time * 1000;
-#endif /* !defined (ACE_HAS_PRUSAGE_T) && !defined (ACE_HAS_GETRUSAGE) && defined (ACE_LACKS_FLOATING_POINT) */
+#endif /* !ACE_LACKS_FLOATING_POINT */
}
if (call_count > 0)
@@ -813,7 +835,10 @@ Client::run_tests (Cubit_ptr cb,
latency,
calls_per_second));
- this->put_latency (my_jitter_array, latency, thread_id);
+ this->put_latency (my_jitter_array,
+ latency,
+ thread_id,
+ context_switch);
#else
ACE_DEBUG ((LM_DEBUG,
"(%P|%t) cube average call ACE_OS::time\t= %f msec, \t"
@@ -822,7 +847,8 @@ Client::run_tests (Cubit_ptr cb,
1 / latency));
this->put_latency (my_jitter_array,
latency * 1000,
- thread_id);
+ thread_id,
+ context_switch);
#endif /* ! ACE_LACKS_FLOATING_POINT */
}
else
@@ -830,7 +856,8 @@ Client::run_tests (Cubit_ptr cb,
// still we have to call this function to store a valid array pointer.
this->put_latency (my_jitter_array,
0,
- thread_id);
+ thread_id,
+ context_switch);
ACE_DEBUG ((LM_DEBUG,
"*** Warning: Latency is less than or equal to zero."
" Precision may have been lost.\n"));
@@ -845,3 +872,134 @@ Client::run_tests (Cubit_ptr cb,
// cb->please_exit (env);
return 0;
}
+
+
+/////////////////////////////////////////////////////////////////////////
+// = DESCRIPTION
+// Program that calculates context switch time between threads.
+// This 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)
+// Ping Suspend/Resume Task and Suspend/Resume Task benchmarks.
+// Laboratory benchmark
+// It measures two different times:
+// 1) the time to resume a block 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.
+//
+// On Solaris 2.5.1, real-time threads must be bound to LWPs (using the
+// THR_BOUND flag), so that they can compete for system-wide resources.
+// In other words, if a thread is bound to an LWP, then the kernel is
+// aware of it.
+//
+// On Solaris 2.5.1, a call to thr_yield () is necessary after a call
+// to thr_continue () by a low-priority task. Without it, the high-priority
+// task doesn't preempt the low-priority task. This happens even with a
+// 10 nsec time quantum for the LWP. Maybe it's because with this version
+// of Solaris, the scheduling policy is SCHED_OTHER.
+//
+// All threads are created with the THR_DETACHED flag so that their
+// resources are released when they terminate.
+//
+// = CREATION DATE
+// 17 January 1997
+//
+// = AUTHOR
+// David L. Levine
+//
+// ============================================================================
+
+
+Yield_Test::Yield_Test (const unsigned long iterations) :
+ ACE_Task<ACE_MT_SYNCH> (),
+ iterations_ (iterations),
+ timer_barrier_ (3),
+ timer_ ()
+{
+ timer_.start ();
+
+ this->activate (THR_BOUND | THR_DETACHED | new_lwp, 2, 0, LOW_PRIORITY);
+
+ timer_barrier_.wait ();
+
+ timer_.stop ();
+ timer_.elapsed_microseconds (elapsed_time_);
+}
+
+Yield_Test::~Yield_Test()
+{
+}
+
+int
+Yield_Test::svc ()
+{
+ for (unsigned long i = 0; i < iterations_; ++i)
+ {
+ ACE_OS::thr_yield ();
+ }
+
+ timer_barrier_.wait ();
+
+ return 0;
+}
+
+double
+context_switch_time (void)
+{
+ const u_int iterations = 1000;
+ const u_int retries = 100;
+ double tmp = 0;
+ // Disable LM_DEBUG
+ ACE_Log_Msg::instance ()->priority_mask (ACE_LOG_MSG->priority_mask () ^
+ LM_DEBUG);
+
+ 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);
+ }
+ }
+
+ for (u_int i=0; i<100; i++)
+ {
+ LOW_PRIORITY = ACE_Sched_Params::priority_min (ACE_SCHED_FIFO);
+ HIGH_PRIORITY = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
+ LOW_PRIORITY);
+
+ // then Yield test
+ Yield_Test yield_test (iterations);
+ // Wait for all tasks to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ tmp += (double) (yield_test.elapsed_time ()/ (ACE_UINT32) 1u) /iterations /2;
+ }
+ return tmp/retries;
+}
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.h b/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.h
index 5e36a39edf0..534270e81bd 100644
--- a/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.h
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.h
@@ -23,12 +23,26 @@
#include "ace/Get_Opt.h"
#include "ace/Profile_Timer.h"
#include "ace/ARGV.h"
+#include "ace/Sched_Params.h"
+#include "ace/Task.h"
+#include "ace/High_Res_Timer.h"
#include "orbsvcs/CosNamingC.h"
#include "cubitC.h"
+#if defined (CHORUS)
+#include "pccTimer.h"
+#endif /* CHORUS */
+
#include <math.h>
+static unsigned int LOW_PRIORITY;
+static unsigned int HIGH_PRIORITY;
+
+// global test configuration parameters
+static unsigned long num_iterations = 1000;
+static unsigned int new_lwp = 0;
+
// @@ Should we put this into a more general file, e.g., OS.h?
//
// I will integrate this, together with the sqrt() function when
@@ -160,9 +174,14 @@ public:
char *ior_file_;
// Name of the filename that the server used to store the iors.
- u_int use_sysbench_;
- // flag that indicates that we are going to use the sysBench() call
- // to time calls. This only applies to the CHORUS ClassiX OS.
+ u_int grain_;
+ // this is the granularity of the timing of the CORBA requests. A
+ // value of 5 represents that we will take time every 5 requests,
+ // instead of the default of every request (1).
+
+ u_int context_switch_;
+ // stores the total number of context switches incurred by the
+ // program while making CORBA requests
};
class Client : public ACE_Task<ACE_SYNCH>
@@ -197,7 +216,8 @@ private:
void put_latency (double *jitter,
double latency,
- u_int);
+ u_int thread_id,
+ u_int context_switch);
// Records the latencies in the <Task_State>.
int parse_args (int, char **);
@@ -213,4 +233,34 @@ private:
// Object reference to the cubit context "MT_Cubit".
};
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Yield_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Yield_Test : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Yield_Test (const unsigned long iterations);
+ virtual ~Yield_Test ();
+
+ virtual int svc ();
+
+ ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
+private:
+ const unsigned long iterations_;
+ ACE_Barrier timer_barrier_;
+ 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 &);
+};
+
+double
+context_switch_time (void);
+
#endif /* !defined (TASK_CLIENT_H) */
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/client.cpp b/TAO/tests/Cubit/TAO/MT_Cubit/client.cpp
index bc54d42718c..5e1a58a1666 100644
--- a/TAO/tests/Cubit/TAO/MT_Cubit/client.cpp
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/client.cpp
@@ -39,6 +39,8 @@ initialize (void)
int
do_priority_inversion_test (Task_State &ts)
{
+ u_int i;
+
// Create the clients.
Client high_priority_client (&ts);
Client low_priority_client (&ts);
@@ -72,8 +74,10 @@ do_priority_inversion_test (Task_State &ts)
"activate failed",
priority));
- u_int i;
-
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating 1 client with high priority of %d\n",
+ priority));
+
// Drop the priority, so that the priority of clients will increase
// with increasing client number.
for (i = 0; i < ts.thread_count_; i++)
@@ -82,9 +86,10 @@ do_priority_inversion_test (Task_State &ts)
ACE_SCOPE_THREAD);
ACE_DEBUG ((LM_DEBUG,
- "Creating %d clients with low priority of %d\n",
+ "Creating %d clients with low priority ranging from %d to %d\n",
ts.thread_count_ - 1,
- priority));
+ priority,
+ priority + ts.thread_count_ - 2));
for (i = 0; i < ts.thread_count_ - 1; i++)
{
@@ -111,7 +116,8 @@ do_priority_inversion_test (Task_State &ts)
ACE_OS::printf ("Test done.\n"
"High priority client latency : %d usec\n"
"Low priority client latency : %d usec\n",
- high_priority_client.get_high_priority_latency (),
+
+ high_priority_client.get_high_priority_latency (),
low_priority_client.get_low_priority_latency ());
#elif defined (CHORUS)
ACE_OS::printf ("Test done.\n"
@@ -126,47 +132,49 @@ do_priority_inversion_test (Task_State &ts)
FILE *latency_file_handle = 0;
char latency_file[BUFSIZ];
char buffer[BUFSIZ];
-
- sprintf (latency_file,
- "cb%d%s%d.txt",
- ACE_OS::getpid (),
- ts.use_sysbench_ == 1? "SB": "__",
- ts.thread_count_);
- ACE_DEBUG ((LM_DEBUG,
- "--->Output file for latency data is \"%s\"\n",
- latency_file));
-
+
+ ACE_OS::sprintf (latency_file,
+ "cb__%d.txt",
+ ts.thread_count_);
+
+ ACE_OS::fprintf(stderr,
+ "--->Output file for latency data is \"%s\"\n",
+ latency_file);
+
latency_file_handle = ACE_OS::fopen (latency_file, "w");
-
- // @@ What does this loop do?
+
+ // This loop visits each client. start_count_ is the number of clients.
for (u_int j = 0; j < ts.start_count_; j ++)
{
- sprintf (buffer,
- "%s #%d",
- j == 0 ? "High Priority": "Low Priority",
- j);
-
- for (u_int i = 0; i < ts.loop_count_; i ++)
- {
- sprintf (buffer + ACE_OS::strlen (buffer),
- "\t%u\n", ts.global_jitter_array_[j][i]);
- ACE_OS::fputs (buffer,
- latency_file_handle);
- buffer[0] = 0;
- }
+ ACE_OS::sprintf(buffer,
+ "%s #%d",
+ j==0? "High Priority": "Low Priority",
+ j);
+ // this loop visits each request latency from a client
+ for (u_int i = 0; i < ts.loop_count_/ts.grain_; i ++)
+ {
+ ACE_OS::sprintf(buffer+strlen(buffer),
+ "\t%u\n",
+ ts.global_jitter_array_[j][i]);
+ fputs (buffer, latency_file_handle);
+ buffer[0]=0;
+ }
}
-
- ACE_OS::fclose (latency_file_handle);
-
-#else /* !defined (CHORUS) */
+
+ ACE_OS::fclose (latency_file_handle);
+#else /* !CHORUS */
ACE_DEBUG ((LM_DEBUG, "Test done.\n"
"High priority client latency : %f msec, jitter: %f msec\n"
- "Low priority client latency : %f msec, jitter: %f msec\n",
+ "Low priority client latency : %f msec, jitter: %f msec\n"
+ "# of context switches: %d\n"
+ "total context switch time: %f\n",
high_priority_client.get_high_priority_latency (),
high_priority_client.get_high_priority_jitter (),
low_priority_client.get_low_priority_latency (),
- low_priority_client.get_low_priority_jitter ()));
-#endif /* !defined (VXWORKS) && !defined (CHORUS) */
+ low_priority_client.get_low_priority_jitter (),
+ ts.context_switch_,
+ context_switch_time () * ts.context_switch_ ));
+#endif /* !VXWORKS && !CHORUS */
// signal the utilization thread to finish with its work..
util_thread.done_ = 1;
@@ -292,11 +300,33 @@ main (int argc, char *argv [])
initialize ();
Task_State ts (argc, argv);
+
+#if defined (CHORUS)
+ // start the pccTimer for chorus classix
+ int pTime;
+
+ // Initialize the PCC timer Chip
+ pccTimerInit();
+
+ if(pccTimer(PCC2_TIMER1_START,&pTime) !=K_OK)
+ {
+ printf("pccTimer has a pending benchmark\n");
+ }
+#endif /* CHORUS */
+
if (ts.thread_per_rate_ == 0)
do_priority_inversion_test (ts);
else
do_thread_per_rate_test (ts);
-#else
+
+#if defined (CHORUS)
+ if(pccTimer(PCC2_TIMER1_STOP,&pTime) !=K_OK)
+ {
+ printf("pccTimer has a pending bench mark\n");
+ }
+#endif /* CHORUS */
+
+#else /* !ACE_HAS_THREADS */
ACE_DEBUG ((LM_DEBUG,
"Test not run. This platform doesn't seem to have threads.\n"));
#endif /* ACE_HAS_THREADS */
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/client.h b/TAO/tests/Cubit/TAO/MT_Cubit/client.h
index 064382899b4..a9386c52596 100644
--- a/TAO/tests/Cubit/TAO/MT_Cubit/client.h
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/client.h
@@ -23,6 +23,10 @@
#include "Task_Client.h"
#include "Util_Thread.h"
+#if defined (CHORUS)
+#include "pccTimer.h"
+#endif /* CHORUS */
+
#if defined (VME_DRIVER)
#include <hostLib.h>
extern "C" STATUS vmeDrv (void);
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.cpp b/TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.cpp
new file mode 100644
index 00000000000..771747c8acb
--- /dev/null
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.cpp
@@ -0,0 +1,277 @@
+// $Id$
+/*
+ ****************************************************************
+ *
+ * Component = pccTimer.C - mvme167
+ *
+ * Synopsis =
+ *
+ * Copyright (c) 1995, 1996, 1997 Chorus systemes
+ * (R) Chorus is a registered trademark of Chorus systemes
+ *
+ ****************************************************************
+ *
+ *
+ ****************************************************************
+ */
+/* Everything is relative from
+/vobs/chorus_work/merge1/mvme177/appl/include/chorus
+*/
+
+#include <stdio.h>
+#include <chorus.h>
+#include <exec/chContext.h>
+//#include <exec/c_cpuContext.H>
+#include <util/chKnTimeVal.h>
+//#include <util/macro.h>
+#include <tick/chTick.h>
+//#include <kbim/p_chIntr.h>
+//#include <stdconsio.h>
+#include <bsp/pccchip2.h>
+#include <bsp/nvram.h>
+#include <bsp/board.h>
+#include <exec/chPanic.h>
+#include <bsp/intrLevel.h>
+#include <timer/chProf.h>
+#include <exec/f_chTrap.h>
+#include <ims/ims_f.h>
+//#include <sched/schedIntf.H>
+//#include <p_boardInfo.H>
+#include "pccTimer.h"
+
+
+static unsigned int quartz;
+static unsigned int timer_reload_value;
+int timerHz = 100;
+
+volatile struct
+pccchip2 *pccchip2 = (volatile struct pccchip2 *) PCCchip2_BASE;
+
+volatile struct
+nvram* nvram = ((volatile struct nvram*)NVRAM_BASE);
+
+
+int
+pccTimer(int option, int* uTime)
+{
+ KnTimeVal time;
+
+ int res = K_EOK;
+ //option &= ~PCC_USERDATA;
+ static int benchEnable1 = 0;
+ static int benchEnable2 = 0;
+ static unsigned int benchLastTime = 0;
+
+ switch(option)
+ {
+
+ case PCC2_TIMER1_START:
+ if (benchEnable1) return K_EINVAL;
+ benchEnable1 = 1;
+ pccTimer1Start();
+ benchLastTime = pccTimer1Reset();
+ break;
+
+ case PCC2_TIMER1_STOP:
+ benchLastTime = pccTime1Get();
+ if (!benchEnable1) return K_EINVAL;
+ benchEnable1 = 0;
+ pccTimer1Stop();
+ break;
+
+ case PCC2_TIMER1_BPOINT:
+ benchLastTime = pccTime1Get();
+ if (!benchEnable1) return K_EINVAL;
+ break;
+
+ case PCC2_TIMER2_START:
+ if (benchEnable2) return K_EINVAL;
+ benchEnable2 = 1;
+ pccTimer2Start();
+ benchLastTime = pccTimer2Reset();
+ break;
+
+ case PCC2_TIMER2_STOP:
+ benchLastTime = pccTime2Get();
+ if (!benchEnable2) return K_EINVAL;
+ benchEnable2 = 0;
+ pccTimer2Stop();
+ break;
+
+ case PCC2_TIMER2_BPOINT:
+ benchLastTime = pccTime2Get();
+ if (!benchEnable2) return K_EINVAL;
+ break;
+
+ default:
+ return K_EINVAL;
+ }
+
+ // Here only is last time must be returned
+ if (uTime)
+ {
+ *uTime = benchLastTime;
+ }
+
+ return res;
+}
+
+
+ //
+ // Return the value of the timer counter, in microseconds.
+ //
+ unsigned int
+pccTime1Get()
+{
+ return pccchip2->timer1cnt;
+}
+
+ unsigned int
+pccTimer1Reset()
+{
+ pccchip2->timer1cnt = 0;
+ return pccchip2->timer1cnt;
+}
+
+ void
+pccTimer1Start()
+{
+ unsigned int temp;
+
+ // Clear the counter
+ pccchip2->timer1cnt = 0;
+ // Start the counter running
+ // Do not reset the counter when it matches the compare register (~PCC2_COC)
+ // Clear the overflow counter
+ temp = pccchip2->timer1ctl;
+ pccchip2->timer1ctl = temp | PCC2_COVF | ~PCC2_COC | PCC2_CEN;
+
+}
+
+ void
+pccTimer1Stop()
+{
+ unsigned int temp;
+
+ // Stop the counter running
+ temp = pccchip2->timer1ctl;
+ pccchip2->timer1ctl = temp | ~PCC2_CEN;
+
+}
+
+
+ //
+ // Return the value of the timer counter, in microseconds.
+ //
+ unsigned int
+pccTime2Get()
+{
+ return pccchip2->timer2cnt;
+}
+
+ unsigned int
+pccTimer2Reset()
+{
+ pccchip2->timer2cnt = 0;
+ return pccchip2->timer2cnt;
+}
+
+ void
+pccTimer2Start()
+{
+ unsigned int temp;
+
+ // Clear the counter
+ pccchip2->timer2cnt = 0;
+ // Start the counter running
+ // Do not reset the counter when it matches the compare register (~PCC2_COC)
+ // Clear the overflow counter
+ temp = pccchip2->timer2ctl;
+ pccchip2->timer2ctl = temp | PCC2_COVF | ~PCC2_COC | PCC2_CEN;
+
+}
+
+ void
+pccTimer2Stop()
+{
+ unsigned int temp;
+
+ // Stop the counter running
+ temp = pccchip2->timer2ctl;
+ pccchip2->timer2ctl = temp | ~PCC2_CEN;
+
+}
+
+ //
+ // Init the PCC2 timer
+ //
+ void
+pccTimerInit()
+{
+ volatile unsigned int temp;
+ char c;
+
+ /* compute board quartz frequency from nvram information */
+ c = nvram->config_rom.speed[0];
+ quartz = ((unsigned int) c - (unsigned int) '0') * 10;
+ c = nvram->config_rom.speed[1];
+ quartz += ((unsigned int) c - (unsigned int) '0');
+
+ /* Step 1. Initialize prescaler control register */
+ /* On a mvme177, the VME2Chip runs at half the MPU speed */
+ temp = pccchip2->prescaleadjust & 0xFFFFFF00;
+
+ switch(quartz) {
+ case 60 : pccchip2->prescaleadjust = temp | 0x000000E2; /* 256-30 */
+ // ASSERT(((BoardInfo*)chorusContext->ctxBoardInfo)->boardId
+ // == BOARD_MVME177);
+ break;
+ default : {
+ char tab [80];
+ printf(tab,"%s : %d", "Unknown clock frequency", quartz);
+ svSysPanic(KP_DEBUG, 0, 0, tab, __FILE__, __LINE__);
+ }
+ }
+
+ timer_reload_value = 1000000 / timerHz;
+
+
+ /* Step 2. Set pcc timer 1 and timer 2 compare register */
+// pccchip2->timer1cmp = timer_reload_value;
+ pccchip2->timer1cmp = ~0;
+ pccchip2->timer2cmp = ~0;
+
+
+ /* Step 3. Clear timer 1 and timer 2 counter register */
+ pccchip2->timer1cnt = 0;
+ pccchip2->timer2cnt = 0;
+
+
+ /* Step 4. Enable pcc timer 1 and timer 2*/
+ temp = pccchip2->timer1ctl;
+ pccchip2->timer1ctl = temp | PCC2_COVF | PCC2_COC | PCC2_CEN;
+
+ temp = pccchip2->timer2ctl;
+ pccchip2->timer2ctl = temp | PCC2_COVF | PCC2_COC | PCC2_CEN;
+
+
+ /* Step 5. VBR is already set */
+// No need to change the VBR if we are not Compare Feature of the PCC2 Timer
+
+ /* Step 6. set the pcc timer 1 interrupt level */
+// temp = pccchip2->irqlvl1;
+// temp = temp & 0xfffffff8;
+// pccchip2->irqlvl1 = temp | TIMER_INT_LEVEL;
+
+
+ // KnIntrEntry clockConf;
+
+ //clockConf.name = VME_CHIP2_TIMER1;
+ //clockConf.hdl = getHdlFromCf();
+ //clockConf.on = clockStart_p;
+ //clockConf.off = clockStop_p;
+ //clockConf.down = clockDown_p;
+ //clockConf.ison = clockTest_p;
+
+ //svIntrConnect (&clockConf);
+}
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.h b/TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.h
new file mode 100644
index 00000000000..453977e6661
--- /dev/null
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.h
@@ -0,0 +1,56 @@
+// $Id$
+/*
+ ****************************************************************
+ *
+ * Component = PCC2 Timer Header File
+ *
+ * Synopsis =
+ *
+ *
+ ****************************************************************
+ *
+ *
+ ****************************************************************
+ */
+
+
+
+#ifndef _PCCTIMER_H
+#define _PCCTIMER_H
+
+int
+pccTimer(int option, int* uTime);
+unsigned int
+pccTime1Get();
+unsigned int
+pccTimer1Reset();
+void
+pccTimer1Start();
+void
+pccTimer1Stop();
+unsigned int
+pccTime2Get();
+unsigned int
+pccTimer2Reset();
+void
+pccTimer2Start();
+void
+pccTimer2Stop();
+void
+pccTimerInit();
+
+
+#define PCC2_TIMER1_START 0x0
+#define PCC2_TIMER1_STOP 0x1
+#define PCC2_TIMER1_BPOINT 0x2
+#define PCC2_TIMER2_START 0x10
+#define PCC2_TIMER2_STOP 0x20
+#define PCC2_TIMER2_BPOINT 0x40
+#define PCC2_USERDATA 0x100
+
+#include <c_defs.h>
+#include <mem/chAddr_f.h>
+
+//extern_C int sysBench __((int, int*));
+
+#endif /* _PCCTIMER_H */
diff --git a/TAO/tests/Cubit/TAO/MT_Cubit/server.cpp b/TAO/tests/Cubit/TAO/MT_Cubit/server.cpp
index ad072424ee9..c30f128ec04 100644
--- a/TAO/tests/Cubit/TAO/MT_Cubit/server.cpp
+++ b/TAO/tests/Cubit/TAO/MT_Cubit/server.cpp
@@ -6,7 +6,7 @@
// TAO/tests
//
// = FILENAME
-// svr.cpp
+// server.cpp
//
// = AUTHOR
// Andy Gokhale, Sumedh Mungee, and Sergio Flores-Gaitan
@@ -781,6 +781,7 @@ start_servants (void)
priority,
ACE_SCOPE_THREAD);
+#if 0
// Make the factory low priority task an active object.
if (factory_task->activate (THR_BOUND | ACE_SCHED_FIFO,
1,
@@ -790,7 +791,7 @@ start_servants (void)
ACE_ERROR ((LM_ERROR, "(%P|%t; %p\n",
"factory_task->activate"));
}
-
+#endif
return 0;
}