int Trick::DataRecordGroup::call_function( Trick::JobData * curr_job ) { int ret = 0 ; switch (curr_job->id) { case 1: ret = init() ; break ; case 2: ret = write_data(false) ; break ; case 3: ret = checkpoint() ; break ; case 4: clear_checkpoint_vars() ; break ; case 5: ret = restart() ; break ; case 6: ret = shutdown() ; break ; default: ret = data_record(exec_get_sim_time()) ; break ; } return(ret) ; }
int Trick::DataRecordDispatcher::record_now_group( const char * in_name ) { unsigned int ii ; if ( in_name != NULL ) { for ( ii = 0 ; ii < groups.size() ; ii++ ) { if ( !groups[ii]->get_group_name().compare(in_name) ) groups[ii]->data_record(exec_get_sim_time()) ; } } return 0 ; }
/* @details -# if the path is empty after /commands create commands top level page. -# else if the path is exec_get_sim_time return create a message with the sim time. -# else create an error message. */ int Trick::JSONVariableServerThread::get_commands( std::stringstream & body , char * path ) { int ret = 200 ; if ( path[strlen(path) - 1] == '/') { path[strlen(path) - 1] = '\0' ; } if ( path[0] == '\0' ) { body << " \"exec_get_sim_time\": \"exec_get_sim_time()\"" << std::endl ; } else if ( ! strcmp( path , "/exec_get_sim_time" ) ) { body << " \"sim_time\": \"" << exec_get_sim_time() << "\"" << std::endl ; } else { body << " \"message\" : \"Not Found\"" << std::endl ; ret = 404 ; } return ret ; }
double Trick::SimTime::get_mettime() { return(exec_get_sim_time() + met_sec_ref); }
double Trick::SimTime::get_rettime() { return(exec_get_sim_time()); }
/** @details -# Block all signals to the child. -# Set the thread cancel type to asynchronous to allow master to this child at any time. -# Lock the go mutex so the master has to wait until this child is ready before staring execution. -# Set thread priority and CPU affinity -# The child enters an infinite loop -# Blocks on mutex or frame trigger until master signals to start processing -# Switch if the child is a synchronous thread -# For each scheduled jobs whose next call time is equal to the current simulation time [@ref ScheduledJobQueue] -# Call call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & job_queue, bool rt_nap, long long curr_time_tics) -# Switch if the child is a asynchronous must finish thread -# Do while the job queue time is less than the time of the next AMF sync time. -# For each scheduled jobs whose next call time is equal to the current queue time -# Call call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & job_queue, bool rt_nap, long long curr_time_tics) -# Switch if the child is a asynchronous thread -# For each scheduled jobs -# Call call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & job_queue, bool rt_nap, long long curr_time_tics) -# Set the child complete flag */ void * Trick::Threads::thread_body() { /* Lock the go mutex so the master has to wait until this child is ready before staring execution. */ pthread_mutex_lock(&go_mutex); /* signal the master that the child is ready and running */ child_complete = true; running = true ; try { do { /* Block child on go mutex or frame trigger until master signals. */ if (rt_semaphores == true) { pthread_cond_wait(&go_cv, &go_mutex); } else { /* Else the child process frame is being started when a shared memory flag... */ while (frame_trigger == false) {} ; frame_trigger = false ; } if ( enabled ) { switch ( process_type ) { case PROCESS_TYPE_SCHEDULED: /* Loop through all jobs currently scheduled to run at this simulation time step. */ job_queue.reset_curr_index() ; job_queue.set_next_job_call_time(TRICK_MAX_LONG_LONG) ; while ( (curr_job = job_queue.find_next_job( curr_time_tics )) != NULL ) { call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ; } break ; case PROCESS_TYPE_AMF_CHILD: /* call the AMF top of frame jobs */ top_of_frame_queue.reset_curr_index() ; while ( (curr_job = top_of_frame_queue.get_next_job()) != NULL ) { int ret ; ret = curr_job->call() ; if ( ret != 0 ) { exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " top_of_frame job did not return 0") ; } } /* Loop through all jobs currently up to the point of the next AMF frame sync */ do { job_queue.reset_curr_index() ; job_queue.set_next_job_call_time(amf_next_tics) ; while ( (curr_job = job_queue.find_next_job( curr_time_tics )) != NULL ) { call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ; } curr_time_tics = job_queue.get_next_job_call_time() ; } while ( curr_time_tics < amf_next_tics ) ; /* call the AMF end of frame jobs */ end_of_frame_queue.reset_curr_index() ; while ( (curr_job = end_of_frame_queue.get_next_job()) != NULL ) { int ret ; ret = curr_job->call() ; if ( ret != 0 ) { exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " end_of_frame job did not return 0") ; } } break ; case PROCESS_TYPE_ASYNC_CHILD: /* Loop through all jobs once */ if ( amf_cycle_tics == 0 ) { // Old behavior, run all jobs once and return. job_queue.reset_curr_index() ; job_queue.set_next_job_call_time(TRICK_MAX_LONG_LONG) ; while ( (curr_job = job_queue.get_next_job()) != NULL ) { call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ; } } else { // catch up job next times to current frame. job_queue.reset_curr_index() ; while ( (curr_job = job_queue.get_next_job()) != NULL ) { long long start_frame = amf_next_tics - amf_cycle_tics ; while ( curr_job->next_tics < start_frame ) { curr_job->next_tics += curr_job->cycle_tics ; } } // New behavior, run a mini scheduler. /* call the AMF top of frame jobs */ top_of_frame_queue.reset_curr_index() ; while ( (curr_job = top_of_frame_queue.get_next_job()) != NULL ) { int ret ; ret = curr_job->call() ; if ( ret != 0 ) { exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " top_of_frame job did not return 0") ; } } /* Loop through all jobs currently up to the point of the next AMF frame sync */ do { job_queue.reset_curr_index() ; job_queue.set_next_job_call_time(amf_next_tics) ; while ( (curr_job = job_queue.find_next_job( curr_time_tics )) != NULL ) { call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ; } curr_time_tics = job_queue.get_next_job_call_time() ; } while ( curr_time_tics < amf_next_tics ) ; /* call the AMF end of frame jobs */ end_of_frame_queue.reset_curr_index() ; while ( (curr_job = end_of_frame_queue.get_next_job()) != NULL ) { int ret ; ret = curr_job->call() ; if ( ret != 0 ) { exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " end_of_frame job did not return 0") ; } } } break ; default: break ; } } /* After all jobs have completed, set the child_complete flag to true. */ child_complete = true; } while (1); } catch (Trick::ExecutiveException & ex ) { fprintf(stderr, "\nCHILD THREAD %d TERMINATED with exec_terminate\n ROUTINE: %s\n DIAGNOSTIC: %s\n" " THREAD STOP TIME: %f\n" , thread_id, ex.file.c_str(), ex.message.c_str(), exec_get_sim_time()) ; exit(ex.ret_code) ; } catch (const std::exception &ex) { std::string except_file ; if ( curr_job != NULL ) { except_file = curr_job->name ; } else { except_file = "somewhere in Executive::run" ; } fprintf(stderr, "\nCHILD THREAD %d TERMINATED with exec_terminate\n ROUTINE: %s\n DIAGNOSTIC: %s\n" " THREAD STOP TIME: %f\n" , thread_id, except_file.c_str() , ex.what(), exec_get_sim_time()) ; exit(-1) ; #ifdef __linux #ifdef __GNUC__ #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2 // for post gcc 4.1.2 } catch (abi::__forced_unwind&) { //pthread_exit and pthread_cancel will cause an abi::__forced_unwind to be thrown. Rethrow it. throw; #endif #endif #endif } catch (...) { /* In gcc 4.1.2 I cannot find the catch type for the pthread_cancel forced_unwind exception so I changed the catch here to just rethrow all unknown exceptions. For the other architectures we signal the main thread for an orderly shutdown. */ #ifdef __linux #ifdef __GNUC__ #if __GNUC__ == 4 && __GNUC_MINOR__ == 1 throw; #else std::string except_file ; std::string except_message ; if ( curr_job != NULL ) { except_file = curr_job->name ; } else { except_file = "somewhere in Executive::run" ; } except_message = "unknown error" ; fprintf(stderr, "\nExecutive::loop terminated with unknown exception\n ROUTINE: %s\n DIAGNOSTIC: %s\n" " STOP TIME: %f\n" , except_file.c_str() , except_message.c_str() , exec_get_sim_time()) ; exit(-1) ; #endif #endif #endif } pthread_exit(NULL) ; return 0 ; }
bool Trick::IPPythonEvent::process_user_event( long long curr_time ) { int ii ; int return_val ; bool it_fired, it_ran; fired = false ; ran = false ; /** @li No need to evaluate any conditions if in manual mode. */ if (! manual) { hold = false ; /** @li Loop thru all conditions. */ for (ii=0; ii<condition_count; ii++) { /** @li Skip condition if it's been disabled. */ if (! condition_list[ii]->enabled ) { condition_list[ii]->fired = false ; continue ; } /** @li No need to evaluate condition if previously fired and hold is on. */ if (condition_list[ii]->hold && condition_list[ii]->fired) { ; } else { /** @li Evaluate the condition and set its fired state. */ condition_list[ii]->fired = false ; return_val = 0 ; if (condition_list[ii]->ref != NULL) { // if it's a variable, get it as a boolean if ( condition_list[ii]->ref->pointer_present ) { condition_list[ii]->ref->address = follow_address_path(condition_list[ii]->ref) ; } if ( condition_list[ii]->ref->address != NULL ) { return_val = *(bool *)condition_list[ii]->ref->address ; } } else if (condition_list[ii]->job != NULL) { // if it's a job, get its return value bool save_disabled_state = condition_list[ii]->job->disabled; condition_list[ii]->job->disabled = false; return_val = condition_list[ii]->job->call(); condition_list[ii]->job->disabled = save_disabled_state; } else { // otherwise use python to evaluate string std::string full_in_string ; ip->parse_condition(condition_list[ii]->str, return_val) ; } if (return_val) { //TODO: write to log/send_hs that trigger fired condition_list[ii]->fired = true ; condition_list[ii]->fired_count++ ; condition_list[ii]->fired_time = curr_time ; } } // end evaluate condition /** @li If cond_all is true, only set event fired/hold after all enabled conditions evaluated. */ if (ii==0) { fired = condition_list[ii]->fired ; hold = condition_list[ii]->hold ; } else { if (cond_all) { fired &= condition_list[ii]->fired ; hold &= condition_list[ii]->hold ; } else { fired |= condition_list[ii]->fired ; hold |= condition_list[ii]->hold ; } } } //end condition loop } it_fired = manual_fired || fired ; /** @li Set the event's fired state...cond_all: if all conditions fired , otherwise if any condition fired. */ if (it_fired) { fired_count++ ; fired_time = curr_time ; if (info_msg) { message_publish( MSG_INFO , "%12.6f Event %s fired.\n" , exec_get_sim_time() , name.c_str()) ; } if (!manual_fired) { active = false ; } } /** @li If the user specified any actions, run them here if a condition fired or manually fired. */ it_ran = false ; if (it_fired && (action_count > 0)) { /** @li Loop thru all actions. */ for (ii=0; ii<action_count; ii++) { /** @li No need to run action if it's been disabled. */ if (! action_list[ii]->enabled ) { action_list[ii]->ran = false ; continue ; } /** @li Run the action and set its ran state. */ if (action_list[ii]->job != NULL) { // if it's a job, do what the action type tells you switch (action_list[ii]->act_type) { case 0 : // python, should not get here break; case 1 : // On action_list[ii]->job->disabled = false; break; case 2 : // Off action_list[ii]->job->disabled = true; break; case 3 : // Call bool save_disabled_state = action_list[ii]->job->disabled; action_list[ii]->job->disabled = false; action_list[ii]->job->call(); action_list[ii]->job->disabled = save_disabled_state; break; } } else { // otherwise use python to evaluate string ip->parse(action_list[ii]->str) ; } it_ran = true ; action_list[ii]->ran = true ; action_list[ii]->ran_count++ ; action_list[ii]->ran_time = curr_time ; ran = true ; } /** @li Leave event fired state on if hold is on. */ manual_fired &= hold ; fired &= hold ; } /** @li Set the event's ran state if any actions were run. */ if (it_ran) { ran_count++ ; ran_time = curr_time ; } /** @li Return true if the event fired. */ return(it_fired) ; }