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

nasa / trick / 19078041271

04 Nov 2025 05:53PM UTC coverage: 55.802% (-0.001%) from 55.803%
19078041271

push

github

web-flow
Ignore .cache dir used by clangd (#1994)

12403 of 22227 relevant lines covered (55.8%)

261346.93 hits per line

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

71.32
/trick_source/sim_services/ThreadBase/ThreadBase.cpp
1
#include <iostream>
2
#include <stdio.h>
3
#include <signal.h>
4
#include <cstring>
5

6
#if __linux__
7
#include <sys/syscall.h>
8
#include <sys/types.h>
9
#include <sched.h>
10
#endif
11

12
#include "trick/ThreadBase.hh"
13
#include "trick/message_proto.h"
14
#include "trick/message_type.h"
15

16
Trick::ThreadBase::ThreadBase(std::string in_name) :
1,002✔
17
 name(in_name) ,
18
 pthread_id(0) ,
19
 pid(0) ,
20
 rt_priority(0),
21
 created(false),
22
 should_shutdown(false),
23
 cancellable(true)
1,002✔
24
{
25
    pthread_mutex_init(&shutdown_mutex, NULL);
1,002✔
26
#if __linux__
27
    max_cpu = sysconf( _SC_NPROCESSORS_ONLN ) ;
1,002✔
28
#ifdef CPU_ALLOC
29
    cpus = CPU_ALLOC(max_cpu) ;
1,002✔
30
    CPU_ZERO_S(CPU_ALLOC_SIZE(max_cpu), cpus) ;
1,002✔
31
#else
32
    cpus = (cpu_set_t *)calloc(1, sizeof(cpu_set_t)) ;
33
#endif
34
#endif
35
#if __APPLE__
36
    max_cpu = 0 ;
37
#endif
38
}
1,002✔
39

40
Trick::ThreadBase::~ThreadBase() {
995✔
41
#if __linux__
42
#ifdef CPU_FREE
43
    CPU_FREE(cpus) ;
995✔
44
#endif
45
#endif
46
}
995✔
47

48
std::string Trick::ThreadBase::get_name() {
×
49
    return name ;
×
50
}
51

52
void Trick::ThreadBase::set_name(std::string in_name) {
×
53
    name = in_name ;
×
54
}
×
55

56
pthread_t Trick::ThreadBase::get_pthread_id() {
6,996✔
57
    return pthread_id ;
6,996✔
58
}
59

60
pid_t Trick::ThreadBase::get_pid() {
×
61
    return pid ;
×
62
}
63

64
void Trick::ThreadBase::set_pid() {
658✔
65
#if __linux__
66
    pid = syscall( __NR_gettid ) ;
658✔
67
#else
68
    pid = getpid() ;
69
#endif
70
}
658✔
71

72
int Trick::ThreadBase::cpu_set(unsigned int cpu __attribute__((unused))) {
2✔
73
    int ret =  0 ;
2✔
74
#if __linux__
75
    if ( cpu < max_cpu ) {
2✔
76
#ifdef CPU_SET_S
77
        CPU_SET_S(cpu, CPU_ALLOC_SIZE(max_cpu), cpus) ;
2✔
78
#else
79
        CPU_SET(cpu, cpus) ;
80
#endif
81
    } else {
82
        message_publish(MSG_WARNING, "CPU value %d is out of range (0 through %d)", cpu, max_cpu - 1) ;
×
83
        ret = -1 ;
×
84
    }
85
#endif
86
#if __APPLE__
87
    message_publish(MSG_WARNING, "Warning: Trick on Darwin does not yet support processor assignment.\n");
88
#endif
89
    return ret ;
2✔
90
}
91

92
int Trick::ThreadBase::cpu_clr(unsigned int cpu __attribute__((unused))) {
×
93
    int ret =  0 ;
×
94
#if __linux__
95
    if ( cpu < max_cpu ) {
×
96
#ifdef CPU_CLR_S
97
        CPU_CLR_S(cpu, CPU_ALLOC_SIZE(max_cpu), cpus) ;
×
98
#else
99
        CPU_CLR(cpu, cpus) ;
100
#endif
101
    } else {
102
        message_publish(MSG_WARNING, "CPU value %d is out of range (0 through %d)", cpu, max_cpu - 1) ;
×
103
        ret = -1 ;
×
104
    }
105
#endif
106
#if __APPLE__
107
    message_publish(MSG_WARNING, "Warning: Trick on Darwin does not yet support processor assignment.\n");
108
#endif
109
    return ret ;
×
110
}
111

112
#if __linux__
113
cpu_set_t * Trick::ThreadBase::get_cpus() {
2✔
114
    return cpus ;
2✔
115
}
116

117
void Trick::ThreadBase::copy_cpus(cpu_set_t * in_cpus) {
2✔
118
#ifdef CPU_OR_S
119
    CPU_ZERO_S(CPU_ALLOC_SIZE(max_cpu), cpus) ;
2✔
120
    CPU_OR_S(CPU_ALLOC_SIZE(max_cpu), cpus, cpus, in_cpus) ;
4✔
121
#else
122
    *cpus = *in_cpus ;
123
#endif
124
}
2✔
125
#endif
126
#if __APPLE__
127
void * Trick::ThreadBase::get_cpus() {
128
    return NULL ;
129
}
130

131
void Trick::ThreadBase::copy_cpus(void * in_cpus __attribute__((unused))) {
132
}
133
#endif
134

135
int Trick::ThreadBase::execute_cpu_affinity() {
658✔
136
#if __linux__
137
#ifdef CPU_ALLOC_SIZE
138
    sched_setaffinity(pid, CPU_ALLOC_SIZE(max_cpu), cpus) ;
658✔
139
#else
140
    sched_setaffinity(pid, sizeof(cpu_set_t), cpus) ;
141
#endif
142
#endif
143
    return(0) ;
658✔
144
}
145

146
int Trick::ThreadBase::set_priority(unsigned int req_priority) {
2✔
147
    rt_priority = req_priority ;
2✔
148
    return 0 ;
2✔
149
}
150

151
#if __linux__
152

153
#include <sched.h>
154
#include <errno.h>
155

156
int Trick::ThreadBase::execute_priority() {
658✔
157

158
    int max_priority;
159
    int min_priority;
160
    int proc_priority;
161
    struct sched_param sparams;
162
    int sched_policy = SCHED_FIFO;
658✔
163

164
    if ( rt_priority > 0 ) {
658✔
165
        if (sched_getparam((pid_t) 0, &sparams)) {
×
166
            message_publish(MSG_ERROR, "Failed to get process scheduling parameters: %s\n", std::strerror(errno));
×
167
        } else {
168

169
            /* Get maximum and minimum RT priority */
170
            max_priority = sched_get_priority_max(SCHED_FIFO);
×
171
            min_priority = sched_get_priority_min(SCHED_FIFO);
×
172

173
            /* Since Trick's max priority starts at 1 and moves to lower priorties as the number goes up and Linux's
174
               priorities goes up as the number goes up and maxes out at "max_priority", we need to offset as follows:
175
             */
176
            proc_priority = max_priority - (rt_priority - 1);
×
177

178
            /* Make sure priority is in bounds. */
179
            if (proc_priority < min_priority) {
×
180

181
                message_publish(MSG_WARNING, "Warning: Linux process %d priority at %d is too low.  Minimum Trick \npriority is %d.\n",
×
182
                         pid, rt_priority, (max_priority - min_priority) + 2);
×
183

184
                proc_priority = min_priority;
×
185
            }
186

187
            if (pthread_getschedparam(pthread_self(), &sched_policy, &sparams)) {
×
188

189
                message_publish(MSG_ERROR, "Failed to get process scheduling parameters: %s\n", std::strerror(errno));
×
190
            }
191

192
            /* Set the process priority. */
193
            sparams.sched_priority = proc_priority;
×
194
            if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sparams)) {
×
195
                message_publish(MSG_ERROR, "Failed to set thread priority: %s\n", std::strerror(errno));
×
196
            }
197
        }
198
    }
199

200
    return(0) ;
658✔
201

202
}
203
#endif
204

205
#if __APPLE__
206

207
#include <sched.h>
208
#include <errno.h>
209

210
int Trick::ThreadBase::execute_priority() {
211

212
    int ret;
213

214
    /* Declare scheduling paramters. */
215
    int max_priority;
216
    int min_priority;
217
    int prev_priority;
218
    int proc_priority;
219
    int sched_policy = SCHED_FIFO;
220
    struct sched_param param;
221

222
    if ( rt_priority > 0 ) {
223
        /* Get maximum and minimum RT priority, and current parameters. */
224
        max_priority = sched_get_priority_max(sched_policy);
225
        min_priority = sched_get_priority_min(sched_policy);
226
        pthread_getschedparam(pthread_self(), &sched_policy, &param);
227
        prev_priority = param.sched_priority;
228

229
        /* Trick's max priority starts at 1 and moves to lower priorities as the number goes up.  Darwin's thread
230
           priorities range between 15 to 47 (observed). The default priority is 31 (observed); higher priorities
231
           cause more favorable scheduling. */
232
        proc_priority = max_priority - (rt_priority - 1);
233

234
        /* Make sure priority is in bounds. */
235
        if (proc_priority < min_priority) {
236

237
            message_publish(MSG_WARNING, "Warning: Trick CPU priority at %d is too low.\n", rt_priority);
238
            message_publish(MSG_WARNING, "This corresponds to a Darwin thread priority of %d.\n", proc_priority);
239
            message_publish(MSG_WARNING, "The Darwin thread priority range is %d:%d (min:max).\n", min_priority, max_priority);
240
            message_publish(MSG_WARNING, "The corresponding minimum Trick priority is %d.\n", (max_priority - min_priority) + 1);
241
            message_publish(MSG_WARNING, "Setting Trick priority to minimum!\n");
242
            proc_priority = min_priority;
243

244
        } else if (proc_priority > max_priority) {
245

246
            message_publish(MSG_WARNING, "Warning: Trick CPU priority at %d is too high.\n", rt_priority);
247
            message_publish(MSG_WARNING, "This corresponds to a Darwin thread priority of %d.\n", proc_priority);
248
            message_publish(MSG_WARNING, "The Darwin thread priority range is %d:%d (min:max).\n", min_priority, max_priority);
249
            message_publish(MSG_WARNING, "The maximum Trick priority is 1. Setting to maximum!\n");
250
            proc_priority = max_priority;
251
        }
252

253
        /* Set the process priority. */
254
        param.sched_priority = proc_priority;
255

256
        ret = pthread_setschedparam(pthread_self(), sched_policy, &param);
257
        if (ret != 0) {
258

259
            message_publish(MSG_ERROR, "Failed to set Darwin thread priority to %d: %s\n", param.sched_priority, std::strerror(errno));
260
            message_publish(MSG_ERROR, "This should correspond to a Trick CPU priority of %d.\n", (max_priority - proc_priority) + 1);
261
            message_publish(MSG_ERROR, "The current Darwin thread priority is %d.\n", prev_priority);
262
            message_publish(MSG_ERROR, "The Darwin thread priority range is %d:%d (min:max).\n", min_priority, max_priority);
263

264
        } else {
265

266
            message_publish(MSG_INFO, "Info: Trick CPU priority set to %d.\n", (max_priority - proc_priority) + 1);
267
            message_publish(MSG_INFO, "This corresponds to a Darwin thread priority of %d.\n", param.sched_priority);
268
            message_publish(MSG_INFO, "The previous Darwin thread priority was %d.\n", prev_priority);
269
            message_publish(MSG_INFO, "The Darwin thread priority range is %d:%d (min:max).\n", min_priority, max_priority);
270
        }
271
    }
272

273
    return(0) ;
274

275
}
276

277
#endif
278

279
int Trick::ThreadBase::create_thread() {
500✔
280

281
    if (created) {
500✔
282
        message_publish(MSG_ERROR, "create_thread called on thread %s (%p) which has already been started.\n", name.c_str(), this);
×
283
        return 0;
×
284
    }
285

286
    pthread_attr_t attr;
287

288
    pthread_attr_init(&attr);
500✔
289
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
500✔
290
    pthread_create(&pthread_id, &attr, Trick::ThreadBase::thread_helper , (void *)this);
500✔
291
    created = true;
500✔
292

293
#if __linux__
294
#ifdef __GNUC__
295
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2
296
    if ( ! name.empty() ) {
500✔
297
       std::string short_str = name.substr(0,15) ;
1,000✔
298
       pthread_setname_np(pthread_id, short_str.c_str()) ;
500✔
299
    }
300
#endif
301
#endif
302
#endif
303
    return(0) ;
500✔
304
}
305

306
int Trick::ThreadBase::cancel_thread() {
1,035✔
307
    pthread_mutex_lock(&shutdown_mutex);
1,035✔
308
    should_shutdown = true;
1,035✔
309
    pthread_mutex_unlock(&shutdown_mutex);
1,035✔
310

311
    if ( pthread_id != 0 ) {
1,035✔
312
        if (cancellable)
788✔
313
            pthread_cancel(pthread_id) ;
452✔
314
    }
315
    return(0) ;
1,035✔
316
}
317

318
int Trick::ThreadBase::join_thread() {
740✔
319
    if ( pthread_id != 0 ) {
740✔
320
        if ((errno = pthread_join(pthread_id, NULL)) != 0) {
493✔
321
            std::string msg = "Thread " + name + " had an error in join";
×
322
            perror(msg.c_str());
×
323
        } else {
324
            pthread_id = 0;
493✔
325
        }
326
    }
327
    return(0) ;
740✔
328
}
329

330
void Trick::ThreadBase::test_shutdown() {
3,847,070✔
331
    test_shutdown (NULL, NULL);
3,847,070✔
332
}
3,846,885✔
333

334
void Trick::ThreadBase::test_shutdown(void (*exit_handler) (void *), void * exit_arg) {
3,847,095✔
335
    pthread_mutex_lock(&shutdown_mutex);
3,847,095✔
336
    if (should_shutdown) {
3,847,095✔
337
        pthread_mutex_unlock(&shutdown_mutex);
186✔
338

339
        thread_shutdown(exit_handler, exit_arg);
186✔
340
    }
341
    pthread_mutex_unlock(&shutdown_mutex);
3,846,909✔
342
}
3,846,909✔
343

344

345
void Trick::ThreadBase::thread_shutdown() {
2✔
346
    thread_shutdown (NULL, NULL);
2✔
347
}
×
348

349
void Trick::ThreadBase::thread_shutdown(void (*exit_handler) (void *), void * exit_arg) {
193✔
350
    if (exit_handler != NULL) {
193✔
351
        exit_handler(exit_arg);
6✔
352
    }
353

354
    pthread_exit(0); 
193✔
355
}
356

357
void * Trick::ThreadBase::thread_helper( void * context ) {
500✔
358

359
    sigset_t sigs;
360
    Trick::ThreadBase * tb = (Trick::ThreadBase *)context ;
500✔
361

362
    /* block out all signals on this thread */
363
    sigfillset(&sigs);
500✔
364
    pthread_sigmask(SIG_BLOCK, &sigs, NULL);
500✔
365

366
    /* Set the cancel type to deffered, the thread will be cancelled at next cancellation point */
367
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
500✔
368

369
    tb->set_pid() ;
500✔
370

371
    /* Set thread priority and CPU affinity */
372
    tb->execute_priority() ;
500✔
373
    tb->execute_cpu_affinity() ;
500✔
374

375
    return tb->thread_body() ;
500✔
376
}
377

378
void Trick::ThreadBase::dump( std::ostream & oss ) {
155✔
379
    oss << "    from Trick::ThreadBase\n";
155✔
380
    oss << "    pthread_id = " << pthread_id << "\n";
155✔
381
    oss << "    process_id = " << pid << "\n";
155✔
382
    oss << "    rt_priority = " << rt_priority << "\n";
155✔
383
#if __linux__
384
    oss << "    cpus = " ;
155✔
385
    bool first_print = true ;
155✔
386
    for ( unsigned int ii = 0 ; ii < max_cpu ; ii++ ) {
775✔
387
#ifdef CPU_ISSET_S
388
        if ( CPU_ISSET_S(ii, CPU_ALLOC_SIZE(max_cpu), cpus) ) {
620✔
389
#else
390
        if ( CPU_ISSET(ii, cpus) ) {
391
#endif
392
            if ( first_print == true ) {
×
393
                first_print = false ;
×
394
            } else {
395
                oss << "," ;
×
396
            }
397
            oss << ii ;
×
398
        }
399
    }
400
    if ( first_print ) {
155✔
401
        oss << "none assigned" ;
155✔
402
    }
403
    oss << std::endl ;
155✔
404
#endif
405
}
155✔
406

407

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