RTXI  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
rt.cpp
Go to the documentation of this file.
1 /*
2  The Real-Time eXperiment Interface (RTXI)
3  Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Weill Cornell Medical College
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  */
19 
20 #include <debug.h>
21 #include <event.h>
22 #include <mutex.h>
23 #include <rt.h>
24 
25 namespace
26 {
27 class SetThreadActive:public RT::Event
28 {
29 
30 public:
31  SetThreadActive(RT::Thread *,bool);
32  ~SetThreadActive(void);
33  int callback(void);
34 
35 private:
36  RT::Thread *thread;
37  bool active;
38 
39 }; // class SetThreadActive
40 
41 class SetDeviceActive : public RT::Event
42 {
43 
44 public:
45  SetDeviceActive(RT::Device *,bool);
46  ~SetDeviceActive(void);
47  int callback(void);
48 
49 private:
50  RT::Device *device;
51  bool active;
52 }; // class SetDeviceActive
53 
54 }; // namespace
55 
56 SetThreadActive::SetThreadActive(RT::Thread *t,bool a):thread(t), active(a) {}
57 
58 SetThreadActive::~SetThreadActive(void) {}
59 
60 int SetThreadActive::callback(void)
61 {
62  thread->setActive(active);
63  return 0;
64 }
65 
66 SetDeviceActive::SetDeviceActive(RT::Device *d,bool a):device(d), active(a) {}
67 
68 SetDeviceActive::~SetDeviceActive(void) {}
69 
70 int SetDeviceActive::callback(void)
71 {
72  device->setActive(active);
73  return 0;
74 }
75 
77  : period(p) {}
78 
80 
82 {
83  int retval;
85 
86  if (!(retval = RT::OS::setPeriod(sys->task,period)))
87  {
88  sys->period = period;
89 
91  event.setParam("period",&period);
93  }
94 
95  return retval;
96 }
97 
99 {
100  sem_init(&signal,0,0);
101 }
102 
104 {
105  sem_destroy(&signal);
106 }
107 
109 {
110  retval = callback();
111  sem_post(&signal);
112 }
113 
114 void RT::Event::wait(void)
115 {
116  sem_wait(&signal);
117 }
118 
120  : active(false)
121 {
123 }
124 
126 {
128 }
129 
130 void RT::Device::setActive(bool state)
131 {
132  if (RT::OS::isRealtime())
133  active = state;
134  else
135  {
136  SetDeviceActive event(this,state);
138  }
139 }
140 
142  : active(false), priority(p)
143 {
145 }
146 
148 {
150 }
151 
152 void RT::Thread::setActive(bool state)
153 {
154  if (RT::OS::isRealtime())
155  active = state;
156  else
157  {
158  SetThreadActive event(this,state);
160  }
161 }
162 
164  : finished(false), eventFifo(100*sizeof(RT::Event *))
165 {
166  period = 1000000; // 1 kHz
167 
168  if (RT::OS::initiate())
169  {
170  ERROR_MSG("RT::System::System : failed to initialize the realtime system\n");
171  return;
172  }
173 
175  {
176  ERROR_MSG("RT::System::System : failed to create realtime thread\n");
177  return;
178  }
179 }
180 
182 {
183  finished = true;
184  RT::OS::deleteTask(task);
186 }
187 
188 int RT::System::setPeriod(long long period)
189 {
191  event_pre.setParam("period",&period);
193 
194  SetPeriodEvent event(period);
195  int retval = postEvent(&event);
196 
198  event_post.setParam("period",&period);
200 
201  return retval;
202 }
203 
204 void RT::System::foreachDevice(void (*callback)(RT::Device *,void *),void *param)
205 {
206  Mutex::Locker lock(&deviceMutex);
207  for (List<Device>::iterator i = devices.begin(); i != devices.end(); ++i)
208  callback(&*i,param);
209 }
210 
211 void RT::System::foreachThread(void (*callback)(RT::Thread *,void *),void *param)
212 {
213  Mutex::Locker lock(&threadMutex);
214  for (List<Thread>::iterator i = threadList.begin(); i != threadList.end(); ++i)
215  callback(&*i,param);
216 }
217 
218 int RT::System::postEvent(RT::Event *event,bool blocking)
219 {
220  eventFifo.write(&event,sizeof(RT::Event *));
221  if (blocking)
222  {
223  event->wait();
224  return event->retval;
225  }
226  return 0;
227 }
228 
230 {
231  if (!device)
232  {
233  ERROR_MSG("RT::System::insertDevice : invalid device\n");
234  return;
235  }
236 
237  Mutex::Locker lock(&deviceMutex);
238 
240  event.setParam("device",device);
242 
243  devices.insert(devices.end(),*device);
244 }
245 
247 {
248  if (!device)
249  {
250  ERROR_MSG("RT::System::removeDevice : invalid device\n");
251  return;
252  }
253 
254  Mutex::Locker lock(&deviceMutex);
255 
257  event.setParam("device",device);
259 
260  devices.remove(*device);
261 }
262 
264 {
265  if (!thread)
266  {
267  ERROR_MSG("RT::System::insertThread : invalid thread\n");
268  return;
269  }
270 
271  Mutex::Locker lock(&threadMutex);
272 
273  /*******************************************************************************
274  * Traverse the list of threads and find the first thread with lower priority. *
275  *******************************************************************************/
276 
277  List<Thread>::iterator i = threadList.begin();
278  for (; i != threadList.end() && i->getPriority() >= thread->getPriority(); ++i);
279 
281  event.setParam("thread",thread);
283 
284  threadList.insert(i,*thread);
285 }
286 
288 {
289  if (!thread)
290  {
291  ERROR_MSG("RT::System::removeThread : invalid thread\n");
292  return;
293  }
294 
295  Mutex::Locker lock(&threadMutex);
296 
298  event.setParam("thread",thread);
300 
301  threadList.remove(*thread);
302 }
303 
304 void *RT::System::bounce(void *param)
305 {
306 
307  RT::System *that = reinterpret_cast<RT::System *>(param);
308  if (that)
309  that->execute();
310  return 0;
311 }
312 
314 {
315 
316  Event *event = 0;
317  List<Device>::iterator iDevice;
318  List<Thread>::iterator iThread;
319  List<Device>::iterator devicesBegin = devices.begin();
320  List<Device>::iterator devicesEnd = devices.end();
321  List<Thread>::iterator threadListBegin = threadList.begin();
322  List<Thread>::iterator threadListEnd = threadList.end();
323 
324  if (RT::OS::setPeriod(task,period))
325  {
326  ERROR_MSG("RT::System::execute : failed to set the initial period of the realtime thread\n");
327  return;
328  }
329 
330  while (!finished)
331  {
332  RT::OS::sleepTimestep(task);
333 
334  for (iDevice = devicesBegin; iDevice != devicesEnd; ++iDevice)
335  if (iDevice->getActive()) iDevice->read();
336 
337  for (iThread = threadListBegin; iThread != threadListEnd; ++iThread)
338  if (iThread->getActive()) iThread->execute();
339 
340  for (iDevice = devicesBegin; iDevice != devicesEnd; ++iDevice)
341  if (iDevice->getActive()) iDevice->write();
342 
343  if (eventFifo.read(&event,sizeof(RT::Event *),false))
344  {
345  do
346  {
347  event->execute();
348  }
349  while (eventFifo.read(&event,sizeof(RT::Event *),false));
350 
351  event = 0;
352  devicesBegin = devices.begin();
353  threadListBegin = threadList.begin();
354  }
355  }
356 }
357 
358 static Mutex mutex;
360 
362 {
363  if (instance)
364  return instance;
365 
366  /*************************************************************************
367  * Seems like alot of hoops to jump through, but static allocation isn't *
368  * thread-safe. So effort must be taken to ensure mutual exclusion. *
369  *************************************************************************/
370 
371  Mutex::Locker lock(&::mutex);
372  if (!instance)
373  {
374  static System system;
375  instance = &system;
376  }
377 
378  return instance;
379 }
virtual ~Event(void)
Definition: rt.cpp:103
const char * RT_PERIOD_EVENT
Definition: event.cpp:24
int initiate(void)
Definition: rt_os-posix.cpp:39
void execute(void)
Definition: rt.cpp:313
Device(void)
Definition: rt.cpp:119
void setParam(const char *, void *)
Definition: event.cpp:89
unsigned long Priority
Definition: rt.h:547
void deleteTask(Task)
void setActive(bool)
Definition: rt.cpp:130
int createTask(Task *, void *(*)(void *), void *, int=0)
SetPeriodEvent(long long)
Definition: rt.cpp:76
void postEvent(const Object *event)
Definition: event.cpp:110
~System(void)
Definition: rt.cpp:181
int callback(void)
Definition: rt.cpp:81
static System * instance
Definition: rt.h:468
bool isRealtime(void)
void insertThread(Thread *)
Definition: rt.cpp:263
Priority getPriority(void) const
Definition: rt.h:563
void insertDevice(Device *)
Definition: rt.cpp:229
System(void)
Definition: rt.cpp:163
void execute(void)
Definition: rt.cpp:108
const char * RT_PREPERIOD_EVENT
Definition: event.cpp:25
Definition: mutex.h:28
void removeThread(Thread *)
Definition: rt.cpp:287
void sleepTimestep(Task)
#define ERROR_MSG(fmt, args...)
Definition: debug.h:41
static Manager * getInstance(void)
Definition: event.cpp:149
void foreachThread(void(*callback)(Thread *, void *), void *param)
Definition: rt.cpp:211
virtual int callback(void)=0
RT::OS::Task task
Definition: rt.h:483
Thread(Priority p=DefaultPriority)
Definition: rt.cpp:141
Event(void)
Definition: rt.cpp:98
Definition: rt.h:371
const char * RT_THREAD_REMOVE_EVENT
Definition: event.cpp:28
void foreachDevice(void(*callback)(Device *, void *), void *param)
Definition: rt.cpp:204
const char * RT_DEVICE_INSERT_EVENT
Definition: event.cpp:29
static void * bounce(void *)
Definition: rt.cpp:304
void setActive(bool)
Definition: rt.cpp:152
const char * RT_POSTPERIOD_EVENT
Definition: event.cpp:26
const char * RT_DEVICE_REMOVE_EVENT
Definition: event.cpp:30
Definition: rt.h:70
int setPeriod(long long period)
Definition: rt.cpp:188
void wait(void)
Definition: rt.cpp:114
Realtime Oriented Classes.
Definition: rt.h:34
long long period
Definition: rt.h:484
virtual ~Device(void)
Definition: rt.cpp:125
static System * getInstance(void)
Definition: rt.cpp:361
int setPeriod(Task, long long)
Event Oriented Classes.
Definition: event.h:35
Definition: rt.h:498
void postEventRT(const Object *event)
Definition: event.cpp:118
void shutdown(void)
Definition: rt_os-posix.cpp:63
virtual ~Thread(void)
Definition: rt.cpp:147
const char * RT_THREAD_INSERT_EVENT
Definition: event.cpp:27
void removeDevice(Device *)
Definition: rt.cpp:246
int postEvent(Event *event, bool blocking=true)
Definition: rt.cpp:218
Definition: rt.h:542