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

nasa / trick / 28390523089

29 Jun 2026 05:26PM UTC coverage: 56.151% (-0.002%) from 56.153%
28390523089

Pull #2155

github

web-flow
Merge 7f260ea8f into b2ea6f12e
Pull Request #2155: Let user aware when itimer is disabled because the frame time is less than 10ms.

0 of 1 new or added line in 1 file covered. (0.0%)

15 existing lines in 1 file now uncovered.

14693 of 26167 relevant lines covered (56.15%)

461701.51 hits per line

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

42.42
/trick_source/sim_services/Timer/ITimer.cpp
1
/*
2
PURPOSE:
3
    ( gettimeofday clock )
4
PROGRAMMERS:
5
    (((Robert W. Bailey) (LinCom) (April 1992) (--) (Realtime.))
6
     ((Robert W. Bailey) (LinCom) (7/22/92) (--) (--))
7
     ((Eddie J. Paddock) (MDSSC) (Oct 1992) (--) (Realtime.)))
8
     ((Alex Lin) (NASA) (April 2009) (--) (c++ port)))
9
*/
10

11
#include <iostream>
12
#include <sstream>
13

14
#include <fcntl.h>
15
#include <stdio.h>
16
#include <string.h>
17
#include <errno.h>
18
#include <math.h>
19
#include <signal.h>
20
#include <sys/types.h>
21
#include <unistd.h>
22

23
#include "trick/ITimer.hh"
24
#include "trick/exec_proto.h"
25
#include "trick/message_proto.h"
26

27
Trick::ITimer * the_itimer ;
28

29
Trick::ITimer::ITimer() : Timer() {
187✔
30

31
    the_itimer = this ;
187✔
32

33
#if ! ( __APPLE__ | __INTERIX )
34
    clock_getres(CLOCK_REALTIME, &res);
187✔
35
#else
36
    res.tv_nsec = 10000000;
37
    res.tv_sec = 0;
38
#endif
39

40
    return ;
187✔
41
}
42

43
Trick::ITimer::~ITimer() {
187✔
44
    return ;
187✔
45
}
187✔
46

47
void Trick::ITimer::semaphore_post() {
×
48
    sem_post(semaphore) ;
×
49
}
×
50

51
/**
52
@details
53
-# Set the SIGALRM signal handler to the ITimer signal handler routine.
54
-# Open a unique named semaphore
55
*/
56
int Trick::ITimer::init() {
2✔
57

58
    static struct sigaction sigact;
59
    std::stringstream sem_name_stream ;
2✔
60

61
    sigact.sa_handler = (void (*)(int)) it_handler;
2✔
62
    if (sigaction(SIGALRM, &sigact, NULL) < 0) {
2✔
63
        perror("sigaction() failed for SIGALRM");
×
64
    }
65

66
    // Initialize the itimer semaphore used by SIGALRM handler to
67
    // wake up the sim_exec_loop from its underrun sleepy time.
68

69
    sem_name_stream << "itimersepmaphore_" << getpid() ;
2✔
70
    sem_name = sem_name_stream.str() ;
2✔
71

72
    semaphore = sem_open(sem_name.c_str(), O_CREAT, S_IRWXU , 0);
2✔
73

74
    return (0) ;
2✔
75
}
2✔
76

77
/**
78
@details
79
-# If the timer is enabled
80
   -# If the frame time is valid
81
      -# Set the system itimer to expire one time at the desired frame period.
82
   -# Else termiate the simulation with the error message stating that the
83
      itimer frame period is invalid.
84
*/
85
int Trick::ITimer::start(double in_frame_time) {
51✔
86

87
    struct itimerval ivalue;
88
    int ret ;
89
    unsigned long long frame_sec ;
90
    unsigned int frame_usec ;
91

92
    if ( enabled ) {
51✔
93

94
        // clear out any built up signals.
95
        while ( (ret = sem_trywait(semaphore)) == 0 ) ;
×
96

97
        frame_sec = ( unsigned long long )in_frame_time ;
×
98
        frame_usec = (unsigned int)((in_frame_time - frame_sec) * 1000000) ;
×
99

100
        // check minimum time > 10ms
101
        if ( frame_sec == 0 && frame_usec < 10000 ) {
×
NEW
102
            message_publish(MSG_WARNING,
×
103
                            "ITimer: frame time (%g s or %g ms) is less than 10ms minimum; "
104
                            "itimer disabled, falling back to clock_spin.\n",
105
                            in_frame_time, in_frame_time * 1000);
106
            active = false ;
×
107
            return(0) ;
×
108
        }
109
        // Arm the itimer slightly early so clock_spin() can busy-wait to the
110
        // frame boundary.  On macOS, timer coalescing can delay SIGALRM delivery
111
        // by 3-15ms, so scale the value to 5% of the frame (with a range of 2-8ms).
112
        // On Linux a fixed 2ms is sufficient.
113
#if __APPLE__
114
        {
115
            // Frames < 10ms are already rejected above, so frame_usec >= 10000 thus >= 8000
116
            // When frame_sec == 0, meaning the borrow path only triggers for frames >= 1s.
117
            unsigned int scaled_usec = (unsigned int)(in_frame_time * 1000000) / 20; // 5% of frame
118
            if (scaled_usec < 2000)
119
                scaled_usec = 2000;
120
            if (scaled_usec > 8000)
121
                scaled_usec = 8000;
122
            if (frame_usec < scaled_usec)
123
            {
124
                frame_sec  -= 1;
125
                frame_usec += 1000000;
126
            }
127
            frame_usec -= scaled_usec;
128
        }
129
#else
UNCOV
130
        if (frame_usec < 2000 && frame_sec > 0)
×
131
        {
UNCOV
132
            frame_sec  -= 1 ;
×
133
            frame_usec += 1000000 ;
×
134
        }
135
        frame_usec -= 2000 ;
×
136
#endif
137

138
        if ( in_frame_time > 0 ) {
×
139
            /* Set timer interval in micro-seconds */
UNCOV
140
            ivalue.it_interval.tv_sec = 0;
×
141
            ivalue.it_interval.tv_usec = 0;
×
UNCOV
142
            ivalue.it_value.tv_sec = frame_sec;
×
143
            ivalue.it_value.tv_usec = (long) frame_usec;
×
144

145
            setitimer(ITIMER_REAL, &ivalue, NULL);
×
146
            active = true ;
×
147
        } else {
148
            char error_message[256];
149
            snprintf(error_message, sizeof(error_message), "itimer frame_time is not set\n" ) ;
×
UNCOV
150
            exec_terminate_with_return(-1, __FILE__, __LINE__ , error_message);
×
151
        }
152
    }
153
    return (0) ;
51✔
154

155
}
156

157
/*
158
@details
159
-# Call the start function
160
*/
161
int Trick::ITimer::reset(double in_frame_time) {
50✔
162
    start(in_frame_time) ;
50✔
163
    return (0) ;
50✔
164
}
165

166
/**
167
@details
168
-# Set the system itimer with the expiriation time of 0.
169
*/
UNCOV
170
int Trick::ITimer::stop() {
×
171

172
    static struct itimerval ivalue, ovalue;
173

174
    /* Turn off itimer */
UNCOV
175
    ivalue.it_interval.tv_usec = 0;
×
UNCOV
176
    ivalue.it_interval.tv_sec = 0;
×
177

178
    ivalue.it_value.tv_usec = 0;
×
179
    ivalue.it_value.tv_sec = 0;
×
180

181
    (void) setitimer(ITIMER_REAL, &ivalue, &ovalue);
×
182

UNCOV
183
    active = false ;
×
184

UNCOV
185
    return (0) ;
×
186

187
}
188

189
/**
190
@details
191
-# If the timer is enabled
192
   -# Call sem_wait to decrement the semaphore.  sem_wait will sleep and wait
193
      for the semaphore to be posted from the signal handler.
194
   -# If sem_wait returns an error, write an error message
195
*/
196
int Trick::ITimer::pause() {
50✔
197

198
    int sem_ret;
199

200
    if ( enabled and active ) {
50✔
201

202
        do {
UNCOV
203
            sem_ret = sem_wait(semaphore);
×
204
            //TODO: I'd like to use sem_timedwait
205
            //sem_ret = sem_timedwait(semaphore, &timeout);
206
        } while ((sem_ret < 0 && errno == EINTR) && (errno != EDEADLK));
×
207

UNCOV
208
        if (sem_ret != 0) {
×
209
            // Prepend info to the error message string (given by errno)
UNCOV
210
            perror( "ITimer call to sem_wait()" );
×
211
        }
212

213
    }
214

215
    return (0) ;
50✔
216

217
}
218

219
/**
220
@details
221
-# Unlink the semaphore
222
*/
223
int Trick::ITimer::shutdown() {
1✔
224
    sem_unlink(sem_name.c_str()) ;
1✔
225
    return(0) ;
1✔
226
}
227

UNCOV
228
Trick::ITimer * get_itimer() {
×
UNCOV
229
    return (the_itimer) ;
×
230
}
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

© 2026 Coveralls, Inc