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

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

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

File size: 9.3 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>
[38]30#include <unistd.h>
31#include <sys/syscall.h>
[2]32#endif
33
34using std::string;
35using namespace flair::core;
36
[15]37Thread_impl::Thread_impl(Thread *self, uint8_t priority) {
38 isRunning = false;
39 tobestopped = false;
40 is_suspended = false;
41 period_set = false;
[2]42
[15]43 this->self = self;
44 cond = new ConditionVariable(self, self->ObjectName());
[2]45
[15]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 }
[2]55
[15]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;
[2]63}
64
[15]65Thread_impl::~Thread_impl() {
66 SafeStop();
67 Join();
[2]68}
69
[15]70void Thread_impl::Start(void) {
71 int status;
[2]72
[15]73 isRunning = true;
[20]74 tobestopped = false;
75 is_suspended = false;
[2]76
77#ifdef __XENO__
[15]78 string th_name =
79 getFrameworkManager()->ObjectName() + "-" + self->ObjectName();
[2]80
81#ifdef RT_STACK_SIZE
[15]82 status = rt_task_create(&task_rt, th_name.c_str(), RT_STACK_SIZE,
83 (int)priority, T_JOINABLE);
[2]84#else
[15]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 }
[2]93
[15]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 }
[2]100
[15]101 // Initialise the rt_print buffer for this task explicitly
102 rt_print_init(512, th_name.c_str());
[2]103
104#else //__XENO__
105
[15]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 }
[2]111
112#ifdef NRT_STACK_SIZE
[15]113 if (pthread_attr_setstacksize(&attr, NRT_STACK_SIZE) != 0) {
114 self->Err("Error pthread_attr_setstacksize\n");
115 }
116#endif // NRT_STACK_SIZE
[2]117
[15]118 if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) {
119 self->Err("Error pthread_attr_setinheritsched\n");
120 }
[2]121
[15]122 if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
123 self->Err("Error pthread_attr_setschedpolicy\n");
124 }
[2]125
[15]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 }
[2]131
[15]132 next_time = GetTime() + period;
[2]133
[15]134 if (pthread_create(&task_nrt, &attr, main_nrt, (void *)this) != 0) {
135 self->Err("pthread_create error\n");
136 }
[2]137
[15]138 if (pthread_attr_destroy(&attr) != 0) {
139 self->Err("Error pthread_attr_destroy\n");
140 }
[2]141
142#endif //__XENO__
143}
144
145#ifdef __XENO__
[15]146void Thread_impl::main_rt(void *arg) {
147 Thread_impl *caller = (Thread_impl *)arg;
[2]148
[15]149 // Perform auto-init of rt_print buffers if the task doesn't do so
150 rt_print_auto_init(1);
[2]151
[15]152 caller->self->Run();
[2]153
[15]154 caller->PrintStats();
[2]155}
156#else
[38]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));*/
[2]162
[15]163 caller->self->Run();
[2]164
[15]165 caller->PrintStats();
[2]166
[15]167 pthread_exit(0);
[2]168}
169#endif //__XENO__
170
171void Thread_impl::SetPeriodUS(uint32_t period) {
[15]172 if (period == 0) {
173 self->Err("Period must be>0\n");
174 return;
175 }
[2]176
177#ifdef __XENO__
[15]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));
[2]181#else
[15]182 next_time -= period;
183 next_time += period * 1000;
[2]184#endif
[15]185 this->period = period * 1000;
186 period_set = true;
[2]187}
188
[15]189uint32_t Thread_impl::GetPeriodUS() const { return this->period / 1000; }
[2]190
191void Thread_impl::SetPeriodMS(uint32_t period) {
[15]192 if (period == 0) {
193 self->Err("Period must be>0\n");
194 return;
195 }
[2]196
197#ifdef __XENO__
[15]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));
[2]201#else
[15]202 next_time -= period;
203 next_time += period * 1000 * 1000;
[2]204#endif
[15]205 this->period = period * 1000 * 1000;
206 period_set = true;
[2]207}
208
[15]209uint32_t Thread_impl::GetPeriodMS() const { return this->period / 1000 / 1000; }
[2]210
[15]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 }
[2]216#ifdef __XENO__
[15]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);
[2]223#else
[15]224 self->SleepUntil(next_time);
225 next_time += period;
[2]226#endif
[15]227 ComputeJitter(GetTime());
[2]228}
229
230void Thread_impl::Suspend(void) {
[15]231 if (isRunning == false) {
232 self->Err("thread is not started\n");
233 return;
234 }
[2]235
[15]236 cond->GetMutex(), is_suspended = true;
237 cond->CondWait();
238 is_suspended = false;
239 cond->ReleaseMutex();
[2]240}
241
242bool Thread_impl::SuspendUntil(Time date) {
[15]243 if (isRunning == false) {
244 self->Err("thread is not started\n");
245 return false;
246 }
[2]247
[15]248 cond->GetMutex(), is_suspended = true;
249 bool success = cond->CondWaitUntil(date);
250 is_suspended = false;
251 cond->ReleaseMutex();
252 return success;
[2]253}
254
[15]255bool Thread_impl::IsSuspended(void) {
256 bool result;
[2]257
[15]258 cond->GetMutex();
259 result = is_suspended;
260 cond->ReleaseMutex();
[2]261
[15]262 return result;
[2]263}
264
[15]265void Thread_impl::Resume(void) {
266 if (isRunning == false) {
267 self->Err("thread is not started\n");
268 return;
269 }
[2]270
[15]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();
[2]278}
279
[15]280int Thread_impl::WaitUpdate(const IODevice *device) {
281 int status = 0;
[2]282
[15]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;
[2]297 }
298
[15]299 cond->ReleaseMutex();
300 }
[2]301
[15]302 return status;
[2]303}
304
[15]305void Thread_impl::PrintStats(void) {
[2]306#ifdef __XENO__
[15]307 RT_TASK_INFO info;
[2]308
[15]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
[2]313#endif
[15]314 {
[2]315#ifndef __XENO__
[15]316// if(last!=0)
[2]317#endif
[15]318 { Printf("Thread::%s :\n", self->ObjectName().c_str()); }
[2]319#ifdef __XENO__
[15]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);
[2]326#else
327/*
328 struct rusage r_usage;
329 getrusage(RUSAGE_THREAD,&r_usage);
330 printf(" memory usage = %ld\n",r_usage.ru_maxrss);
[15]331 printf("RUSAGE :ru_utime => %lld [sec] : %lld [usec], :ru_stime => %lld
332 [sec] : %lld [usec] \n",
[2]333 (int64_t)r_usage.ru_utime.tv_sec, (int64_t)r_usage.ru_utime.tv_usec,
[15]334 (int64_t)r_usage.ru_stime.tv_sec,
335 (int64_t)r_usage.ru_stime.tv_usec);*/
[2]336#endif
[15]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);
[2]342 }
[15]343 }
[2]344}
345
[15]346void Thread_impl::Join(void) {
347 if (isRunning == true) {
348 int status;
[2]349
350#ifdef __XENO__
[15]351 status = rt_task_join(&task_rt);
[2]352#else
[15]353 status = pthread_join(task_nrt, NULL);
[2]354#endif
[15]355 if (status != 0)
356 self->Err("error %s\n", strerror(-status));
357 isRunning = false;
358 }
[2]359}
360
[15]361void Thread_impl::ComputeJitter(Time time) {
362 Time diff, delta;
363 diff = time - last;
[2]364
[15]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;
[2]374
[15]375 if (delta > max_jitter)
376 max_jitter = delta;
377 if (delta < min_jitter)
378 min_jitter = delta;
379 mean_jitter += delta;
380 cpt++;
[2]381
[15]382 // Printf("Thread::%s jitter moy (ns):
383 // %lld\n",self->ObjectName().c_str(),mean_jitter/cpt);
[2]384}
385
[15]386void Thread_impl::SafeStop(void) {
387 tobestopped = true;
388 if (IsSuspended())
389 Resume();
[2]390}
391
[15]392bool Thread_impl::ToBeStopped(void) { return tobestopped; }
Note: See TracBrowser for help on using the repository browser.