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

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

aded semaphore
resolved bug for rt_printf before thread is started

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