RTXI  2.4
The Real-Time eXperiment Interface Documentation
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 #include <sys/types.h>
29 #include <unistd.h>
30 #include <pthread.h>
31 #include <time.h>
32 #include <sys/resource.h>
33 
34 #include <fstream>
35 #include <string>
36 
37 typedef struct
38 {
39  long long period;
40  long long next_t;
41  pthread_t thread;
42 } posix_task_t;
43 
44 static bool init_rt = false;
45 static pthread_key_t is_rt_key;
46 
48 {
49  /*
50  * I want users to be very much aware that they aren't running in realtime.
51  */
52  std::cout << "***WARNING*** You are using the POSIX compatibility layer, RTXI is NOT running in realtime!!!\n";
53 
54  if (mlockall(MCL_CURRENT | MCL_FUTURE))
55  {
56  std::cout << "RT::OS(POSIX)::initiate : failed to lock memory.\n";
57 
58  /*
59  * I don't think it is necessary to return an error in this case.
60  * Because unless you are root it will always error.
61  */
62  //return -EPERM;
63  }
64 
65  pthread_key_create(&is_rt_key,0);
66  init_rt = true;
67 
68  return 0;
69 }
70 
71 void RT::OS::shutdown(void)
72 {
73  pthread_key_delete(is_rt_key);
74 }
75 
77 {
78  void *(*entry)(void *);
80  void *arg;
81  sem_t sem;
82 };
83 
84 static void *bounce(void *bounce_info)
85 {
86  posix_bounce_info_t *info = reinterpret_cast<posix_bounce_info_t *>(bounce_info);
87 
88  posix_task_t *t = info->t;
89  void *(*entry)(void *) = info->entry;
90  void *arg = info->arg;
91 
92  t->period = -1;
93  t->next_t = -1;
94  t->thread = pthread_self();
95 
96  pthread_setspecific(is_rt_key,reinterpret_cast<const void *>(t));
97 
98  sem_post(&info->sem);
99  return entry(arg);
100 }
101 
102 int RT::OS::createTask(RT::OS::Task *task,void *(*entry)(void *),void *arg,int)
103 {
104  int retval = 0;
105  posix_task_t *t = new posix_task_t;
106  *task = t;
107 
108  posix_bounce_info_t info =
109  {
110  entry,
111  t,
112  arg,
113  };
114  sem_init(&info.sem,0,0);
115 
116  retval = pthread_create(&t->thread,NULL,&::bounce,&info);
117  if (!retval)
118  sem_wait(&info.sem);
119  else
120  ERROR_MSG("RT::OS::createTask : pthread_create failed\n");
121 
122  sem_destroy(&info.sem);
123  return retval;
124 }
125 
127 {
128  posix_task_t *t = reinterpret_cast<posix_task_t *>(task);
129  if (t == NULL)
130  return;
131 
132  pthread_join(t->thread,0);
133  delete t;
134 }
135 
137 {
138  if (init_rt && pthread_getspecific(is_rt_key))
139  return true;
140  return false;
141 }
142 
143 long long RT::OS::getTime(void)
144 {
145  struct timeval tv;
146 
147  gettimeofday(&tv,NULL);
148 
149  return 1000000000ll*tv.tv_sec+1000ll*tv.tv_usec;
150 }
151 
152 int RT::OS::setPeriod(RT::OS::Task task,long long period)
153 {
154  posix_task_t *t = reinterpret_cast<posix_task_t *>(task);
155 
156  t->period = period;
157  t->next_t = getTime()+period;
158 
159  return 0;
160 }
161 
163 {
164  posix_task_t *t = reinterpret_cast<posix_task_t *>(task);
165  if (t == NULL)
166  return;
167 
168  long long sleep_time = t->next_t-getTime();
169  t->next_t += t->period;
170 
171  struct timespec ts =
172  {
173  sleep_time / 1000000000ll,
174  sleep_time % 1000000000ll,
175  };
176 
177  while (nanosleep(&ts,&ts) < 0 && errno == EINTR);
178 }
179 
181 timespec last_proc_time;
182 
184 {
185  // Should not attempt this in the real-time thread
186  if(RT::OS::isRealtime()){
187  ERROR_MSG("RT::OS::getCpuUsage : This function should only be run in user space. Aborting.");
188  return 0.0;
189  }
190 
191  double cpu_percent;
192  long cpu_time_elapsed;
193  long proc_time_elapsed;
194 
195  timespec clock_time;
196  timespec proc_time;
197  //rusage resource_usage;
198 
199  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &proc_time);
200  clock_gettime(CLOCK_REALTIME, &clock_time);
201  //getrusage(RUSAGE_SELF, &resource_usage);
202 
203  cpu_time_elapsed = 1e9*(clock_time.tv_sec - last_clock_read.tv_sec) +
204  (clock_time.tv_nsec - last_clock_read.tv_nsec);
205  if (cpu_time_elapsed <= 0) return 0.0;
206  proc_time_elapsed = 1e9*(proc_time.tv_sec - last_proc_time.tv_sec) +
207  (proc_time.tv_nsec - last_proc_time.tv_nsec);
208  cpu_percent = 100.0*(proc_time_elapsed) / cpu_time_elapsed;
209 
210  last_proc_time = proc_time;
211  last_clock_read = clock_time;
212  return cpu_percent;
213 }
214 
posix_bounce_info_t
Definition: rt_os-posix.cpp:76
posix_bounce_info_t::t
posix_task_t * t
Definition: rt_os-posix.cpp:79
RT::OS::createTask
int createTask(Task *, void *(*)(void *), void *, int=0)
ERROR_MSG
void ERROR_MSG(const std::string &errmsg,...)
Definition: debug.cpp:27
posix_task_t::period
long long period
Definition: rt_os-posix.cpp:39
RT::OS::deleteTask
void deleteTask(Task)
Definition: rt_os-posix.cpp:126
posix_task_t::next_t
long long next_t
Definition: rt_os-posix.cpp:40
posix_bounce_info_t::entry
void *(* entry)(void *)
Definition: rt_os-posix.cpp:78
RT::OS::getTime
long long getTime(void)
Definition: rt_os-posix.cpp:143
RT::OS::isRealtime
bool isRealtime(void)
Definition: rt_os-posix.cpp:136
RT::OS::Task
void * Task
Definition: rt.h:40
RT::OS::sleepTimestep
void sleepTimestep(Task)
Definition: rt_os-posix.cpp:162
posix_task_t::thread
pthread_t thread
Definition: rt_os-posix.cpp:41
last_clock_read
timespec last_clock_read
Definition: rt_os-posix.cpp:180
posix_bounce_info_t::arg
void * arg
Definition: rt_os-posix.cpp:80
last_proc_time
timespec last_proc_time
Definition: rt_os-posix.cpp:181
RT::OS::setPeriod
int setPeriod(Task, long long)
Definition: rt_os-posix.cpp:152
posix_task_t
Definition: rt_os-posix.cpp:37
RT::OS::getCpuUsage
double getCpuUsage(void)
Definition: rt_os-posix.cpp:183
rt.h
RT::OS::shutdown
void shutdown(void)
Definition: rt_os-posix.cpp:71
posix_bounce_info_t::sem
sem_t sem
Definition: rt_os-posix.cpp:81
RT::OS::initiate
int initiate(void)
Definition: rt_os-posix.cpp:47
debug.h