From 760dfb3e6f33d74a68e132feeebe94745e9c4073 Mon Sep 17 00:00:00 2001 From: sergio Date: Wed, 15 Apr 1998 17:17:57 +0000 Subject: *** empty log message *** --- TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile | 16 +- .../Cubit/TAO/MT_Cubit/Task_Client.cpp | 232 ++++++++++++++--- .../Cubit/TAO/MT_Cubit/Task_Client.h | 58 ++++- .../Cubit/TAO/MT_Cubit/client.cpp | 106 +++++--- TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h | 4 + .../Cubit/TAO/MT_Cubit/server.cpp | 5 +- TAO/tests/Cubit/TAO/MT_Cubit/Makefile | 16 +- TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.cpp | 232 ++++++++++++++--- TAO/tests/Cubit/TAO/MT_Cubit/Task_Client.h | 58 ++++- TAO/tests/Cubit/TAO/MT_Cubit/client.cpp | 106 +++++--- TAO/tests/Cubit/TAO/MT_Cubit/client.h | 4 + TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.cpp | 277 +++++++++++++++++++++ TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.h | 56 +++++ TAO/tests/Cubit/TAO/MT_Cubit/server.cpp | 5 +- 14 files changed, 1007 insertions(+), 168 deletions(-) create mode 100644 TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.cpp create mode 100644 TAO/tests/Cubit/TAO/MT_Cubit/pccTimer.h 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
+// "RTOS Benchmarking -- All Things Considered . . ."
+// Real-Time Magazine, +// Second Quarter 1993, +// reprinted by Wind River +// Systems

+// 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 (), + 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 +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 @@ -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 . 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 +{ +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 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
+// "RTOS Benchmarking -- All Things Considered . . ."
+// Real-Time Magazine, +// Second Quarter 1993, +// reprinted by Wind River +// Systems

+// 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 (), + 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 +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 @@ -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 . 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 +{ +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 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 +#include +#include +//#include +#include +//#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#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 +#include + +//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; } -- cgit v1.2.1