![]() |
RTXI 1.3
|
00001 /* 00002 Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Weill Cornell Medical College 00003 00004 This program is free software: you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation, either version 3 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 00017 */ 00018 00019 #ifndef RT_H 00020 #define RT_H 00021 00022 #include <fifo.h> 00023 #include <mutex.h> 00024 #include <pthread.h> 00025 #include <semaphore.h> 00026 #include <settings.h> 00027 00029 00033 namespace RT { 00034 00035 namespace OS { 00036 00037 typedef void * Task; 00038 00039 int initiate(void); 00040 void shutdown(void); 00041 00042 int createTask(Task *,void *(*)(void *),void *,int =0); 00043 void deleteTask(Task); 00044 00045 int setPeriod(Task,long long); 00046 void sleepTimestep(Task); 00047 00048 bool isRealtime(void); 00049 00057 long long getTime(void); 00058 00059 } // namespace OS 00060 00067 class Event { 00068 00069 friend class System; 00070 00071 public: 00072 00073 Event(void); 00074 virtual ~Event(void); 00075 00081 virtual int callback(void)=0; 00082 00083 private: 00084 00085 void execute(void); 00086 void wait(void); 00087 00088 int retval; 00089 sem_t signal; 00090 00091 }; // class Event 00092 00093 template<typename T> 00094 class List { 00095 00096 public: 00097 00098 class Node; 00099 00100 class iterator { 00101 00102 public: 00103 00104 iterator(void) 00105 : current(0) {}; 00106 iterator(T *x) 00107 : current(static_cast<Node *>(x)) {}; 00108 iterator(const iterator &x) 00109 : current(x.current) {}; 00110 00111 bool operator==(const iterator &x) const { 00112 return current == x.current; 00113 }; 00114 bool operator!=(const iterator &x) const { 00115 return current != x.current; 00116 }; 00117 00118 T &operator*(void) const { 00119 return *static_cast<T *>(current); 00120 }; 00121 T *operator->(void) const { 00122 return static_cast<T *>(current); 00123 }; 00124 00125 iterator &operator++(void) { 00126 current = current->next; 00127 return *this; 00128 }; 00129 iterator operator++(int) { 00130 typename RT::List<T>::iterator tmp = *this; 00131 current = current->next; 00132 return tmp; 00133 }; 00134 iterator &operator--(void) { 00135 current = current->prev; 00136 return *this; 00137 }; 00138 iterator operator--(int) { 00139 typename RT::List<T>::iterator tmp = *this; 00140 current = current->prev; 00141 return tmp; 00142 }; 00143 00144 00145 private: 00146 00147 Node *current; 00148 00149 }; // class iterator 00150 00151 class const_iterator { 00152 00153 public: 00154 00155 const_iterator(void) 00156 : current(0) {}; 00157 const_iterator(const T *x) 00158 : current(static_cast<const Node *>(x)) {}; 00159 const_iterator(const const_iterator &x) 00160 : current(x.current) {}; 00161 00162 bool operator==(const const_iterator &x) const { 00163 return current == x.current; 00164 }; 00165 bool operator!=(const const_iterator &x) const { 00166 return current != x.current; 00167 }; 00168 00169 const T &operator*(void) const { 00170 return *static_cast<const T *>(current); 00171 }; 00172 const T *operator->(void) const { 00173 return static_cast<const T *>(current); 00174 }; 00175 00176 const_iterator &operator++(void) { 00177 current = current->next; 00178 return *this; 00179 }; 00180 const_iterator operator++(int) { 00181 typename RT::List<T>::const_iterator tmp = *this; 00182 current = current->next; 00183 return tmp; 00184 }; 00185 const_iterator &operator--(void) { 00186 current = current->prev; 00187 return *this; 00188 }; 00189 const_iterator operator--(int) { 00190 typename RT::List<T>::const_iterator tmp = *this; 00191 current = current->prev; 00192 return tmp; 00193 }; 00194 00195 00196 private: 00197 00198 const Node *current; 00199 00200 }; // class const_iterator 00201 00202 class Node { 00203 00204 friend class List<T>; 00205 friend class List<T>::iterator; 00206 friend class List<T>::const_iterator; 00207 00208 public: 00209 00210 Node(void) 00211 : next(0), prev(0) {}; 00212 virtual ~Node(void) {}; 00213 00214 bool operator==(const Node &x) const { 00215 return next == x.next && prev == x.prev; 00216 }; 00217 00218 private: 00219 00220 Node *next, *prev; 00221 00222 }; // class Node 00223 00224 List(void) 00225 : count(0), head(&tail), tail() {}; 00226 virtual ~List(void) { 00227 #ifdef DEBUG 00228 if(tail.next) 00229 ERROR_MSG("RT::List::~List : end of list overwritten\n"); 00230 #endif 00231 }; 00232 00233 size_t size(void) const { 00234 return count; 00235 }; 00236 bool empty(void) const { 00237 return count==0; 00238 }; 00239 00240 iterator begin(void) { 00241 return iterator(static_cast<T *>(head)); 00242 }; 00243 iterator end(void) { 00244 return iterator(static_cast<T *>(&tail)); 00245 }; 00246 00247 const_iterator begin(void) const { 00248 return const_iterator(static_cast<const T *>(head)); 00249 }; 00250 const_iterator end(void) const { 00251 return const_iterator(static_cast<const T *>(&tail)); 00252 }; 00253 00254 void insert(iterator,T &); 00255 void insertRT(iterator position,T &node) { 00256 Node *object = static_cast<Node *>(&node); 00257 00258 object->next = &(*position); 00259 object->prev = object->next->prev; 00260 if(object->next == head) 00261 head = object; 00262 else 00263 position->prev->next = object; 00264 position->prev = object; 00265 count++; 00266 }; 00267 00268 void remove(T &); 00269 void removeRT(T &node) { 00270 Node *object = static_cast<Node *>(&node); 00271 00272 if(object == &tail) 00273 return; 00274 if(object == head) 00275 head = object->next; 00276 else if(object->prev) 00277 object->prev->next = object->next; 00278 object->next->prev = object->prev; 00279 count--; 00280 }; 00281 00282 private: 00283 00284 class InsertListNodeEvent : public RT::Event { 00285 00286 public: 00287 00288 InsertListNodeEvent(List<T> *l,iterator i,T *n) 00289 : list(l), iter(i), node(n) {}; 00290 int callback(void) { 00291 list->insertRT(iter,*node); 00292 return 0; 00293 }; 00294 00295 private: 00296 00297 List<T> *list; 00298 typename List<T>::iterator iter; 00299 T *node; 00300 00301 }; // class InsertListNodeEvent; 00302 00303 class RemoveListNodeEvent : public RT::Event { 00304 00305 public: 00306 00307 RemoveListNodeEvent(List<T> *l,T *n) 00308 : list(l), node(n) {}; 00309 int callback(void) { 00310 list->removeRT(*node); 00311 return 0; 00312 }; 00313 00314 private: 00315 00316 List<T> *list; 00317 T *node; 00318 00319 }; // class RemoveListNodeEvnet; 00320 00321 size_t count; 00322 Node *head, tail; 00323 00324 }; // class List 00325 00326 class Device; 00327 class Thread; 00328 00333 class System { 00334 00335 friend class Device; 00336 friend class Thread; 00337 00338 public: 00339 00346 static System *getInstance(void); 00347 00353 long long getPeriod(void) const { return period; }; 00360 int setPeriod(long long period); 00361 00371 void foreachDevice(void (*callback)(Device *,void *),void *param); 00381 void foreachThread(void (*callback)(Thread *,void *),void *param); 00382 00392 int postEvent(Event *event,bool blocking =true); 00393 00394 private: 00395 00396 /****************************************************************** 00397 * The constructors, destructor, and assignment operator are made * 00398 * private to control instantiation of the class. * 00399 ******************************************************************/ 00400 00401 System(void); 00402 ~System(void); 00403 System(const System &) : eventFifo(0) {}; 00404 System &operator=(const System &) { return *getInstance(); }; 00405 00406 class SetPeriodEvent : public RT::Event { 00407 00408 public: 00409 00410 SetPeriodEvent(long long); 00411 ~SetPeriodEvent(void); 00412 00413 int callback(void); 00414 00415 private: 00416 00417 long long period; 00418 00419 }; // class SetPeriodEvent 00420 00421 00422 static System *instance; 00423 00424 Mutex deviceMutex; 00425 void insertDevice(Device *); 00426 void removeDevice(Device *); 00427 00428 Mutex threadMutex; 00429 void insertThread(Thread *); 00430 void removeThread(Thread *); 00431 00432 static void *bounce(void *); 00433 void execute(void); 00434 00435 bool finished; 00436 pthread_t thread; 00437 RT::OS::Task task; 00438 long long period; 00439 00440 List<RT::Device> deviceList; 00441 List<RT::Thread> threadList; 00442 00443 Fifo eventFifo; 00444 00445 }; // class System 00446 00452 class Device : public List<Device>::Node { 00453 00454 public: 00455 00456 Device(void); 00457 virtual ~Device(void); 00458 00470 /********************************************************** 00471 * read & write must not be pure virtual because they can * 00472 * be called during construction and destruction. * 00473 **********************************************************/ 00474 00475 virtual void read(void) {}; 00476 virtual void write(void) {}; 00477 00478 inline bool getActive(void) const { return active; }; 00479 void setActive(bool); 00480 00481 private: 00482 00483 bool active; 00484 00485 }; // class Device 00486 00492 class Thread : public List<Thread>::Node { 00493 00494 public: 00495 00496 typedef unsigned long Priority; 00497 00498 static const Priority MinimumPriority = 0; 00499 static const Priority MaximumPriority = 100; 00500 static const Priority DefaultPriority = MaximumPriority/2; 00501 00502 Thread(Priority p =DefaultPriority); 00503 virtual ~Thread(void); 00504 00512 Priority getPriority(void) const { return priority; }; 00513 00520 /********************************************************** 00521 * execute must not be pure virtual because it can be * 00522 * called during construction and destruction. * 00523 **********************************************************/ 00524 00525 virtual void execute(void) {}; 00526 00527 inline bool getActive(void) const { return active; }; 00528 void setActive(bool); 00529 00530 private: 00531 00532 bool active; 00533 Priority priority; 00534 00535 }; // class Thread 00536 00537 template<typename T> 00538 void List<T>::insert(iterator position,T &node) { 00539 InsertListNodeEvent event(this,position,&node); 00540 RT::System::getInstance()->postEvent(&event); 00541 } 00542 00543 template<typename T> 00544 void List<T>::remove(T &node) { 00545 RemoveListNodeEvent event(this,&node); 00546 RT::System::getInstance()->postEvent(&event); 00547 } 00548 00549 } // namespace RT 00550 00551 #endif // RT_H