From fa4664c4ea09adecda77394d37abf806d87a5048 Mon Sep 17 00:00:00 2001 From: Alex Lin Date: Tue, 30 Aug 2016 10:56:18 -0500 Subject: [PATCH] Move the loop that waits for scheduled threads to finish out of advance_sim_time #292 2 problems found. Syncing scheduled threads was not happening at all because the job was not being rescheduled. Did not want to deal with changing job call times so I called the new scheuduled_thread_sync routine from advance_sim_time. That's where it started, it'll be fine. Also found that I was resetting job complete flags too aggressively. The check to test if the thread is ready to run was missing. Added that check back in. --- include/trick/Executive.hh | 6 ++++ share/trick/sim_objects/default_trick_sys.sm | 2 -- .../Executive/Executive_advance_sim_time.cpp | 3 ++ .../Executive_isThreadReadyToRun.cpp | 36 +++++++++++++++++++ .../Executive/Executive_loop_multi_thread.cpp | 30 ++-------------- .../Executive/Executive_thread_sync.cpp | 23 ++++++------ 6 files changed, 58 insertions(+), 42 deletions(-) create mode 100644 trick_source/sim_services/Executive/Executive_isThreadReadyToRun.cpp diff --git a/include/trick/Executive.hh b/include/trick/Executive.hh index 3d594b3a..ee6f8e19 100644 --- a/include/trick/Executive.hh +++ b/include/trick/Executive.hh @@ -271,6 +271,12 @@ namespace Trick { */ void reset_job_call_times() ; + /** + Internal call to test if thread is ready to run + @return bool + */ + bool isThreadReadyToRun( Trick::Threads * curr_thread , long long time_tics) ; + public: Executive() ; diff --git a/share/trick/sim_objects/default_trick_sys.sm b/share/trick/sim_objects/default_trick_sys.sm index 70ab275d..f945fdcb 100644 --- a/share/trick/sim_objects/default_trick_sys.sm +++ b/share/trick/sim_objects/default_trick_sys.sm @@ -158,8 +158,6 @@ class SysSimObject : public Trick::SimObject { ("freeze_init") sched.init_freeze_scheduled() ; - // sync all scheduled threads before advancing time - {TRK} ("system_advance_sim_time") sched.scheduled_thread_sync() ; // required job to advance sim time {TRK} ("system_advance_sim_time") sched.advance_sim_time() ; diff --git a/trick_source/sim_services/Executive/Executive_advance_sim_time.cpp b/trick_source/sim_services/Executive/Executive_advance_sim_time.cpp index 9de338dc..30961b27 100644 --- a/trick_source/sim_services/Executive/Executive_advance_sim_time.cpp +++ b/trick_source/sim_services/Executive/Executive_advance_sim_time.cpp @@ -17,6 +17,9 @@ int Trick::Executive::advance_sim_time() { unsigned int ii ; + // synchronize the scheduled threads before advancing time. + scheduled_thread_sync() ; + /* Save the current time to time_last_pass */ time_last_pass_tics = time_tics ; diff --git a/trick_source/sim_services/Executive/Executive_isThreadReadyToRun.cpp b/trick_source/sim_services/Executive/Executive_isThreadReadyToRun.cpp new file mode 100644 index 00000000..5af3238f --- /dev/null +++ b/trick_source/sim_services/Executive/Executive_isThreadReadyToRun.cpp @@ -0,0 +1,36 @@ + +#include "trick/Executive.hh" + +/* +-# Switch on the type of thread + -# Scheduled threads are always ready to run + -# AMF thredas are ready to run if their previous frame just finished + -# ASYNC threads are ready to run if their complete flag is set and either they have + no cycle time or their previous frame just finished. +*/ +bool Trick::Executive::isThreadReadyToRun( Trick::Threads * curr_thread , long long time_tics) { + bool ret = false ; + switch ( curr_thread->process_type ) { + case Trick::PROCESS_TYPE_SCHEDULED: + ret = true ; + break ; + case Trick::PROCESS_TYPE_AMF_CHILD: + if ( curr_thread->amf_next_tics == time_tics ) { + ret = true ; + } + break ; + case Trick::PROCESS_TYPE_ASYNC_CHILD: + if ( curr_thread->child_complete == true ) { + if (curr_thread->amf_cycle_tics == 0 ) { + ret = true ; + } else { + if ( curr_thread->amf_next_tics == time_tics ) { + ret = true ; + } + } + } + break ; + } + return ret ; +} + 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 843d4267..6218836e 100644 --- a/trick_source/sim_services/Executive/Executive_loop_multi_thread.cpp +++ b/trick_source/sim_services/Executive/Executive_loop_multi_thread.cpp @@ -7,32 +7,6 @@ #include "trick/exec_proto.h" #include "trick/release.h" -static bool isThreadReadyToRun( Trick::Threads * curr_thread , long long time_tics) { - bool ret = false ; - switch ( curr_thread->process_type ) { - case Trick::PROCESS_TYPE_SCHEDULED: - ret = true ; - break ; - case Trick::PROCESS_TYPE_AMF_CHILD: - if ( curr_thread->amf_next_tics == time_tics ) { - ret = true ; - } - break ; - case Trick::PROCESS_TYPE_ASYNC_CHILD: - if ( curr_thread->child_complete == true ) { - if (curr_thread->amf_cycle_tics == 0 ) { - ret = true ; - } else { - if ( curr_thread->amf_next_tics == time_tics ) { - ret = true ; - } - } - } - break ; - } - return ret ; -} - /** @details -# Wait for all synchronous threads to finish initializing before entering infinite loop @@ -54,9 +28,9 @@ static bool isThreadReadyToRun( Trick::Threads * curr_thread , long long time_ti calling Trick::ScheduledJobQueue::test_next_job_call_time(Trick::JobData *, long long) -# If the exec_command equals ExitCmd -# Call Trick::Executive::exec_terminate_with_return(int, char *, int, char *) - -# If the elapsed time has reached the termination time + -# If the elapsed time has reached the termination time -# Call Trick::Executive::exec_terminate_with_return(int, char *, int, char *) - -# If the elapsed time equals the next software frame time + -# If the elapsed time equals the next software frame time -# Call the end_of_frame jobs. Requirement [@ref r_exec_periodic_2] -# Set the end of frame execution time to the current time + software_frame */ diff --git a/trick_source/sim_services/Executive/Executive_thread_sync.cpp b/trick_source/sim_services/Executive/Executive_thread_sync.cpp index be1f608d..79022d6c 100644 --- a/trick_source/sim_services/Executive/Executive_thread_sync.cpp +++ b/trick_source/sim_services/Executive/Executive_thread_sync.cpp @@ -33,10 +33,6 @@ int Trick::Executive::thread_sync() { RELEASE(); } } - curr_thread->job_queue.reset_curr_index(); - while ( (curr_job = curr_thread->job_queue.find_job(time_tics)) != NULL ) { - curr_job->complete = false; - } } else if ( curr_thread->process_type == PROCESS_TYPE_ASYNC_CHILD ) { if ( curr_thread->child_complete == true ) { @@ -46,18 +42,21 @@ int Trick::Executive::thread_sync() { curr_thread->amf_next_tics += curr_thread->amf_cycle_tics ; } } - curr_thread->job_queue.reset_curr_index(); - while ( (curr_job = curr_thread->job_queue.find_job(time_tics)) != NULL ) { - curr_job->complete = false; - } } } } - /* reset the job complete flags on thread 0 (master thread) */ - threads[0]->job_queue.reset_curr_index(); - while ( (curr_job = threads[0]->job_queue.find_job(time_tics)) != NULL ) { - curr_job->complete = false; + /* Go through all of the job queues and mark all jobs that are to run this time step to not complete. */ + for (ii = 0; ii < threads.size() ; ii++) { + Threads * curr_thread = threads[ii] ; + /* For all threads that are waiting to start the next cycle (child_complete == true) + reset job completion flags */ + if ( isThreadReadyToRun(curr_thread, time_tics) ) { + curr_thread->job_queue.reset_curr_index(); + while ( (curr_job = curr_thread->job_queue.find_job(time_tics)) != NULL ) { + curr_job->complete = false; + } + } } return(0) ;