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

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

correction bug recpetion log et watchdog

File size: 9.1 KB
Line 
1// %flair:license{
2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
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
35Thread_impl::Thread_impl(Thread *self, uint8_t priority) {
36  isRunning = false;
37  tobestopped = false;
38  is_suspended = false;
39  period_set = false;
40
41  this->self = self;
42  cond = new ConditionVariable(self, self->ObjectName());
43
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  }
53
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;
61}
62
63Thread_impl::~Thread_impl() {
64  SafeStop();
65  Join();
66}
67
68void Thread_impl::Start(void) {
69  int status;
70
71  isRunning = true;
72  tobestopped = false;
73  is_suspended = false;
74
75#ifdef __XENO__
76  string th_name =
77      getFrameworkManager()->ObjectName() + "-" + self->ObjectName();
78
79#ifdef RT_STACK_SIZE
80  status = rt_task_create(&task_rt, th_name.c_str(), RT_STACK_SIZE,
81                          (int)priority, T_JOINABLE);
82#else
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  }
91
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  }
98
99  // Initialise the rt_print buffer for this task explicitly
100  rt_print_init(512, th_name.c_str());
101
102#else //__XENO__
103
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  }
109
110#ifdef NRT_STACK_SIZE
111  if (pthread_attr_setstacksize(&attr, NRT_STACK_SIZE) != 0) {
112    self->Err("Error pthread_attr_setstacksize\n");
113  }
114#endif // NRT_STACK_SIZE
115
116  if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) {
117    self->Err("Error pthread_attr_setinheritsched\n");
118  }
119
120  if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
121    self->Err("Error pthread_attr_setschedpolicy\n");
122  }
123
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  }
129
130  next_time = GetTime() + period;
131
132  if (pthread_create(&task_nrt, &attr, main_nrt, (void *)this) != 0) {
133    self->Err("pthread_create error\n");
134  }
135
136  if (pthread_attr_destroy(&attr) != 0) {
137    self->Err("Error pthread_attr_destroy\n");
138  }
139
140#endif //__XENO__
141}
142
143#ifdef __XENO__
144void Thread_impl::main_rt(void *arg) {
145  Thread_impl *caller = (Thread_impl *)arg;
146
147  // Perform auto-init of rt_print buffers if the task doesn't do so
148  rt_print_auto_init(1);
149
150  caller->self->Run();
151
152  caller->PrintStats();
153}
154#else
155void *Thread_impl::main_nrt(void *arg) {
156  Thread_impl *caller = (Thread_impl *)arg;
157
158  caller->self->Run();
159
160  caller->PrintStats();
161
162  pthread_exit(0);
163}
164#endif //__XENO__
165
166void Thread_impl::SetPeriodUS(uint32_t period) {
167  if (period == 0) {
168    self->Err("Period must be>0\n");
169    return;
170  }
171
172#ifdef __XENO__
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));
176#else
177  next_time -= period;
178  next_time += period * 1000;
179#endif
180  this->period = period * 1000;
181  period_set = true;
182}
183
184uint32_t Thread_impl::GetPeriodUS() const { return this->period / 1000; }
185
186void Thread_impl::SetPeriodMS(uint32_t period) {
187  if (period == 0) {
188    self->Err("Period must be>0\n");
189    return;
190  }
191
192#ifdef __XENO__
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));
196#else
197  next_time -= period;
198  next_time += period * 1000 * 1000;
199#endif
200  this->period = period * 1000 * 1000;
201  period_set = true;
202}
203
204uint32_t Thread_impl::GetPeriodMS() const { return this->period / 1000 / 1000; }
205
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  }
211#ifdef __XENO__
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);
218#else
219  self->SleepUntil(next_time);
220  next_time += period;
221#endif
222  ComputeJitter(GetTime());
223}
224
225void Thread_impl::Suspend(void) {
226  if (isRunning == false) {
227    self->Err("thread is not started\n");
228    return;
229  }
230
231  cond->GetMutex(), is_suspended = true;
232  cond->CondWait();
233  is_suspended = false;
234  cond->ReleaseMutex();
235}
236
237bool Thread_impl::SuspendUntil(Time date) {
238  if (isRunning == false) {
239    self->Err("thread is not started\n");
240    return false;
241  }
242
243  cond->GetMutex(), is_suspended = true;
244  bool success = cond->CondWaitUntil(date);
245  is_suspended = false;
246  cond->ReleaseMutex();
247  return success;
248}
249
250bool Thread_impl::IsSuspended(void) {
251  bool result;
252
253  cond->GetMutex();
254  result = is_suspended;
255  cond->ReleaseMutex();
256
257  return result;
258}
259
260void Thread_impl::Resume(void) {
261  if (isRunning == false) {
262    self->Err("thread is not started\n");
263    return;
264  }
265
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();
273}
274
275int Thread_impl::WaitUpdate(const IODevice *device) {
276  int status = 0;
277
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;
292    }
293
294    cond->ReleaseMutex();
295  }
296
297  return status;
298}
299
300void Thread_impl::PrintStats(void) {
301#ifdef __XENO__
302  RT_TASK_INFO info;
303
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
308#endif
309  {
310#ifndef __XENO__
311// if(last!=0)
312#endif
313    { Printf("Thread::%s :\n", self->ObjectName().c_str()); }
314#ifdef __XENO__
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);
321#else
322/*
323        struct rusage r_usage;
324        getrusage(RUSAGE_THREAD,&r_usage);
325        printf("    memory usage = %ld\n",r_usage.ru_maxrss);
326        printf("RUSAGE :ru_utime => %lld [sec] : %lld [usec], :ru_stime => %lld
327   [sec] : %lld [usec] \n",
328           (int64_t)r_usage.ru_utime.tv_sec, (int64_t)r_usage.ru_utime.tv_usec,
329           (int64_t)r_usage.ru_stime.tv_sec,
330   (int64_t)r_usage.ru_stime.tv_usec);*/
331#endif
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);
337    }
338  }
339}
340
341void Thread_impl::Join(void) {
342  if (isRunning == true) {
343    int status;
344
345#ifdef __XENO__
346    status = rt_task_join(&task_rt);
347#else
348    status = pthread_join(task_nrt, NULL);
349#endif
350    if (status != 0)
351      self->Err("error %s\n", strerror(-status));
352    isRunning = false;
353  }
354}
355
356void Thread_impl::ComputeJitter(Time time) {
357  Time diff, delta;
358  diff = time - last;
359
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;
369
370  if (delta > max_jitter)
371    max_jitter = delta;
372  if (delta < min_jitter)
373    min_jitter = delta;
374  mean_jitter += delta;
375  cpt++;
376
377  // Printf("Thread::%s jitter moy (ns):
378  // %lld\n",self->ObjectName().c_str(),mean_jitter/cpt);
379}
380
381void Thread_impl::SafeStop(void) {
382  tobestopped = true;
383  if (IsSuspended())
384    Resume();
385}
386
387bool Thread_impl::ToBeStopped(void) { return tobestopped; }
Note: See TracBrowser for help on using the repository browser.