diff --git a/include/trick/Executive.hh b/include/trick/Executive.hh index a545253e7..5e58a4ef2 100644 --- a/include/trick/Executive.hh +++ b/include/trick/Executive.hh @@ -276,6 +276,15 @@ namespace Trick { /** S_run_summary - Trick version.\n */ std::string current_version; /**< trick_units(--) */ + /** rt_nap statistics - total number of rt_nap that is longer than 10% of the software frame.\n */ + int rt_nap_count; /**< trick_units(--) */ + + /** rt_nap statistics - the longest rt_nap.\n */ + double longest_rt_nap; /**< trick_units(s) */ + + /** rt_nap statistics - the shortest rt_nap.\n */ + double shortest_rt_nap; /**< trick_units(s) */ + /** @userdesc Command to reset job cycle times after the time_tic_value has changed. @return void @@ -875,6 +884,16 @@ namespace Trick { */ int set_current_version(std::string version) ; + /** + @userdesc Set stats after each RELEASE() when rt_nap is true. The stats contains the counts of + RELEASE() if the time delta between before and after RELEASE() is greater than 10% of the + software frame time, the longest delta, and the shortest delta of before and after RELEASE(). + @param clock_time_before_rt_nap - clock time before RELEASE() is called when rt_nap is true. + @param clock_time_after_rt_nap - clock time after RELEASE() is done when rt_nap is true. + @reutnr void + */ + void set_rt_nap_stats(long long clock_time_before_rt_nap, long long clock_time_after_rt_nap) ; + // END GET and SET FUNCTIONS /** diff --git a/include/trick/exec_proto.h b/include/trick/exec_proto.h index d536c79eb..607c16e56 100644 --- a/include/trick/exec_proto.h +++ b/include/trick/exec_proto.h @@ -74,6 +74,7 @@ extern "C" { int exec_set_version_date_tag(const char * tag) ; int exec_set_build_date(const char * date) ; int exec_set_current_version(const char * version) ; + void exec_set_rt_nap_stats(long long clock_time_before_rt_nap, long long clock_time_after_rt_nap) ; int exec_freeze(void) ; int exec_run(void) ; diff --git a/trick_source/sim_services/Clock/Clock.cpp b/trick_source/sim_services/Clock/Clock.cpp index 420ded5ad..020550d6e 100644 --- a/trick_source/sim_services/Clock/Clock.cpp +++ b/trick_source/sim_services/Clock/Clock.cpp @@ -84,11 +84,15 @@ long long Trick::Clock::clock_time() { */ long long Trick::Clock::clock_spin(long long req_time) { long long curr_time ; + long long time_before_rt_nap, time_after_rt_nap ; curr_time = clock_time() ; /* Perform spin loop to allow current time to catch up to requested time */ while (curr_time < req_time) { if ( exec_get_rt_nap() == 1 ) { + time_before_rt_nap = wall_clock_time() ; RELEASE(); + time_after_rt_nap = wall_clock_time() ; + exec_set_rt_nap_stats(time_before_rt_nap, time_after_rt_nap) ; } curr_time = clock_time(); } diff --git a/trick_source/sim_services/Clock/test/Makefile b/trick_source/sim_services/Clock/test/Makefile index fe58b2771..cbbe6c2be 100644 --- a/trick_source/sim_services/Clock/test/Makefile +++ b/trick_source/sim_services/Clock/test/Makefile @@ -21,7 +21,7 @@ BASE_OBJECTS = ../object_${TRICK_HOST_CPU}/Clock.o\ ../object_${TRICK_HOST_CPU}/clock_c_intf.o -GETTIMEOFDAY_CLOCK_OBJECTS = ${BASE_OBJECTS} GetTimeOfDayClock_test.o ../object_${TRICK_HOST_CPU}/GetTimeOfDayClock.o exec_get_rt_nap_stub.o +GETTIMEOFDAY_CLOCK_OBJECTS = ${BASE_OBJECTS} GetTimeOfDayClock_test.o ../object_${TRICK_HOST_CPU}/GetTimeOfDayClock.o exec_get_rt_nap_stub.o exec_set_rt_nap_stats_stub.o # All tests produced by this Makefile. Remember to add new tests you # created to the list. @@ -45,3 +45,6 @@ GetTimeOfDayClock_test : ${GETTIMEOFDAY_CLOCK_OBJECTS} exec_get_rt_nap_stub.o : exec_get_rt_nap_stub.cpp $(TRICK_CXX) $(TRICK_CPPFLAGS) -c $< + +exec_set_rt_nap_stats_stub.o : exec_set_rt_nap_stats_stub.cpp + $(TRICK_CXX) $(TRICK_CPPFLAGS) -c $< diff --git a/trick_source/sim_services/Clock/test/exec_set_rt_nap_stats_stub.cpp b/trick_source/sim_services/Clock/test/exec_set_rt_nap_stats_stub.cpp new file mode 100644 index 000000000..58bc02092 --- /dev/null +++ b/trick_source/sim_services/Clock/test/exec_set_rt_nap_stats_stub.cpp @@ -0,0 +1,3 @@ +extern "C" void exec_set_rt_nap_stats(long long clock_time_before_rt_nap, long long clock_time_after_rt_nap) { + +} diff --git a/trick_source/sim_services/Executive/Executive.cpp b/trick_source/sim_services/Executive/Executive.cpp index 5b4759a7e..75e49ed41 100644 --- a/trick_source/sim_services/Executive/Executive.cpp +++ b/trick_source/sim_services/Executive/Executive.cpp @@ -417,3 +417,19 @@ int Trick::Executive::set_current_version(std::string version) { int Trick::Executive::get_except_return() const { return except_return; } + +void Trick::Executive::set_rt_nap_stats(long long clock_time_before_rt_nap, long long clock_time_after_rt_nap) { + double rt_nap_elapsed_time = (double)(clock_time_after_rt_nap - clock_time_before_rt_nap) / time_tic_value ; + if (rt_nap_elapsed_time / software_frame > 0.1) { + rt_nap_count++ ; + } + if (longest_rt_nap < rt_nap_elapsed_time) { + longest_rt_nap = rt_nap_elapsed_time ; + } + + if (shortest_rt_nap == 0.0) { + shortest_rt_nap = rt_nap_elapsed_time ; + } else if (shortest_rt_nap > rt_nap_elapsed_time) { + shortest_rt_nap = rt_nap_elapsed_time ; + } +} \ No newline at end of file diff --git a/trick_source/sim_services/Executive/Executive_c_intf.cpp b/trick_source/sim_services/Executive/Executive_c_intf.cpp index 8e88f0c05..861988683 100644 --- a/trick_source/sim_services/Executive/Executive_c_intf.cpp +++ b/trick_source/sim_services/Executive/Executive_c_intf.cpp @@ -737,6 +737,17 @@ extern "C" const char * exec_get_current_version() { return NULL ; } +/** + * @relates Trick::Executive + * @copydoc Trick::Executive::set_rt_nap_stats + * C wrapper for Trick::Executive::set_rt_nap_stats + */ +extern "C" void exec_set_rt_nap_stats(long long clock_time_before_rt_nap, long long clock_time_after_rt_nap) { + if ( the_exec != NULL ) { + the_exec->set_rt_nap_stats(clock_time_before_rt_nap, clock_time_before_rt_nap) ; + } +} + /** * @relates Trick::Executive * @userdesc Raise a signal on the main thread to terminate the simuation immediately. diff --git a/trick_source/sim_services/Executive/Executive_loop_multi_thread.cpp b/trick_source/sim_services/Executive/Executive_loop_multi_thread.cpp index 34e348c1d..cd0b3b69c 100644 --- a/trick_source/sim_services/Executive/Executive_loop_multi_thread.cpp +++ b/trick_source/sim_services/Executive/Executive_loop_multi_thread.cpp @@ -6,6 +6,8 @@ #include "trick/Executive.hh" #include "trick/exec_proto.h" #include "trick/release.h" +#include "trick/clock_proto.h" +#include "trick/Executive.hh" /** @details @@ -40,13 +42,17 @@ int Trick::Executive::loop_multi_thread() { unsigned int ii ; Trick::ScheduledJobQueue * main_sched_queue ; int ret = 0 ; + long long time_before_rt_nap, time_after_rt_nap; /* Wait for all threads to finish initializing and set the child_complete flag. */ for (ii = 1; ii < threads.size() ; ii++) { Threads * curr_thread = threads[ii] ; while (curr_thread->child_complete == false ) { if (rt_nap == true) { - RELEASE(); + time_before_rt_nap = clock_wall_time() ; + RELEASE() ; + time_after_rt_nap = clock_wall_time() ; + set_rt_nap_stats(time_before_rt_nap, time_after_rt_nap) ; } } } @@ -146,7 +152,10 @@ int Trick::Executive::loop_multi_thread() { depend_job = curr_job->depends[ii] ; while (! depend_job->complete) { if (rt_nap == true) { + time_before_rt_nap = clock_wall_time() ; RELEASE(); + time_after_rt_nap = clock_wall_time() ; + set_rt_nap_stats(time_before_rt_nap, time_after_rt_nap) ; } } } diff --git a/trick_source/sim_services/Executive/Executive_scheduled_thread_sync.cpp b/trick_source/sim_services/Executive/Executive_scheduled_thread_sync.cpp index 59f631e27..032095562 100644 --- a/trick_source/sim_services/Executive/Executive_scheduled_thread_sync.cpp +++ b/trick_source/sim_services/Executive/Executive_scheduled_thread_sync.cpp @@ -3,6 +3,7 @@ #include "trick/Executive.hh" #include "trick/release.h" +#include "trick/clock_proto.h" /** @design @@ -12,14 +13,17 @@ int Trick::Executive::scheduled_thread_sync() { unsigned int ii ; - + long long time_before_rt_nap, time_after_rt_nap ; /* Wait for synchronous threads to finish before testing for adjusting time_tics */ for (ii = 1; ii < threads.size() ; ii++) { Threads * curr_thread = threads[ii] ; if ( curr_thread->enabled and curr_thread->process_type == PROCESS_TYPE_SCHEDULED) { while (curr_thread->child_complete == false ) { if (rt_nap == true) { + time_before_rt_nap = clock_wall_time() ; RELEASE(); + time_after_rt_nap = clock_wall_time() ; + set_rt_nap_stats(time_before_rt_nap, time_after_rt_nap) ; } } } diff --git a/trick_source/sim_services/Executive/Executive_shutdown.cpp b/trick_source/sim_services/Executive/Executive_shutdown.cpp index 9e431eb46..2c91e875b 100644 --- a/trick_source/sim_services/Executive/Executive_shutdown.cpp +++ b/trick_source/sim_services/Executive/Executive_shutdown.cpp @@ -125,6 +125,16 @@ int Trick::Executive::shutdown() { user_cpu_time, kernal_cpu_time, sim_to_cpu, user_cpu_init, kernal_cpu_init, sim_mem) ; + if (rt_nap == true) { + message_publish(MSG_NORMAL , "\n\n" + " SIMULATION RT NAP STATS\n" + " RT NAP COUNTS: %17d\n" + " (RT NAP / SOFTWARE FRAME > 0.1)\n" + " LONGEST RT NAP: %12.15f\n" + " SHORTEST RT NAP: %12.15f\n", + rt_nap_count, longest_rt_nap, shortest_rt_nap) ; + } + /* Kill all threads. */ for (ii = 1; ii < threads.size() ; ii++) { if ( threads[ii]->running ) { diff --git a/trick_source/sim_services/Executive/Executive_thread_sync.cpp b/trick_source/sim_services/Executive/Executive_thread_sync.cpp index 79022d6c6..a43a546a9 100644 --- a/trick_source/sim_services/Executive/Executive_thread_sync.cpp +++ b/trick_source/sim_services/Executive/Executive_thread_sync.cpp @@ -3,6 +3,7 @@ #include "trick/Executive.hh" #include "trick/release.h" +#include "trick/clock_proto.h" /** @design @@ -22,6 +23,7 @@ int Trick::Executive::thread_sync() { unsigned int ii ; + long long time_before_rt_nap, time_after_rt_nap ; /* Wait for async_must finish to complete at the current time_tics */ for (ii = 1; ii < threads.size() ; ii++) { @@ -30,7 +32,10 @@ int Trick::Executive::thread_sync() { (curr_thread->amf_next_tics == time_tics )) { while (curr_thread->child_complete == false ) { if (rt_nap == true) { + time_before_rt_nap = clock_wall_time() ; RELEASE(); + time_after_rt_nap = clock_wall_time() ; + set_rt_nap_stats(time_before_rt_nap, time_after_rt_nap) ; } } } diff --git a/trick_source/sim_services/Executive/Threads_child.cpp b/trick_source/sim_services/Executive/Threads_child.cpp index 3a9ac40b9..4b38118cb 100644 --- a/trick_source/sim_services/Executive/Threads_child.cpp +++ b/trick_source/sim_services/Executive/Threads_child.cpp @@ -22,10 +22,12 @@ #include "trick/Threads.hh" #include "trick/release.h" +#include "trick/Executive.hh" #include "trick/ExecutiveException.hh" #include "trick/exec_proto.h" #include "trick/TrickConstant.hh" #include "trick/message_proto.h" +#include "trick/clock_proto.h" /** @@ -41,6 +43,7 @@ static int call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & j Trick::JobData * depend_job ; unsigned int ii ; int ret = 0 ; + long long time_before_rt_nap, time_after_rt_nap ; //cout << "time = " << curr_time_tics << " " << curr_job->name << " job next = " // << curr_job->next_tics << " id = " << curr_job->id << endl ; @@ -50,7 +53,10 @@ static int call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & j depend_job = curr_job->depends[ii] ; while (! depend_job->complete) { if (rt_nap == true) { + time_before_rt_nap = clock_wall_time() ; RELEASE(); + time_after_rt_nap = clock_wall_time() ; + the_exec->set_rt_nap_stats(time_before_rt_nap, time_after_rt_nap) ; } } }