diff options
Diffstat (limited to 'TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp')
-rw-r--r-- | TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp | 865 |
1 files changed, 865 insertions, 0 deletions
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp new file mode 100644 index 00000000000..e0d97da8166 --- /dev/null +++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp @@ -0,0 +1,865 @@ +// $Id$ + +#include "ace/config-all.h" + +#if defined (ACE_VXWORKS) && !defined (__RTP__) +# undef ACE_MAIN +# define ACE_MAIN client +#endif /* ACE_VXWORKS && !__RTP__ */ + +#include "ace/Sched_Params.h" +#include "tao/Strategies/advanced_resource.h" +#include "server.h" +#include "client.h" +#include "Globals.h" +#include "ace/Barrier.h" + +#if defined (ACE_HAS_QUANTIFY) +# include "quantify.h" +#endif /* ACE_HAS_QUANTIFY */ + +ACE_RCSID(MT_Cubit, client, "$Id$") + +#if defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS) +u_int ctx = 0; +u_int ct = 0; + +typedef struct +{ + char name[15]; + WIND_TCB *tcb; +#if (CPU_FAMILY == PPC) + INSTR pc; +#else + INSTR *pc; +#endif +} task_info; + +const u_int SWITCHES = 25000; +task_info tInfo[SWITCHES]; + +extern "C" +int +switchHook (WIND_TCB *pOldTcb, // pointer to old task's WIND_TCB. + WIND_TCB *pNewTcb) // pointer to new task's WIND_TCB. +{ + ACE_UNUSED_ARG (pOldTcb); + + // We create the client threads with names starting with "@". + char* name = ::taskName (::taskIdSelf ()); + if (name[0] == '@') + ++ctx; + + if (ct < SWITCHES) + { + ACE_OS::strncpy (tInfo[ct].name, + name, + TASKNAME_LEN); + tInfo[ct].tcb = pNewTcb; + tInfo[ct].pc = pNewTcb->regs.pc; + ++ct; + } + + return 0; +} +#endif /* ACE_VXWORKS && !__RTP__ && !ACE_HAS_PTHREADS */ + +// Constructor. + +Client_i::Client_i (void) + : high_priority_client_ (0), + low_priority_client_ (0), + util_thread_ (0), + ts_ (0), + num_low_priority_ (0), + num_priorities_ (0), + grain_ (0), + counter_ (0), + task_id_ (0), + argc_ (0), + argv_ (0), + context_switch_ (0) +{ +} + +// Destructor. + +Client_i::~Client_i (void) +{ + delete this->high_priority_client_; + if (this->low_priority_client_ != 0) + // Delete the low priority task array. + for (u_int i = this->num_low_priority_; + i > 0; + i--) + delete this->low_priority_client_[i - 1]; + delete [] this->low_priority_client_; + delete this->util_thread_; + delete this->ts_; +} + +int +Client_i::init (int argc, char *argv[]) +{ + this->argc_ = argc; + this->argv_ = argv; + + int result; + result = GLOBALS::instance ()->sched_fifo_init (); + if (result == -1) + return result; + VX_VME_INIT; + FORCE_ARGV (this->argc_,this->argv_); + // Make sure we've got plenty of socket handles. This call will use + // the default maximum. + ACE::set_handle_limit (); + + ACE_NEW_RETURN (this->ts_, + Task_State, + -1); + + // Preliminary argument processing. + for (int i=0; + i< this->argc_; + ++i) + { + if (ACE_OS::strcmp (this->argv_[i],"-r") == 0) + this->ts_->thread_per_rate_ = 1; + else if (ACE_OS::strcmp (this->argv_[i],"-t") == 0 + && (i - 1 < this->argc_)) + this->ts_->thread_count_ = + ACE_OS::atoi (this->argv_[i+1]); + } + PCCTIMER_INIT; + return 0; +} + +void +Client_i::run (void) +{ + if (this->ts_->thread_per_rate_ == 0) + { + this->do_priority_inversion_test (); + + if (this->ts_->use_utilization_test_ == 1) + { + // Exit. Otherwise, the process just waits forever. + ACE_OS::exit (); + } + } + else + this->do_thread_per_rate_test (); +} + +#if defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS) +void +Client_i::output_taskinfo (void) +{ + FILE *file_handle = ACE_OS::fopen ("taskinfo.txt", "w"); + + if (file_handle == 0) + ACE_ERROR ((LM_ERROR, + "%p\n", + "open")); + + ACE_DEBUG ((LM_DEBUG, + "--->Output file for taskinfo data is \"taskinfo.txt\"\n")); + + // This loop visits each client. thread_count_ is the number of + // clients. + + for (u_int j = 0; j < SWITCHES; ++j) + ACE_OS::fprintf(file_handle, + "\tname= %s\ttcb= %p\tpc= %p\n", + tInfo[j].name, + tInfo[j].tcb, + tInfo[j].pc); + + ACE_OS::fclose (file_handle); +} +#endif /* ACE_VXWORKS && !__RTP__ && !ACE_HAS_PTHREADS */ + +void +Client_i::get_context_switches (void) +{ +#if (defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)) && !defined (ACE_WIN32) + + if (this->ts_->context_switch_test_ == 1) + { + this->timer_for_context_switch.start (); + this->timer_for_context_switch.get_rusage (this->usage); +# if defined (ACE_HAS_PRUSAGE_T) + this->context_switch_ = this->usage.pr_vctx + this->usage.pr_ictx; +# else /* ACE_HAS_PRUSAGE_T */ + this->context_switch_ = this->usage.ru_nvcsw + this->usage.ru_nivcsw; +# endif /* ACE_HAS_GETRUSAGE */ + } +#endif /* ACE_HAS_PRUSAGE_T || ACE_HAS_GETRUSAGE */ + +#if defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS) + if (this->ts_->context_switch_test_ == 1) + { + ACE_DEBUG ((LM_DEBUG, + "Adding the context switch hook!\n")); + taskSwitchHookAdd ((FUNCPTR) &switchHook); + } +#endif /* ACE_VXWORKS && !__RTP__ */ +} + +void +Client_i::output_latency (void) +{ + FILE *latency_file_handle = 0; + char latency_file[BUFSIZ]; + char buffer[BUFSIZ]; + + ACE_OS::sprintf (latency_file, + "c%d", + this->ts_->thread_count_); + + ACE_DEBUG ((LM_DEBUG, + "--->Output file for latency data is \"%s\"\n", + latency_file)); + + latency_file_handle = ACE_OS::fopen (latency_file, "w"); + + // This loop visits each client. thread_count_ is the number of + // clients. + for (u_int j = 0; + j < this->ts_->thread_count_; + ++j) + { + ACE_OS::sprintf(buffer, + "%s #%d", + j == 0 + ? "High Priority" + : "Low Priority", + j); + // This loop visits each request latency from a client. + JITTER_ARRAY_ITERATOR iterator = + this->ts_->global_jitter_array_ [j]->begin (); + + u_int i = 0; + ACE_timer_t *latency = 0; + + for (iterator.first (); + (i < (j == 0 + ? this->ts_->high_priority_loop_count_ + : this->ts_->loop_count_) / this->ts_->granularity_) && + (iterator.next (latency)); + i++,iterator.advance ()) + { + ACE_OS::sprintf (buffer + ACE_OS::strlen (buffer), +#if defined (CHORUS_MVME) + "\t%u\n", +#else + "\t%f\n", +#endif /* !CHORUS_MVME */ + *latency); + ACE_OS::fputs (buffer, + latency_file_handle); + buffer[0] = 0; + } + } + + ACE_OS::fclose (latency_file_handle); +} + +// Mechanism to distribute the available priorities among the threads +// when there are not enough different priorities for all threads. + +void +Client_i::init_low_priority (void) +{ + ACE_Sched_Priority prev_priority = this->high_priority_; + if (this->ts_->use_multiple_priority_ == 1) + this->low_priority_ = + this->priority_.get_low_priority (this->num_low_priority_, + prev_priority, + 1); + else + this->low_priority_ = + this->priority_.get_low_priority (this->num_low_priority_, + prev_priority, + 0); + this->num_priorities_ = + this->priority_.number_of_priorities (); + this->grain_ = this->priority_.grain (); + this->counter_ = 0; +} + +void +Client_i::calc_util_time (void) +{ + MT_Cubit_Timer timer (ACE_ONE_SECOND_IN_MSECS); + // Time the utilization thread' "computation" to get % IdleCPU at the + // end of the test. + + // Execute one computation. + timer.start (); +#if defined (CHORUS_MVME) + this->util_thread_->computation (); + timer.stop (); + this->util_task_duration_ = timer.get_elapsed (); +#else + for (u_int i = 0; + i < NUM_UTIL_COMPUTATIONS; + ++i) + this->util_thread_->computation (); + + timer.stop (); + this->util_task_duration_ = timer.get_elapsed () / NUM_UTIL_COMPUTATIONS; +#endif /* !CHORUS_MVME */ +} + +int +Client_i::activate_high_client (void) +{ + ACE_NEW_RETURN (this->high_priority_client_, + Client (&this->client_thread_manager_, + this->ts_, + this->argc_, + this->argv_, + 0), + -1); + +#if defined (ACE_VXWORKS) + // Set a task_id string starting with "@", so we are able to + // accurately count the number of context switches. + ACE_OS::strcpy (this->task_id_, + "@High"); +#endif /* ACE_VXWORKS */ + + this->high_priority_ = + this->priority_.get_high_priority (); + + ACE_DEBUG ((LM_DEBUG, + "Creating 1 client with high priority of %d\n", + this->high_priority_)); + if (this->high_priority_client_->activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 0, + this->high_priority_, + -1, + 0, + 0, + 0, + 0, + (ACE_thread_t *) &this->task_id_) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p; priority is %d\n", + "activate failed", + this->high_priority_), + -1); + return 0; +} + +int +Client_i::activate_low_client (void) +{ + ACE_NEW_RETURN (this->low_priority_client_, + Client *[this->ts_->thread_count_], + -1); + + // Hack to make sure we have something in this pointer, when + // thread_count == 1. + this->low_priority_client_[0] = + this->high_priority_client_; + this->num_low_priority_ = + this->ts_->thread_count_ - 1; + + // Set the priority for the low priority threads. + this->init_low_priority (); + + ACE_DEBUG ((LM_DEBUG, + "Creating %d clients at priority %d\n", + this->ts_->thread_count_ - 1, + this->low_priority_)); + + for (u_int i = this->num_low_priority_; + i > 0; + i--) + { + ACE_NEW_RETURN (this->low_priority_client_ [i - 1], + Client (&this->client_thread_manager_, + this->ts_, + this->argc_, + this->argv_, + i), + -1); +#if defined (ACE_VXWORKS) + // Pace the connection establishment on VxWorks. + const ACE_Time_Value delay (0L, 500000L); + ACE_OS::sleep (delay); + + // Set a task_id string startiing with "@", so we are able to + // accurately count the number of context switches on VXWORKS + sprintf (this->task_id_, + "@Low%u", + i); +#endif /* ACE_VXWORKS */ + ACE_DEBUG ((LM_DEBUG, + "Creating client with thread ID %d and priority %d\n", + i, + this->low_priority_)); + // The first thread starts at the lowest priority of all the low + // priority clients. + if (this->low_priority_client_[i - 1]->activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 0, + this->low_priority_, // These are constructor defaults. + -1, // int grp_id = -1, + 0, // ACE_Task_Base *task = 0, + 0, // ACE_hthread_t thread_handles[] = 0, + 0, // void *stack[] = 0, + 0, // size_t stack_size[] = 0, + (ACE_thread_t *) &this->task_id_) == -1) + ACE_ERROR ((LM_ERROR, + "%p; priority is %d\n", + "activate failed", + this->low_priority_)); + + if (this->ts_->use_multiple_priority_ == 1) + { + this->counter_ = (this->counter_ + 1) % this->grain_; + + if (this->counter_ == 0 + // Just so when we distribute the priorities among the + // threads, we make sure we don't go overboard. + && this->num_priorities_ * this->grain_ > this->num_low_priority_ - (i - 1)) + // Get the next higher priority. + this->low_priority_ = ACE_Sched_Params::next_priority + (ACE_SCHED_FIFO, this->low_priority_, ACE_SCOPE_THREAD); + } + } /* end of for () */ + + return 0; +} + +int +Client_i::activate_util_thread (void) +{ + ACE_NEW_RETURN (this->util_thread_, + Util_Thread (this->ts_, + &this->util_thread_manager_), + -1); + + // Time the utilization thread' "computation" to get %IdleCPU at the + // end of the test. + this->calc_util_time (); + + if (this->ts_->use_utilization_test_ == 1) + // Activate the utilization thread only if specified. See + // description of this variable in header file. + { + this->low_priority_ = + ACE_Sched_Params::priority_min (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD); + ACE_DEBUG ((LM_DEBUG, + "Creating utilization thread with priority of %d\n", + this->low_priority_)); + + // Activate the Utilization thread. It will wait until all + // threads have finished binding. + this->util_thread_->activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 0, + this->low_priority_); + } + else + this->util_thread_->close (); + return 0; +} + +void +Client_i:: print_context_stats (void) +{ + if (this->ts_->context_switch_test_ == 1) + { +#if defined (ACE_HAS_PRUSAGE_T) + this->timer_for_context_switch.stop (); + this->timer_for_context_switch.get_rusage (this->usage); + // Add up the voluntary context switches & involuntary context + // switches. + this->context_switch_ = + this->usage.pr_vctx + this->usage.pr_ictx - this->context_switch_; + ACE_DEBUG ((LM_DEBUG, + "Voluntary context switches = %d, Involuntary context switches = %d\n", + this->usage.pr_vctx, + this->usage.pr_ictx)); +#elif defined (ACE_HAS_GETRUSAGE) && !defined (ACE_WIN32) + this->timer_for_context_switch.stop (); + this->timer_for_context_switch.get_rusage (this->usage); + // Add up the voluntary context switches & involuntary context + // switches. + this->context_switch_ = + this->usage.ru_nvcsw + this->usage.ru_nivcsw - this->context_switch_; + ACE_DEBUG ((LM_DEBUG, + "Voluntary context switches=%d, Involuntary context switches=%d\n", + this->usage.ru_nvcsw, + this->usage.ru_nivcsw)); +#elif defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS) + taskSwitchHookDelete ((FUNCPTR) &switchHook); + ACE_DEBUG ((LM_DEBUG, + "Context switches=%d\n", + ctx)); +#endif /* ACE_HAS_PRUSAGE_T */ + } +} + +void +Client_i::print_latency_stats (void) +{ + // If running the utilization test, don't report latency nor jitter. + if (this->ts_->use_utilization_test_ == 0) + { +#if defined (ACE_VXWORKS) + ACE_DEBUG ((LM_DEBUG, + "Test done.\n" + "High priority client latency : %f usec, jitter: %f usec\n" + "Low priority client latency : %f usec, jitter: %f usec\n", + this->high_priority_client_->get_high_priority_latency (), + this->high_priority_client_->get_high_priority_jitter (), + this->low_priority_client_[0]->get_low_priority_latency (), + this->low_priority_client_[0]->get_low_priority_jitter ())); + // Output the latency values to a file, tab separated, to import + // it to Excel to calculate jitter, in the mean time we come up + // with the sqrt() function. + output_latency (); +#elif defined (CHORUS_MVME) + ACE_DEBUG ((LM_DEBUG, + "Test done.\n" + "High priority client latency : %u usec\n" + "Low priority client latency : %u usec\n", + this->high_priority_client_->get_high_priority_latency (), + this->low_priority_client_[0]->get_low_priority_latency () )); + // Output the latency values to a file, tab separated, to import + // it to Excel to calculate jitter, in the mean time we come up + // with the sqrt() function. + output_latency (); +#else /* !CHORUS_MVME */ + ACE_DEBUG ((LM_DEBUG, "Test done.\n" + "High priority client latency : %f usec, jitter: %f usec\n" + "Low priority client latency : %f usec, jitter: %f usec\n", + this->high_priority_client_->get_high_priority_latency (), + this->high_priority_client_->get_high_priority_jitter (), + this->low_priority_client_[0]->get_low_priority_latency (), + this->low_priority_client_[0]->get_low_priority_jitter ())); + // output_latency (); +#endif /* !ACE_VXWORKS && !CHORUS_MVME */ + } +} + +void +Client_i::print_util_stats (void) +{ + if (this->ts_->use_utilization_test_ == 1) + { + ACE_DEBUG ((LM_DEBUG, + "(%t) Scavenger task performed \t%u computations\n" + "(%t) CLIENT task performed \t\t%u %s calls as requested\n\n" + "(%t) Utilization test time is \t\t%f microseconds\n\t%s\n", + this->util_thread_->get_number_of_computations (), + this->ts_->loop_count_, + this->ts_->remote_invocations_ == 1 ? "CORBA" : "local", + this->ts_->util_test_time_, + this->ts_->remote_invocations_ == 1 ? + "NOW run the same test again, adding the \"-l\" option. See README file for explanation." : + " " + )); + } +} + +void +Client_i::print_priority_inversion_stats (void) +{ + this->print_context_stats (); + this->print_latency_stats (); + this->print_util_stats (); +} + +int +Client_i::start_servant (void) +{ + char high_thread_args[BUFSIZ]; + + ACE_OS::sprintf (high_thread_args, + "-ORBSndSock 32768 " + "-ORBRcvSock 32768 "); + + Cubit_Task *high_priority_task; + + ACE_NEW_RETURN (high_priority_task, + Cubit_Task ((const char *) high_thread_args, + (const char *) "internet", + (u_int) 1, + &this->server_thread_manager_, + (u_int) 0), // task id 0. + -1); + + this->high_priority_ = + this->priority_.get_high_priority (); + + ACE_DEBUG ((LM_DEBUG, + "Creating servant 0 with high priority %d\n", + this->high_priority_)); + + // Make the high priority task an active object. + if (high_priority_task->activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 0, + this->high_priority_) == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "\thigh_priority_task->activate failed")); + + ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon, GLOBALS::instance ()->ready_mtx_,-1)); + + // Wait on the condition variable till the high priority cubit_task + // has finished argument processing. + while (!GLOBALS::instance ()->ready_) + GLOBALS::instance ()->ready_cnd_.wait (); + // wait on the barrier till the servant writes its ior. + GLOBALS::instance ()->barrier_->wait (); + + this->ts_->one_ior_ = + high_priority_task->get_servant_ior (0); + + return 0; +} + +int +Client_i::do_priority_inversion_test (void) +{ + this->timer_.start (); +#if defined (ACE_VXWORKS) +# if !defined (__RTP__) && !defined (ACE_HAS_PTHREADS) + ctx = 0; +# endif + ACE_NEW_RETURN (this->task_id_, + char[TASK_ID_LEN], + -1); +#endif /* ACE_VXWORKS */ + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) <<<<<<< starting test on %D\n")); + GLOBALS::instance ()->num_of_objs = 1; + + for (int j = 0; j < this->argc_; j++) + if (ACE_OS::strcmp (this->argv_[j], "-u") == 0) + { + this->start_servant (); + break; + } + // Create and activate the high priority client. + int result = this->activate_high_client (); + if (result < 0) + return result; + + ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon, this->ts_->ready_mtx_,-1)); + + // Wait on the condition variable until the high priority thread + // wakes us up. + while (!this->ts_->ready_) + this->ts_->ready_cnd_.wait (); + + result = this->activate_low_client (); + + if (result < 0) + return result; + + // Activate the utilization thread if necessary. + result = this->activate_util_thread (); + if (result < 0) + return result; + + // Wait for all the client threads to be initialized before going + // any further. + this->ts_->barrier_->wait (); + + STOP_QUANTIFY; + CLEAR_QUANTIFY; + + // Collect the context switch data. + this->get_context_switches (); + + // Wait for all the client threads to exit (except the utilization + // thread). + this->client_thread_manager_.wait (); + + STOP_QUANTIFY; + ACE_DEBUG ((LM_DEBUG,"(%P|%t) >>>>>>> ending test on %D\n")); + + this->timer_.stop (); + this->timer_.elapsed_time (this->delta_); + + // Signal the utilization thread to finish with its work.. only if + // utilization test was specified. See description of this variable + // in header file. + if (this->ts_->use_utilization_test_ == 1) + { + this->util_thread_->done_ = 1; + + // This will wait for the utilization thread to finish. + this->util_thread_manager_.wait (); + } + + ACE_DEBUG ((LM_DEBUG, + "-------------------------- Stats -------------------------------\n")); + + this->print_priority_inversion_stats (); + + return 0; +} + +int +Client_i::do_thread_per_rate_test (void) +{ + Client CB_20Hz_client (&this->client_thread_manager_, + this->ts_, + this->argc_, + this->argv_, + CB_20HZ_CONSUMER); + Client CB_10Hz_client (&this->client_thread_manager_, + this->ts_, + this->argc_, + this->argv_, + CB_10HZ_CONSUMER); + Client CB_5Hz_client (&this->client_thread_manager_, + this->ts_, + this->argc_, + this->argv_, + CB_5HZ_CONSUMER); + Client CB_1Hz_client (&this->client_thread_manager_, + this->ts_, + this->argc_, + this->argv_, + CB_1HZ_CONSUMER); + ACE_Sched_Priority priority; + + priority = this->priority_.get_high_priority (); + ACE_DEBUG ((LM_DEBUG, + "Creating 20 Hz client with priority %d\n", + priority)); + + if (CB_20Hz_client.activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 1, + priority) == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) errno = %p: activate failed\n")); + // The high priority thread is parsing the arguments, so wait on the + // condition variable until it wakes us up. + + ACE_DEBUG ((LM_DEBUG, + "(%t) Waiting for argument parsing\n")); + + ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon, this->ts_->ready_mtx_,-1)); + + // Wait on the condition variable until the high priority thread + // wakes us up. + while (!this->ts_->ready_) + this->ts_->ready_cnd_.wait (); + + ACE_DEBUG ((LM_DEBUG, + "(%t) Argument parsing waiting done\n")); + + priority = ACE_Sched_Params::previous_priority (ACE_SCHED_FIFO, + priority, + ACE_SCOPE_THREAD); + ACE_DEBUG ((LM_DEBUG, + "Creating 10 Hz client with priority %d\n", + priority)); + + if (CB_10Hz_client.activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 1, + priority) == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) errno = %p: activate failed\n")); + + priority = ACE_Sched_Params::previous_priority (ACE_SCHED_FIFO, + priority, + ACE_SCOPE_THREAD); + ACE_DEBUG ((LM_DEBUG, + "Creating 5 Hz client with priority %d\n", + priority)); + + if (CB_5Hz_client.activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 1, + priority) == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) errno = %p: activate failed\n")); + + priority = ACE_Sched_Params::previous_priority (ACE_SCHED_FIFO, + priority, + ACE_SCOPE_THREAD); + ACE_DEBUG ((LM_DEBUG, + "Creating 1 Hz client with priority %d\n", + priority)); + + if (CB_1Hz_client.activate ( + GLOBALS::instance ()->thr_create_flags, + 1, + 1, + priority) == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) errno = %p: activate failed\n")); + + // Wait for all the threads to exit. + this->client_thread_manager_.wait (); + + ACE_DEBUG ((LM_DEBUG, + "Test done.\n" + "20Hz client latency : %A usec, jitter: %A usec\n" + "10Hz client latency : %A usec, jitter: %A usec\n" + "5Hz client latency : %A usec, jitter: %A usec\n" + "1Hz client latency : %A usec, jitter: %A usec\n", + CB_20Hz_client.get_latency (0), + CB_20Hz_client.get_jitter (0), + CB_10Hz_client.get_latency (1), + CB_10Hz_client.get_jitter (1), + CB_5Hz_client.get_latency (2), + CB_5Hz_client.get_jitter (2), + CB_1Hz_client.get_latency (3), + CB_1Hz_client.get_jitter (3) )); + return 0; +} + +// This is the main routine of the client, where we create a high +// priority and a low priority client. we then activate the clients +// with the appropriate priority threads, and wait for them to +// finish. After they aer done, we compute the latency and jitter +// metrics and print them. + +int +main (int argc, char *argv[]) +{ + ACE_Log_Msg::instance()->clr_flags (ACE_Log_Msg::LOGGER); + + Client_i client; + + int result = client.init (argc,argv); + + if (result < 0) + return result; + + // Run the tests. + client.run (); + +#if defined (CHORUS_MVME) + int pTime; + if (pccTimer (PCC2_TIMER1_STOP, + &pTime) != K_OK) + ACE_DEBUG ((LM_DEBUG, + "pccTimer has a pending bench mark\n")); +#endif /* CHORUS_MVME */ + return 0; +} |