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

Last change on this file since 42 was 38, checked in by Bayard Gildas, 5 years ago

Modif. pour ajour manette émulée (EmulatedController?)

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