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

Last change on this file since 25 was 20, checked in by Sanahuja Guillaume, 8 years ago

correction bug recpetion log et watchdog

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