• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 17772917031

16 Sep 2025 04:46PM UTC coverage: 55.866% (-0.005%) from 55.871%
17772917031

Pull #1958

github

web-flow
Merge d8200bf04 into ed8b1979f
Pull Request #1958: Resolves potential-for-fpe-in-run_ratio-sample-calcs

10 of 12 new or added lines in 1 file covered. (83.33%)

5 existing lines in 3 files now uncovered.

12352 of 22110 relevant lines covered (55.87%)

267838.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.83
/trick_source/sim_services/Executive/Executive_loop_multi_thread.cpp
1

2
#include <iostream>
3
#include <fstream>
4
#include <sstream>
5

6
#include "trick/Executive.hh"
7
#include "trick/exec_proto.h"
8
#include "trick/release.h"
9

10
/**
11
@details
12
-# Wait for all synchronous threads to finish initializing before entering infinite loop
13
-# Enter an infinite loop.  A call to exec_terminate(const char *) or
14
   exec_terminate_with_return(int, const char *, int , const char * ) will exit the loop.
15
    -# For all asynchronous must finish threads that are to finish at this time, wait for their completion
16
    -# If the exec_command equals freeze mode, call Trick::Executive::freeze_loop().  Transition from
17
       freeze back to run will continue execution at this point.
18
       Requirement  [@ref r_exec_mode_1]
19
    -# Set the job complete flags for all jobs to false.
20
    -# Check to see if all child threads are alive.  If a thread has exited, call
21
       Trick::Executive::exec_terminate_with_return(int, char *, int, char *)
22
       Requirement  [@ref r_exec_thread_7]
23
    -# Signal threads to start the next time step of processing.
24
    -# For each scheduled jobs whose next call time is equal to the current simulation time [@ref ScheduledJobQueue]
25
        -# Wait for all job dependencies to complete.  Requirement  [@ref r_exec_thread_6]
26
        -# Call the job.  Requirement  [@ref r_exec_periodic_0]
27
        -# If the job is a system job, check to see if the next job call time is the lowest next time by
28
           calling Trick::ScheduledJobQueue::test_next_job_call_time(Trick::JobData *, long long)
29
    -# If the exec_command equals ExitCmd
30
       -# Call Trick::Executive::exec_terminate_with_return(int, char *, int, char *)
31
    -# If the elapsed time has reached the termination time
32
       -# Call Trick::Executive::exec_terminate_with_return(int, char *, int, char *)
33
    -# If the elapsed time equals the next software frame time
34
       -# Call the end_of_frame jobs. Requirement  [@ref r_exec_periodic_2]
35
       -# Set the end of frame execution time to the current time + software_frame
36
*/
37
int Trick::Executive::loop_multi_thread() {
2✔
38

39
    JobData * depend_job ;
40
    unsigned int ii ;
41
    Trick::ScheduledJobQueue * main_sched_queue ;
42
    int ret = 0 ;
2✔
43

44
    /* Wait for all threads to finish initializing and set the child_complete flag. */
45
    for (ii = 1; ii < threads.size() ; ii++) {
7✔
46
        Threads * curr_thread = threads[ii] ;
5✔
47
        while (curr_thread->child_complete == false ) {
5✔
UNCOV
48
            if (rt_nap == true) {
×
UNCOV
49
                RELEASE();
×
50
            }
51
        }
52
    }
53

54
    /* The main scheduler queue is the queue in thread 0 */
55
    main_sched_queue = &(threads[0]->job_queue) ;
2✔
56

57
    while (1) {
58

59
        /* Call freeze_loop() if commanded by freeze() or a <CTRL-C> signal was caught. */
60
        if (exec_command == FreezeCmd) {
1,402✔
61
            exec_command = NoCmd;
×
62
            freeze_loop();
×
63
        }
64

65
        /* Call all top of frame jobs if the simulation time equals to the time software frame boundary. */
66
        if (time_tics == next_frame_check_tics - software_frame_tics ) {
1,402✔
67
            top_of_frame_queue.reset_curr_index() ;
1,402✔
68
            while ( (curr_job = top_of_frame_queue.get_next_job()) != NULL ) {
5,608✔
69
                ret = curr_job->call() ;
4,206✔
70
                if ( ret != 0 ) {
4,206✔
71
                    exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "top_of_frame job did not return 0") ;
×
72
                }
73
            }
74

75
            for (ii = 1; ii < threads.size() ; ii++) {
5,207✔
76

77
                Trick::Threads * curr_thread = threads[ii];
3,805✔
78

79
                if (curr_thread->process_type == Trick::PROCESS_TYPE_SCHEDULED) {            
3,805✔
80
                    curr_thread->top_of_frame_queue.reset_curr_index() ;
1,001✔
81
                    while ( (curr_job = curr_thread->top_of_frame_queue.get_next_job()) != NULL ) {
3,003✔
82
                        ret = curr_job->call() ;
2,002✔
83
                        if ( ret != 0 ) {
2,002✔
84
                            exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "top_of_frame job did not return 0") ;
×
85
                        }
86
                    }
87
                }
88
            }
89
            
90
            frame_count++ ;
1,402✔
91
        }
92

93
    /* Loop through child threads calling their top of frame jobs */
94

95

96
        /* Call thread sync jobs (wait for threads that are scheduled to finish by current time) */
97
        thread_sync_queue.reset_curr_index() ;
1,402✔
98
        while ( (curr_job = thread_sync_queue.get_next_job()) != NULL ) {
2,804✔
99
            ret = curr_job->call() ;
1,402✔
100
            if ( ret != 0 ) {
1,402✔
101
                exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "thread_sync job did not return 0") ;
×
102
            }
103
        }
104

105
        /* Call the input_processor_run queue jobs. Run between threads ending and restarting */
106
        input_processor_run_queue.reset_curr_index() ;
1,402✔
107
        while ( (curr_job = input_processor_run_queue.find_next_job( time_tics )) != NULL ) {
1,411✔
108
            ret = curr_job->call() ;
9✔
109
            if ( ret != 0 ) {
9✔
110
                exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "input_processor_run job did not return 0") ;
×
111
            }
112
            // input processor jobs set their own next job call time.  The test_next_job_call_time
113
            // will adjust the next call time for this queue
114
            input_processor_run_queue.test_next_job_call_time(curr_job , time_tics) ;
9✔
115

116
            /* System jobs next call time are not set until after they run.
117
               Test their next job call time after they have been called */
118
            if ( curr_job->system_job_class ) {
9✔
119
                main_sched_queue->test_next_job_call_time(curr_job , time_tics) ;
9✔
120
            }
121
        }
122

123
        /* Start threads that are ready to run */
124
        for (ii = 1; ii < threads.size() ; ii++) {
5,207✔
125

126
            Trick::Threads * curr_thread = threads[ii] ;
3,805✔
127

128
            /* For all threads that are waiting to start the next cycle (child_complete == true)
129
               signal them to start through either the thread mutex or frame trigger. */
130
            if ( isThreadReadyToRun(curr_thread, time_tics) ) {
3,805✔
131

132
                curr_thread->curr_time_tics = time_tics ;
1,430✔
133
                curr_thread->child_complete = false ;
1,430✔
134
                curr_thread->amf_next_tics += curr_thread->amf_cycle_tics ;
1,430✔
135
                curr_thread->trigger_container.getThreadTrigger()->fire() ;
1,430✔
136

137
            }
138
        }
139

140
        /* Get next job scheduled to run at the current simulation time step. */
141
        main_sched_queue->reset_curr_index() ;
1,402✔
142
        while ( (curr_job = main_sched_queue->find_next_job( time_tics )) != NULL ) {
7,296✔
143

144
            /* Wait for all jobs that the current job depends on to complete. */
145
            for ( ii = 0 ; ii < curr_job->depends.size() ; ii++ ) {
5,894✔
146
                depend_job = curr_job->depends[ii] ;
×
147
                while (! depend_job->complete) {
×
148
                    if (rt_nap == true) {
×
149
                        RELEASE();
×
150
                    }
151
                }
152
            }
153

154
            /* Call the current job scheduled to run at the current simulation time step. */
155
            ret = curr_job->call() ;
5,894✔
156
            if ( ret != 0 ) {
5,894✔
157
                exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "scheduled job did not return 0") ;
×
158
            }
159
            /* System jobs next call time are not set until after they run.
160
               Test their next job call time after they have been called */
161
            if ( curr_job->system_job_class ) {
5,894✔
162
                main_sched_queue->test_next_job_call_time(curr_job , time_tics) ;
1,404✔
163
            }
164
            curr_job->complete = true ;
5,894✔
165
        }
166

167
        /* Call Executive::exec_terminate_with_return(int , const char * , int , const char *)
168
           if exec_command equals ExitCmd. */
169
        if (exec_command == ExitCmd) {
1,402✔
170
            exec_terminate_with_return( 0 , __FILE__ , __LINE__ , "Sim control Shutdown" ) ;
×
171
        }
172

173
        /* We are already in run... clear any redundant exec_commands to go to run */
174
        if ( exec_command == RunCmd ) {
1,402✔
175
            exec_command = NoCmd ;
×
176
        }
177

178
        /* Call Executive::exec_terminate_with_return( int , const char * , int , const char *)
179
           if simulation elapsed time has reached the termination time. */
180
        if (terminate_time <= time_last_pass_tics ) {
1,402✔
181
            time_tics = time_last_pass_tics ;
2✔
182
            exec_terminate_with_return( 0 , __FILE__ , __LINE__ , "Reached termination time" ) ;
2✔
183
        }
184

185
        /* Call all end of frame jobs if the simulation time equals to the time software frame boundary. */
186
        if (time_tics == next_frame_check_tics ) {
1,400✔
187
            end_of_frame_queue.reset_curr_index() ;
1,400✔
188
            while ( (curr_job = end_of_frame_queue.get_next_job()) != NULL ) {
12,600✔
189
                ret = curr_job->call() ;
11,200✔
190
                if ( ret != 0 ) {
11,200✔
191
                    exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "end_of_frame job did not return 0") ;
×
192
                }
193
            }
194
                         /* Loop through child threads calling their end of frame jobs */
195
            for (ii = 1; ii < threads.size() ; ii++) {
5,200✔
196

197
                Trick::Threads * curr_thread = threads[ii];
3,800✔
198

199
                if (curr_thread->process_type == Trick::PROCESS_TYPE_SCHEDULED) {
3,800✔
200
                    curr_thread->end_of_frame_queue.reset_curr_index();            
1,000✔
201
                    while ( (curr_job =  curr_thread->end_of_frame_queue.get_next_job()) != NULL ) {
1,000✔
202
                        ret = curr_job->call();
×
203
                        if ( ret != 0 ) {
×
204
                            exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "end_of_frame job did not return 0");
×
205
                        }
206
                    }
207
                }
208
            }
209

210
            next_frame_check_tics += software_frame_tics ;
1,400✔
211
        }
212

213
    }
1,400✔
214

215
    return(0) ;
216
}
217

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc