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

nasa / trick / 26543350755

27 May 2026 10:49PM UTC coverage: 57.317% (+0.4%) from 56.928%
26543350755

Pull #2107

github

web-flow
Merge ef7df26a3 into 1196611f3
Pull Request #2107: Checkpoint in freeze only

42 of 51 new or added lines in 5 files covered. (82.35%)

26 existing lines in 8 files now uncovered.

13089 of 22836 relevant lines covered (57.32%)

297749.43 hits per line

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

70.66
/trick_source/sim_services/CheckPointRestart/CheckPointRestart.cpp
1

2
#include <iostream>
3
#include <iomanip>
4
#include <sstream>
5
#include <stdlib.h>
6
#include <sys/types.h>
7
#include <unistd.h>
8
#include <sys/syscall.h>
9
#include <sys/stat.h>
10
#include <string.h>
11

12
#include "trick/CheckPointRestart.hh"
13
#include "trick/MemoryManager.hh"
14
#include "trick/SimObject.hh"
15
#include "trick/Executive.hh"
16
#include "trick/exec_proto.hh"
17
#include "trick/exec_proto.h"
18
#include "trick/command_line_protos.h"
19
#include "trick/message_proto.h"
20
#include "trick/message_type.h"
21
#include "trick/TrickConstant.hh"
22
#include "trick/sim_mode.h"
23

24
Trick::CheckPointRestart * the_cpr ;
25

26
Trick::CheckPointRestart::CheckPointRestart() {
187✔
27

28
    int num_classes = 0 ;
187✔
29

30
    pre_init_checkpoint = false ;
187✔
31
    post_init_checkpoint = false ;
187✔
32
    end_checkpoint = false ;
187✔
33
    safestore_enabled = false ;
187✔
34
    cpu_num = -1 ;
187✔
35
    safestore_time = TRICK_MAX_LONG_LONG ;
187✔
36
    load_checkpoint_file_name.clear() ;
187✔
37

38
    write_checkpoint_job = NULL ;
187✔
39
    safestore_checkpoint_job = NULL ;
187✔
40

41
    class_map["checkpoint"] = num_classes ;
187✔
42
    class_to_queue[num_classes++] = &checkpoint_queue ;
187✔
43

44
    class_map["post_checkpoint"] = num_classes ;
187✔
45
    class_to_queue[num_classes++] = &post_checkpoint_queue ;
187✔
46

47
    class_map["preload_checkpoint"] = num_classes ;
187✔
48
    class_to_queue[num_classes++] = &preload_checkpoint_queue ;
187✔
49

50
    class_map["restart"] = num_classes ;
187✔
51
    class_to_queue[num_classes++] = &restart_queue ;
187✔
52

53
    the_cpr = this ;
187✔
54

55
    redirect_data_recording = false;
187✔
56
    redirected_data_recording_directory = "";
187✔
57
}
187✔
58

59
int Trick::CheckPointRestart::set_pre_init_checkpoint(bool yes_no) {
1✔
60
    pre_init_checkpoint = yes_no ;
1✔
61
    return(0) ;
1✔
62
}
63

64
int Trick::CheckPointRestart::set_post_init_checkpoint(bool yes_no) {
1✔
65
    post_init_checkpoint = yes_no ;
1✔
66
    return(0) ;
1✔
67
}
68

69
int Trick::CheckPointRestart::set_end_checkpoint(bool yes_no) {
2✔
70
    end_checkpoint = yes_no ;
2✔
71
    return(0) ;
2✔
72
}
73

74
int Trick::CheckPointRestart::set_safestore_enabled(bool yes_no) {
×
75
    safestore_enabled = yes_no ;
×
76
    return(0) ;
×
77
}
78

79
int Trick::CheckPointRestart::set_cpu_num(int in_cpu_num) {
×
80
    if ( in_cpu_num <= 0 ) {
×
81
        cpu_num = -1 ;
×
82
    } else {
83
        cpu_num = in_cpu_num ;
×
84
    }
85
    return(0) ;
×
86
}
87

88

89
const char * Trick::CheckPointRestart::get_output_file() {
×
90
    return output_file.c_str() ;
×
91
}
92

93
const char * Trick::CheckPointRestart::get_load_file() {
×
94
    return load_checkpoint_file_name.c_str() ;
×
95
}
96

97
int Trick::CheckPointRestart::find_write_checkpoint_jobs(std::string sim_object_name) {
187✔
98

99
    write_checkpoint_job = exec_get_job(std::string(sim_object_name + ".write_checkpoint").c_str()) ;
187✔
100
    if ( write_checkpoint_job == NULL ) {
187✔
101
        exec_terminate_with_return(-1 , __FILE__ , __LINE__ , "CheckPointRestart could not find write_checkpoint job" ) ;
×
102
    } else {
103
        write_checkpoint_job->next_tics = TRICK_MAX_LONG_LONG ;
187✔
104
    }
105

106
    safestore_checkpoint_job = exec_get_job(std::string(sim_object_name + ".safestore_checkpoint").c_str()) ;
187✔
107
    if ( safestore_checkpoint_job == NULL ) {
187✔
108
        exec_terminate_with_return(-1 , __FILE__ , __LINE__ , "CheckPointRestart could not find safestore_checkpoint job" ) ;
×
109
    } else {
110
        safestore_checkpoint_job->next_tics = TRICK_MAX_LONG_LONG ;
187✔
111
    }
112

113
    return(0) ;
187✔
114
}
115

116
/**
117
 * @brief Schedule a checkpoint to be written at a given time.
118
 * @param in_time The time the checkpoint should be dumped
119
 * @see write_checkpoint() 
120
 */
121
int Trick::CheckPointRestart::checkpoint(double in_time, std::string file_name) {
12✔
122

123
    long long curr_time = exec_get_time_tics() ;
12✔
124
    long long new_time ;
125

126
    new_time = (long long)(in_time * exec_get_time_tic_value()) ;
12✔
127

128
    if (new_time >= curr_time ) {
12✔
129
        checkpoint_times.push(new_time) ;
12✔
130
        if ( new_time < write_checkpoint_job->next_tics ) {
12✔
131
            write_checkpoint_job->next_tics = new_time ;
12✔
132
        }
133

134
        if ( chkpnt_resume_sim_map.find(new_time) == chkpnt_resume_sim_map.end() ) {
12✔
135
            chkpnt_resume_sim_map[new_time] = true ;
12✔
136
        }
137
        
138
        if (!file_name.empty()) chkpnt_names[new_time] = file_name;
12✔
139
        
140
        the_exec->freeze(in_time, false);
12✔
141
        //std::cout << "\033[33mSET CHECKPOINT TIME " << in_time << " " << new_time << "\033[0m" << std::endl ;
142
    } else {
143
        message_publish(MSG_ERROR, "Checkpoint time specified in the past. specified %f, current_time %f\n",
×
144
         in_time , exec_get_sim_time()) ;
145
    }
146

147
    return(0) ;
12✔
148
}
149

NEW
150
void Trick::CheckPointRestart::note_scheduled_freeze(long long in_time_tics) {
×
151
    // If a freeze is scheduled at the same time as a checkpoint, the checkpoint will be taken and sim will not resume afterwards.
152
    // Otherwise, sim will resume after the checkpoint as the scheduled checkpoint auto freezes sim before taking the checkpoint.
NEW
153
    chkpnt_resume_sim_map[in_time_tics] = false ;
×
NEW
154
}
×
155

UNCOV
156
int Trick::CheckPointRestart::set_safestore_time(double in_time) {
×
157

158
    long long software_frame_tics ;
159

160
    safestore_period = (long long)(in_time * exec_get_time_tic_value()) ;
×
161
    software_frame_tics = exec_get_software_frame_tics() ;
×
162

163
    if ( safestore_period % software_frame_tics ) {
×
164
        safestore_period = ((safestore_time / software_frame_tics) + 1 ) * software_frame_tics ;
×
165
    }
166
    safestore_time = safestore_period ;
×
167

168
    if ( safestore_checkpoint_job != NULL ) {
×
169
        safestore_checkpoint_job->next_tics = safestore_time ;
×
170
    }
171

172
    return(0) ;
×
173
}
174

175
int Trick::CheckPointRestart::checkpoint(std::string file_name, bool print_status, std::string obj_list_str ) {
17✔
176

177
    // first, empty the sim obj list to make sure there is nothing left from last time
178
    obj_list.clear();
17✔
179

180
    if (obj_list_str.compare("")) {
17✔
181
        const char * tok = strtok((char*)obj_list_str.c_str(), ",");
×
182
        while (tok != NULL) {
×
183
            obj_list.push_back(tok);
×
184
            tok = strtok(NULL, ",");
×
185
        }
186
    }
187

188
    do_checkpoint(file_name, print_status) ;
17✔
189

190
    return(0) ;
17✔
191
}
192

193
int Trick::CheckPointRestart::do_checkpoint(std::string file_name, bool print_status) {
17✔
194

195
    JobData * curr_job ;
196
    pid_t pid;
197
    SIM_MODE mode;
198

199
    mode = the_exec->get_mode();
17✔
200

201
    if (mode != Freeze) {
17✔
202
        std::string msg_format  = "WARNING: Saving a checkpoint not in 'Freeze' mode may cause non time-homogeneous data. ";
5✔
203
                    msg_format += "Current Mode: %s (%d)\n";
5✔
204
        message_publish(MSG_WARNING, msg_format.c_str(),
5✔
205
                        simModeCharString(mode), mode);
206

207
        return 0;
5✔
208
    }
209
    
210

211
    if ( ! file_name.compare("") ) {
12✔
212
        std::stringstream file_name_stream ;
×
213
        file_name_stream << "chkpnt_" << std::fixed << std::setprecision(6) << exec_get_sim_time() ;
×
214
        file_name = file_name_stream.str() ;
×
215
    }
216
    output_file = std::string(command_line_args_get_output_dir()) + "/" + file_name ;
12✔
217

218
    checkpoint_queue.reset_curr_index() ;
12✔
219
    while ( (curr_job = checkpoint_queue.get_next_job()) != NULL ) {
45✔
220
        curr_job->parent_object->call_function(curr_job) ;
33✔
221
    }
222

223
    if ( cpu_num != -1 ) {
12✔
224
    // if the user specified a cpu number for the checkpoint, fork a process to write the checkpoint
225
        if ((pid = fork()) == 0) {
×
226
#if __linux__
227
            if ( cpu_num >= 0 ) {
×
228
                unsigned long mask;
229
                mask = 1 << cpu_num ;
×
230
                syscall((long) __NR_sched_setaffinity, 0, sizeof(mask), &mask);
×
231
            }
232
#endif
233
#if __APPLE__
234
            if ( cpu_num >= 0 ) {
235
            }
236
#endif
237
            if (obj_list.empty()) {
×
238
                trick_MM->write_checkpoint(output_file.c_str()) ;
×
239
            } else {
240
                trick_MM->write_checkpoint(output_file.c_str(), obj_list);
×
241
            }
242
            _Exit(0) ;
×
243
        }
244
    }
245
    else {
246
    // no fork
247
        if (obj_list.empty()) {
12✔
248
            trick_MM->write_checkpoint(output_file.c_str()) ;
12✔
249
        } else {
250
            trick_MM->write_checkpoint(output_file.c_str(), obj_list);
×
251
        }
252
    }
253

254
    post_checkpoint_queue.reset_curr_index() ;
12✔
255
    while ( (curr_job = post_checkpoint_queue.get_next_job()) != NULL ) {
33✔
256
        curr_job->parent_object->call_function(curr_job) ;
21✔
257
    }
258

259
    if ( print_status )
12✔
260
    {
261
        if (trick_MM->is_hexfloat_checkpoint())
12✔
262
        {
263
            message_publish(MSG_INFO, "Dumped Checkpoint (floating point values in Hexadecimal) %s.\n", file_name.c_str()) ;
×
264
        }
265
        else
266
        {
267
            message_publish(MSG_INFO, "Dumped ASCII Checkpoint %s.\n", file_name.c_str()) ;
12✔
268
        }
269
    }
270

271
    return 0 ;
12✔
272
}
273

274
/** 
275
 * @brief Writes a scheduled checkpoint if it is the correct time. 
276
 * @see checkpoint(double in_time)
277
 */
278
int Trick::CheckPointRestart::write_checkpoint() {
12✔
279

280
    long long curr_time = exec_get_time_tics() ;
12✔
281
    bool should_resume_sim = true ;
12✔
282

283
    // checkpoint time is set in a read event that occurs at top of frame
284
    if ( curr_time == checkpoint_times.top() ) {
12✔
285

286
        // remove all times at the top of the queue that match the current time.
287
        while ( !checkpoint_times.empty() and (checkpoint_times.top() == curr_time) ) {
24✔
288
            checkpoint_times.pop() ;
12✔
289
        }
290

291
        if ( !checkpoint_times.empty() ) {
12✔
292
            write_checkpoint_job->next_tics = checkpoint_times.top() ;
×
293
        } else {
294
            write_checkpoint_job->next_tics = TRICK_MAX_LONG_LONG ;
12✔
295
        }
296

297
        if ( chkpnt_resume_sim_map.find(curr_time) != chkpnt_resume_sim_map.end() ) {
12✔
298
            should_resume_sim = chkpnt_resume_sim_map[curr_time] ;
12✔
299
            chkpnt_resume_sim_map.erase(curr_time) ;
12✔
300
        }
301

302
        double sim_time = exec_get_sim_time() ;
12✔
303
        std::string file_name = "";
24✔
304

305
        if (chkpnt_names.find(curr_time) == chkpnt_names.end()) {
12✔
306
            std::stringstream chk_name_stream ;
11✔
307
            chk_name_stream << "chkpnt_" << std::fixed << std::setprecision(6) << sim_time ;
11✔
308
            file_name = chk_name_stream.str();
11✔
309
        } else {
310
            file_name = chkpnt_names[curr_time];
1✔
311
            chkpnt_names.erase(curr_time);
1✔
312
        }
313

314
        checkpoint( file_name );
12✔
315

316
        if ( should_resume_sim ) {
12✔
317
            the_exec->run();
12✔
318
        }
319
    }
320

321
    return(0) ;
12✔
322
}
323

324
int Trick::CheckPointRestart::write_pre_init_checkpoint() {
155✔
325
    if ( pre_init_checkpoint ) {
155✔
326
        checkpoint(std::string("chkpnt_pre_init")) ;
×
327
    }
328
    return 0  ;
155✔
329
}
330

331
int Trick::CheckPointRestart::write_post_init_checkpoint() {
154✔
332
    if ( post_init_checkpoint ) {
154✔
333
        checkpoint(std::string("chkpnt_post_init")) ;
×
334
    }
335
    return 0  ;
154✔
336
}
337

338
int Trick::CheckPointRestart::write_end_checkpoint() {
155✔
339
    if ( end_checkpoint ) {
155✔
340
        checkpoint(std::string("chkpnt_end")) ;
1✔
341
    }
342
    return 0  ;
155✔
343
}
344

345
int Trick::CheckPointRestart::safestore_checkpoint() {
×
346

347
    if ( safestore_enabled) {
×
348
        checkpoint(std::string("chkpnt_safestore"), false) ;
×
349
        safestore_time += safestore_period ;
×
350
    }
351

352
    if ( safestore_checkpoint_job != NULL ) {
×
353
        safestore_checkpoint_job->next_tics = safestore_time ;
×
354
    }
355

356
    return(0) ;
×
357
}
358

359
void Trick::CheckPointRestart::load_checkpoint(std::string file_name) {
11✔
360
    SIM_MODE mode = the_exec->get_mode();
11✔
361

362
    if (mode == Run) {
11✔
363
        std::string msg_format  = "WARNING: Loading a checkpoint in 'Run Mode' may cause non time-homogeneous data. ";
10✔
364
                    msg_format += "Current Mode: %s (%d)\n";
10✔
365
        
366
        message_publish(MSG_WARNING, msg_format.c_str(),
10✔
367
                        file_name.c_str(), simModeCharString(mode), mode);
368
        // If in RUN mode, this will freeze the simulation and notify the code to unfreeze later.
369
        // To forbid loading a checkpoint in RUN mode, remove the following two lines and the second to last line in load_checkpoint_job()
370
        the_exec->freeze();
10✔
371
        auto_freeze = true;
10✔
372
    } 
373
        
374
    load_checkpoint_file_name = file_name ;
11✔
375
}
11✔
376

377
void Trick::CheckPointRestart::load_checkpoint(std::string file_name, bool stls_on) {
×
378
    trick_MM->set_restore_stls_default(stls_on);
×
379
    load_checkpoint(file_name);
×
380
}
×
381

382
void Trick::CheckPointRestart::load_checkpoint(std::string file_name, std::string new_data_record_dir)
1✔
383
{
384

385
    redirect_data_recording = true;
1✔
386
    redirected_data_recording_directory = new_data_record_dir;
1✔
387
    load_checkpoint(file_name);
1✔
388
}
1✔
389

390
void Trick::CheckPointRestart::load_checkpoint(std::string file_name, std::string new_data_record_dir, bool stls_on)
×
391
{
392

393
    redirect_data_recording = true;
×
394
    redirected_data_recording_directory = new_data_record_dir;
×
395
    trick_MM->set_restore_stls_default(stls_on);
×
396
    load_checkpoint(file_name);
×
397
}
×
398

399

400
int Trick::CheckPointRestart::load_checkpoint_job() {
106,328✔
401

402
    JobData * curr_job ;
403
    struct stat temp_buf ;
404

405
    if ( ! load_checkpoint_file_name.empty() && the_exec->get_mode() != Run) {
106,328✔
406

407
        if ( stat( load_checkpoint_file_name.c_str() , &temp_buf) == 0 ) {
11✔
408
            preload_checkpoint_queue.reset_curr_index() ;
11✔
409
            while ( (curr_job = preload_checkpoint_queue.get_next_job()) != NULL ) {
66✔
410
                curr_job->call() ;
55✔
411
            }
412

413
            // clear the queues!  They will be rebuilt when the executive calls its restart job.
414
            checkpoint_queue.clear() ;
11✔
415
            post_checkpoint_queue.clear() ;
11✔
416
            preload_checkpoint_queue.clear() ;
11✔
417
            restart_queue.clear() ;
11✔
418

419
            message_publish(MSG_INFO, "Load checkpoint file %s.\n", load_checkpoint_file_name.c_str()) ;
11✔
420
            trick_MM->init_from_checkpoint(load_checkpoint_file_name.c_str()) ;
11✔
421

422
            message_publish(MSG_INFO, "Finished loading checkpoint file.  Calling restart jobs.\n") ;
11✔
423
            if (redirect_data_recording)
11✔
424
            {
425
                redirect_data_recording = false;
1✔
426
                set_output_dir( redirected_data_recording_directory.c_str() );
1✔
427
            }
428

429

430
            // bootstrap the sim_objects back into the executive!
431
            // TODO: MAKE AN exec_restart() CALL THAT DOES NOT REQUIRE WE USE the_exec.
432
            the_exec->restart() ;
11✔
433

434
            // the restart queue will be rebuilt by the executive.
435
            restart_queue.reset_curr_index() ;
11✔
436
            while ( (curr_job = restart_queue.get_next_job()) != NULL ) {
152✔
437
                curr_job->call() ;
141✔
438
            }
439
        } else {
440
            message_publish(MSG_INFO, "Could not find checkpoint file %s.\n", load_checkpoint_file_name.c_str()) ;
×
441
        }
442
        load_checkpoint_file_name.clear() ;
11✔
443
        if(auto_freeze)  the_exec->run();
11✔
444
    }
445

446
    return(0) ;
106,328✔
447
}
448

449
int Trick::CheckPointRestart::write_s_job_execution(FILE *fp) {
154✔
450

451
    if ( fp == NULL ) {
154✔
452
        return(0) ;
×
453
    }
454

455
    fprintf(fp, "\n===================================================================================================\n") ;
154✔
456
    fprintf(fp, "CheckPointRestart :\n\n") ;
154✔
457
    checkpoint_queue.write_non_sched_queue(fp) ;
154✔
458
    post_checkpoint_queue.write_non_sched_queue(fp) ;
154✔
459
    preload_checkpoint_queue.write_non_sched_queue(fp) ;
154✔
460
    restart_queue.write_non_sched_queue(fp) ;
154✔
461
    return 0 ;
154✔
462
}
463

464
int Trick::CheckPointRestart::instrument_job_before( Trick::JobData * instrument_job ) {
1✔
465

466
    int count = 0 ;
1✔
467

468
    /** @par Detailed Design: */
469

470
    /** @li if target_job specified, instrument job will only be inserted before it
471
        note: when more than one target job with same name, this will insert instrument job for 1st occurrence of target_job in each queue
472
     */
473
    count += checkpoint_queue.instrument_before(instrument_job) ;
1✔
474
    count += preload_checkpoint_queue.instrument_before(instrument_job) ;
1✔
475
    count += restart_queue.instrument_before(instrument_job) ;
1✔
476

477
    /** @li Return how many insertions were done. */
478
    return(count) ;
1✔
479

480
}
481

482
int Trick::CheckPointRestart::instrument_job_after( Trick::JobData * instrument_job ) {
1✔
483

484
    int count = 0 ;
1✔
485

486
    /** @par Detailed Design */
487
    // if target_job specified, instrument job will only be inserted after it
488
    // note: when more than one target job with same name, this will insert instrument job for 1st occurrence of target_job in each queue
489

490
    count += checkpoint_queue.instrument_after(instrument_job) ;
1✔
491
    count += preload_checkpoint_queue.instrument_after(instrument_job) ;
1✔
492
    count += restart_queue.instrument_after(instrument_job) ;
1✔
493

494
    /** @li Return how many insertions were done. */
495
    return(count) ;
1✔
496

497
}
498

499
int Trick::CheckPointRestart::instrument_job_remove(std::string in_job) {
×
500

501
    checkpoint_queue.instrument_remove(in_job) ;
×
502
    preload_checkpoint_queue.instrument_remove(in_job) ;
×
503
    restart_queue.instrument_remove(in_job) ;
×
504

505
    return(0) ;
×
506
}
507

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

© 2026 Coveralls, Inc