RTXI  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
rt_os-posix.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 <rt.h>
22 
23 #include <errno.h>
24 #include <list>
25 #include <semaphore.h>
26 #include <sys/mman.h>
27 #include <sys/time.h>
28 
29 typedef struct
30 {
31  long long period;
32  long long next_t;
33  pthread_t thread;
34 } posix_task_t;
35 
36 static bool init_rt = false;
37 static pthread_key_t is_rt_key;
38 
40 {
41  /*
42  * I want users to be very much aware that they aren't running in realtime.
43  */
44  ERROR_MSG("***WARNING*** You are using the POSIX compatibility layer, RTXI is NOT running in realtime!!!\n");
45 
46  if (mlockall(MCL_CURRENT | MCL_FUTURE))
47  {
48  ERROR_MSG("RT::OS(POSIX)::initiate : failed to lock memory.\n");
49 
50  /*
51  * I don't think it is necessary to return an error in this case.
52  * Because unless you are root it will always error.
53  */
54  //return -EPERM;
55  }
56 
57  pthread_key_create(&is_rt_key,0);
58  init_rt = true;
59 
60  return 0;
61 }
62 
63 void RT::OS::shutdown(void)
64 {
65  pthread_key_delete(is_rt_key);
66 }
67 
69 {
70  void *(*entry)(void *);
72  void *arg;
73  sem_t sem;
74 };
75 
76 static void *bounce(void *bounce_info)
77 {
78  posix_bounce_info_t *info = reinterpret_cast<posix_bounce_info_t *>(bounce_info);
79 
80  posix_task_t *t = info->t;
81  void *(*entry)(void *) = info->entry;
82  void *arg = info->arg;
83 
84  t->period = -1;
85  t->next_t = -1;
86  t->thread = pthread_self();
87 
88  pthread_setspecific(is_rt_key,reinterpret_cast<const void *>(t));
89 
90  sem_post(&info->sem);
91  return entry(arg);
92 }
93 
94 int RT::OS::createTask(RT::OS::Task *task,void *(*entry)(void *),void *arg,int)
95 {
96  int retval = 0;
97  posix_task_t *t = new posix_task_t;
98  *task = t;
99 
100  posix_bounce_info_t info =
101  {
102  entry,
103  t,
104  arg,
105  };
106  sem_init(&info.sem,0,0);
107 
108  retval = pthread_create(&t->thread,NULL,&::bounce,&info);
109  if (!retval)
110  sem_wait(&info.sem);
111  else
112  ERROR_MSG("RT::OS::createTask : pthread_create failed\n");
113 
114  sem_destroy(&info.sem);
115  return retval;
116 }
117 
119 {
120  posix_task_t *t = reinterpret_cast<posix_task_t *>(task);
121  if (t == NULL)
122  return;
123 
124  pthread_join(t->thread,0);
125  delete t;
126 }
127 
129 {
130  if (init_rt && pthread_getspecific(is_rt_key))
131  return true;
132  return false;
133 }
134 
135 long long RT::OS::getTime(void)
136 {
137  struct timeval tv;
138 
139  gettimeofday(&tv,NULL);
140 
141  return 1000000000ll*tv.tv_sec+1000ll*tv.tv_usec;
142 }
143 
144 int RT::OS::setPeriod(RT::OS::Task task,long long period)
145 {
146  posix_task_t *t = reinterpret_cast<posix_task_t *>(task);
147 
148  t->period = period;
149  t->next_t = getTime()+period;
150 
151  return 0;
152 }
153 
155 {
156  posix_task_t *t = reinterpret_cast<posix_task_t *>(task);
157  if (t == NULL)
158  return;
159 
160  long long sleep_time = t->next_t-getTime();
161  t->next_t += t->period;
162 
163  struct timespec ts =
164  {
165  sleep_time / 1000000000ll,
166  sleep_time % 1000000000ll,
167  };
168 
169  while (nanosleep(&ts,&ts) < 0 && errno == EINTR);
170 }
int initiate(void)
Definition: rt_os-posix.cpp:39
void deleteTask(Task)
int createTask(Task *, void *(*)(void *), void *, int=0)
bool isRealtime(void)
double arg(const complex _z)
Definition: complex.h:133
void sleepTimestep(Task)
#define ERROR_MSG(fmt, args...)
Definition: debug.h:41
pthread_t thread
Definition: rt_os-posix.cpp:33
void * Task
Definition: rt.h:40
long long getTime(void)
long long period
Definition: rt_os-posix.cpp:31
long long next_t
Definition: rt_os-posix.cpp:32
int setPeriod(Task, long long)
void shutdown(void)
Definition: rt_os-posix.cpp:63
posix_task_t * t
Definition: rt_os-posix.cpp:71
void *(* entry)(void *)
Definition: rt_os-posix.cpp:70