source: flair-src/trunk/lib/FlairCore/src/Thread_impl.cpp@ 19

Last change on this file since 19 was 15, checked in by Bayard Gildas, 8 years ago

sources reformatted with flair-format-dir script

File size: 9.0 KB
RevLine 
[2]1// %flair:license{
[15]2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
[2]4// %flair:license}
5// created: 2012/10/04
6// filename: Thread_impl.cpp
7//
8// author: Guillaume Sanahuja
9// Copyright Heudiasyc UMR UTC/CNRS 7253
10//
11// version: $Id: $
12//
13// purpose: classe implementant un thread rt ou non
14//
15//
16/*********************************************************************/
17
18#include "Thread_impl.h"
19#include "Thread.h"
20#include "IODevice.h"
21#include "IODevice_impl.h"
22#include "ConditionVariable.h"
23#include "config.h"
24#include "FrameworkManager.h"
25#include <string.h>
26#ifdef __XENO__
27#include <rtdk.h>
28#else
29#include <sys/resource.h>
30#endif
31
32using std::string;
33using namespace flair::core;
34
[15]35Thread_impl::Thread_impl(Thread *self, uint8_t priority) {
36 isRunning = false;
37 tobestopped = false;
38 is_suspended = false;
39 period_set = false;
[2]40
[15]41 this->self = self;
42 cond = new ConditionVariable(self, self->ObjectName());
[2]43
[15]44 if (priority < MIN_THREAD_PRIORITY) {
45 priority = MIN_THREAD_PRIORITY;
46 // printf("Thread::Thread, %s: priority set to
47 // %i\n",self->ObjectName().c_str(), priority);
48 }
49 if (priority > MAX_THREAD_PRIORITY) {
50 priority = MAX_THREAD_PRIORITY;
51 self->Warn("priority set to %i\n", MAX_THREAD_PRIORITY);
52 }
[2]53
[15]54 this->priority = priority;
55 period = 100 * 1000 * 1000; // 100ms par defaut
56 min_jitter = 1000 * 1000 * 1000;
57 max_jitter = 0;
58 mean_jitter = 0;
59 last = 0;
60 cpt = 0;
[2]61}
62
[15]63Thread_impl::~Thread_impl() {
64 SafeStop();
65 Join();
[2]66}
67
[15]68void Thread_impl::Start(void) {
69 int status;
[2]70
[15]71 isRunning = true;
[2]72
73#ifdef __XENO__
[15]74 string th_name =
75 getFrameworkManager()->ObjectName() + "-" + self->ObjectName();
[2]76
77#ifdef RT_STACK_SIZE
[15]78 status = rt_task_create(&task_rt, th_name.c_str(), RT_STACK_SIZE,
79 (int)priority, T_JOINABLE);
[2]80#else
[15]81 status =
82 rt_task_create(&task_rt, th_name.c_str(), 0, (int)priority, T_JOINABLE);
83#endif // RT_STACK_SIZE
84 if (status != 0) {
85 self->Err("rt_task_create error (%s)\n", strerror(-status));
86 } else {
87 //_printf("rt_task_create ok %s\n",th_name);
88 }
[2]89
[15]90 status = rt_task_start(&task_rt, &main_rt, (void *)this);
91 if (status != 0) {
92 self->Err("rt_task_start error (%s)\n", strerror(-status));
93 } else {
94 //_printf("rt_task_start ok %s\n",th_name);
95 }
[2]96
[15]97 // Initialise the rt_print buffer for this task explicitly
98 rt_print_init(512, th_name.c_str());
[2]99
100#else //__XENO__
101
[15]102 // Initialize thread creation attributes
103 pthread_attr_t attr;
104 if (pthread_attr_init(&attr) != 0) {
105 self->Err("Error pthread_attr_init\n");
106 }
[2]107
108#ifdef NRT_STACK_SIZE
[15]109 if (pthread_attr_setstacksize(&attr, NRT_STACK_SIZE) != 0) {
110 self->Err("Error pthread_attr_setstacksize\n");
111 }
112#endif // NRT_STACK_SIZE
[2]113
[15]114 if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) {
115 self->Err("Error pthread_attr_setinheritsched\n");
116 }
[2]117
[15]118 if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
119 self->Err("Error pthread_attr_setschedpolicy\n");
120 }
[2]121
[15]122 struct sched_param parm;
123 parm.sched_priority = priority;
124 if (pthread_attr_setschedparam(&attr, &parm) != 0) {
125 self->Err("Error pthread_attr_setschedparam\n");
126 }
[2]127
[15]128 next_time = GetTime() + period;
[2]129
[15]130 if (pthread_create(&task_nrt, &attr, main_nrt, (void *)this) != 0) {
131 self->Err("pthread_create error\n");
132 }
[2]133
[15]134 if (pthread_attr_destroy(&attr) != 0) {
135 self->Err("Error pthread_attr_destroy\n");
136 }
[2]137
138#endif //__XENO__
139}
140
141#ifdef __XENO__
[15]142void Thread_impl::main_rt(void *arg) {
143 Thread_impl *caller = (Thread_impl *)arg;
[2]144
[15]145 // Perform auto-init of rt_print buffers if the task doesn't do so
146 rt_print_auto_init(1);
[2]147
[15]148 caller->self->Run();
[2]149
[15]150 caller->PrintStats();
[2]151}
152#else
[15]153void *Thread_impl::main_nrt(void *arg) {
154 Thread_impl *caller = (Thread_impl *)arg;
[2]155
[15]156 caller->self->Run();
[2]157
[15]158 caller->PrintStats();
[2]159
[15]160 pthread_exit(0);
[2]161}
162#endif //__XENO__
163
164void Thread_impl::SetPeriodUS(uint32_t period) {
[15]165 if (period == 0) {
166 self->Err("Period must be>0\n");
167 return;
168 }
[2]169
170#ifdef __XENO__
[15]171 int status = rt_task_set_periodic(&task_rt, TM_NOW, period * 1000);
172 if (status != 0)
173 self->Err("Error rt_task_set_periodic %s\n", strerror(-status));
[2]174#else
[15]175 next_time -= period;
176 next_time += period * 1000;
[2]177#endif
[15]178 this->period = period * 1000;
179 period_set = true;
[2]180}
181
[15]182uint32_t Thread_impl::GetPeriodUS() const { return this->period / 1000; }
[2]183
184void Thread_impl::SetPeriodMS(uint32_t period) {
[15]185 if (period == 0) {
186 self->Err("Period must be>0\n");
187 return;
188 }
[2]189
190#ifdef __XENO__
[15]191 int status = rt_task_set_periodic(&task_rt, TM_NOW, period * 1000 * 1000);
192 if (status != 0)
193 self->Err("Error rt_task_set_periodic %s\n", strerror(-status));
[2]194#else
[15]195 next_time -= period;
196 next_time += period * 1000 * 1000;
[2]197#endif
[15]198 this->period = period * 1000 * 1000;
199 period_set = true;
[2]200}
201
[15]202uint32_t Thread_impl::GetPeriodMS() const { return this->period / 1000 / 1000; }
[2]203
[15]204void Thread_impl::WaitPeriod(void) {
205 if (period_set == false) {
206 self->Err("Period must be set befaore calling this method\n");
207 return;
208 }
[2]209#ifdef __XENO__
[15]210 unsigned long overruns_r;
211 int status = rt_task_wait_period(&overruns_r);
212 if (status != 0)
213 self->Err("Error rt_task_wait_period %s\n", strerror(-status));
214 if (status == -ETIMEDOUT)
215 self->Err("overrun: %lld\n", overruns_r);
[2]216#else
[15]217 self->SleepUntil(next_time);
218 next_time += period;
[2]219#endif
[15]220 ComputeJitter(GetTime());
[2]221}
222
223void Thread_impl::Suspend(void) {
[15]224 if (isRunning == false) {
225 self->Err("thread is not started\n");
226 return;
227 }
[2]228
[15]229 cond->GetMutex(), is_suspended = true;
230 cond->CondWait();
231 is_suspended = false;
232 cond->ReleaseMutex();
[2]233}
234
235bool Thread_impl::SuspendUntil(Time date) {
[15]236 if (isRunning == false) {
237 self->Err("thread is not started\n");
238 return false;
239 }
[2]240
[15]241 cond->GetMutex(), is_suspended = true;
242 bool success = cond->CondWaitUntil(date);
243 is_suspended = false;
244 cond->ReleaseMutex();
245 return success;
[2]246}
247
[15]248bool Thread_impl::IsSuspended(void) {
249 bool result;
[2]250
[15]251 cond->GetMutex();
252 result = is_suspended;
253 cond->ReleaseMutex();
[2]254
[15]255 return result;
[2]256}
257
[15]258void Thread_impl::Resume(void) {
259 if (isRunning == false) {
260 self->Err("thread is not started\n");
261 return;
262 }
[2]263
[15]264 cond->GetMutex();
265 if (is_suspended == true) {
266 cond->CondSignal();
267 } else {
268 self->Err("thread is not suspended\n");
269 }
270 cond->ReleaseMutex();
[2]271}
272
[15]273int Thread_impl::WaitUpdate(const IODevice *device) {
274 int status = 0;
[2]275
[15]276 if (IsSuspended() == true) {
277 self->Err("thread is already supended\n");
278 status = -1;
279 } else {
280 cond->GetMutex();
281
282 if (device->pimpl_->SetToWake(self) == 0) {
283 is_suspended = true;
284 cond->CondWait();
285 is_suspended = false;
286 } else {
287 self->Err("%s is already waiting an update\n",
288 device->ObjectName().c_str());
289 status = -1;
[2]290 }
291
[15]292 cond->ReleaseMutex();
293 }
[2]294
[15]295 return status;
[2]296}
297
[15]298void Thread_impl::PrintStats(void) {
[2]299#ifdef __XENO__
[15]300 RT_TASK_INFO info;
[2]301
[15]302 int status = rt_task_inquire(NULL, &info);
303 if (status != 0) {
304 self->Err("Error rt_task_inquire %s\n", strerror(-status));
305 } else
[2]306#endif
[15]307 {
[2]308#ifndef __XENO__
[15]309// if(last!=0)
[2]310#endif
[15]311 { Printf("Thread::%s :\n", self->ObjectName().c_str()); }
[2]312#ifdef __XENO__
[15]313 Printf(" number of context switches: %i\n", info.ctxswitches);
314 Printf(" number of primary->secondary mode switch: %i\n",
315 info.modeswitches);
316 // printf("number of page faults: %i\n",info.pagefaults);
317 Printf(" execution time (ms) in primary mode: %lld\n",
318 info.exectime / 1000000);
[2]319#else
320/*
321 struct rusage r_usage;
322 getrusage(RUSAGE_THREAD,&r_usage);
323 printf(" memory usage = %ld\n",r_usage.ru_maxrss);
[15]324 printf("RUSAGE :ru_utime => %lld [sec] : %lld [usec], :ru_stime => %lld
325 [sec] : %lld [usec] \n",
[2]326 (int64_t)r_usage.ru_utime.tv_sec, (int64_t)r_usage.ru_utime.tv_usec,
[15]327 (int64_t)r_usage.ru_stime.tv_sec,
328 (int64_t)r_usage.ru_stime.tv_usec);*/
[2]329#endif
[15]330 if (last != 0) {
331 Printf(" min jitter (ns): %lld\n", min_jitter);
332 Printf(" max jitter (ns): %lld\n", max_jitter);
333 Printf(" jitter moy (ns): %lld\n", mean_jitter / cpt);
334 Printf(" itertions: %lld\n", cpt);
[2]335 }
[15]336 }
[2]337}
338
[15]339void Thread_impl::Join(void) {
340 if (isRunning == true) {
341 int status;
[2]342
343#ifdef __XENO__
[15]344 status = rt_task_join(&task_rt);
[2]345#else
[15]346 status = pthread_join(task_nrt, NULL);
[2]347#endif
[15]348 if (status != 0)
349 self->Err("error %s\n", strerror(-status));
350 isRunning = false;
351 }
[2]352}
353
[15]354void Thread_impl::ComputeJitter(Time time) {
355 Time diff, delta;
356 diff = time - last;
[2]357
[15]358 if (diff >= period) {
359 delta = diff - period;
360 } else {
361 delta = period - diff;
362 }
363 // if(delta==0) rt_printf("%lld %lld\n",time,last);
364 last = time;
365 if (diff == time)
366 return;
[2]367
[15]368 if (delta > max_jitter)
369 max_jitter = delta;
370 if (delta < min_jitter)
371 min_jitter = delta;
372 mean_jitter += delta;
373 cpt++;
[2]374
[15]375 // Printf("Thread::%s jitter moy (ns):
376 // %lld\n",self->ObjectName().c_str(),mean_jitter/cpt);
[2]377}
378
[15]379void Thread_impl::SafeStop(void) {
380 tobestopped = true;
381 if (IsSuspended())
382 Resume();
[2]383}
384
[15]385bool Thread_impl::ToBeStopped(void) { return tobestopped; }
Note: See TracBrowser for help on using the repository browser.