MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
rtaisolver.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/rtaisolver.cc,v 1.20 2017/01/12 14:46:10 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
33 
34 
35 #include "mbdefs.h"
36 #include "solver.h"
37 #include "solver_impl.h"
38 #include "rtaisolver.h"
39 
40 #include "mbrtai_utils.h"
41 
42 // RTAI log message
43 struct mbrtai_msg_t {
44  int step;
45  int time;
46 } msg;
47 
48 /* RTAISolver - begin */
49 
51  RTMode eRTMode,
52  long long lRTPeriod,
53  unsigned long RTStackSize,
54  bool bRTAllowNonRoot,
55  int RTCpuMap,
56  bool bRTHard,
57  bool bRTlog,
58  const std::string& LogProcName)
59 : RTSolverBase(pS, eRTMode, lRTPeriod,
60  RTStackSize, bRTAllowNonRoot, RTCpuMap),
61 bRTHard(bRTHard),
62 bRTlog(bRTlog),
63 LogProcName(LogProcName),
64 lRTPeriod(lRTPeriod),
65 RTSemPtr_in(0),
66 RTSemPtr_out(0),
67 mbxlog(0),
68 RTStpFlag(0),
69 t_tot(0),
70 t0(0),
71 t1(0),
72 or_counter(0)
73 {
74  ASSERT(lRTPeriod > 0);
75  ASSERT(!bRTlog || !LogProcName.empty());
76 }
77 
79 {
80  if (mbxlog) {
81  rtmbdyn_rt_mbx_delete(&mbxlog);
82  mbxlog = 0;
83  }
84 }
85 
86 // write contribution to restart file
87 std::ostream&
88 RTAISolver::Restart(std::ostream& out) const
89 {
90  out << "RTAI";
91 
92  out << ", reserve stack, " << RTStackSize;
93 
94  out << ", mode, ";
95  switch (eRTMode) {
97  out << "period, time step, " << lRTPeriod;
98  break;
99 
101  out << "semaphore";
102  break;
103 
104  default:
106  }
107 
108  if (bRTAllowNonRoot) {
109  out << ", allow nonroot";
110  }
111 
112  if (RTCpuMap != 0xFF) {
113  out << ", cpu map, " << RTCpuMap;
114  }
115 
116  if (bRTHard) {
117  out << ", hard realtime";
118  }
119 
120  if (bRTlog) {
121  out << ", realtime log, \"" << LogProcName << "\"";
122  }
123 
124  return out;
125 }
126 
127 // very first setup, to be always performed
128 void
130 {
131  if (bRTAllowNonRoot) {
132  rtmbdyn_rt_allow_nonroot_hrt();
133  }
134 
135  ASSERT(::rtmbdyn_rtai_task == 0);
136 
137  /* Init RTAI; if init'ed, it will be shut down at exit */
138  if (rtmbdyn_rt_task_init("MBDTSK", 1, 0, 0, RTCpuMap,
139  &::rtmbdyn_rtai_task))
140  {
141  silent_cerr("RTAISolver: unable to init RTAI task" << std::endl);
143  }
144 }
145 
146 // initialization to be performed only if real-time is requested
147 void
149 {
150  /* Need timer */
151  if (!rtmbdyn_rt_is_hard_timer_running()) {
152  /* FIXME: ??? */
153  silent_cout("RTAISolver: Hard timer is started by MBDyn"
154  << std::endl);
155  rtmbdyn_rt_set_oneshot_mode();
156  rtmbdyn_start_rt_timer(rtmbdyn_nano2count(1000000));
157  }
158 
159  /*
160  * MBDyn can work in two ways:
161  * - internal timer
162  * - scheduled by an external signal
163  * only the first case is currently implemented
164  */
165  if (RTWaitPeriod()) {
166  long long t = rtmbdyn_rt_get_time();
167  int r;
168 
169  /* Timer should be init'ed */
170  ASSERT(t > 0);
171 
172  silent_cout("RTAISolver: Task: " << ::rtmbdyn_rtai_task
173  << "; time: " << t
174  << "; period: " << lRTPeriod
175  << std::endl);
176 
177  // NOTE: the period was in nanoseconds until now.
178  lRTPeriod = rtmbdyn_nano2count(lRTPeriod);
179 
180  r = rtmbdyn_rt_task_make_periodic(::rtmbdyn_rtai_task,
181  t, lRTPeriod);
182 
183  if (r) {
184  silent_cerr("RTAISolver: "
185  "rtmbdyn_rt_task_make_periodic() failed "
186  "(" << r << ")" << std::endl);
188  }
189 
190 #if 0
191  } else if (RTSemWait()) {
192  int r;
193 
194  /* FIXME: check args
195  * name should be configurable?
196  * initial value 0: non-blocking
197  */
198  r = rtmbdyn_rt_sem_init("MBDSMI", 0, &RTSemPtr_in);
199  if (r) {
200  silent_cerr("rt_sem_init() failed ("
201  << r << ")" << std::endl);
203  }
204 
205  /* FIXME: check args
206  * name should be configurable?
207  * initial value 0: non-blocking
208  */
209  r = rtmbdyn_rt_sem_init("MBDSMO", 0, &RTSemPtr_out);
210  if (r) {
211  silent_cerr("rt_sem_init() failed ("
212  << r << ")" << std::endl);
214  }
215 #endif
216  }
217 
218  /* FIXME: should check whether RTStackSize is correctly set? */
219  if (bRTlog) {
220  silent_cout("RTAISolver: MBDyn starts overruns monitor "
221  "(proc: \"" << LogProcName << "\")"
222  << std::endl);
223 
224  const char *mbxlogname = "logmb";
225  if (rtmbdyn_rt_mbx_init(mbxlogname, sizeof(msg)*16, &mbxlog)) {
226  bRTlog = false;
227  silent_cerr("RTAISolver: cannot init log mailbox "
228  "\"" << mbxlogname << "\""
229  << std::endl);
230 
231  } else {
232  const char *nonroot =
233  bRTAllowNonRoot ? "TRUE" : "FALSE";
234 
235  switch (fork()) {
236  case 0: {
237  char LogCpuMap[] = "0xFF";
238 
239  if (RTCpuMap != 0xFF) {
240  /* MBDyn can use any cpu
241  * The overruns monitor will use any free cpu */
242  snprintf(LogCpuMap, sizeof(LogCpuMap),
243  "0x%02X", ~RTCpuMap);
244  }
245 
246  if (strcmp(LogProcName.c_str(), "logproc") != 0) {
247  if (execl(LogProcName.c_str(), LogProcName.c_str(),
248  "MBDTSK", mbxlogname,
249  LogCpuMap, nonroot, NULL) == 0)
250  {
251  break;
252  }
253 
254  /* error */
255  silent_cout("RTAISolver: cannot start "
256  "log procedure "
257  "\"" << LogProcName << "\"; "
258  "using default" << std::endl);
259  }
260 
261 #ifdef HAVE_SETENV
262  /* sets new path */
263  /* BINPATH is the ${bindir} variable
264  * at configure time, defined in
265  * include/mbdefs.h.in */
266  char *origpath = getenv("PATH");
267  if (origpath == 0) {
268  /* ?!? */
269  setenv("PATH", ".:" BINPATH, 1);
270 
271  } else {
272  std::string newpath = ".:" BINPATH ":";
273  newpath += origpath;
274  setenv("PATH", newpath.c_str(), 1);
275  }
276 #endif // HAVE_SETENV
277 
278  /* start logger */
279  if (execlp("logproc", "logproc", "MBDTSK",
280  mbxlogname, LogCpuMap, nonroot, NULL)
281  == -1)
282  {
283  silent_cout("RTAISolver: cannot start default "
284  "log procedure \"logproc\""
285  << std::endl);
286  /* FIXME: better give up logging? */
287  bRTlog = false;
288  }
289  break;
290  }
291 
292  case -1:
293  silent_cerr("Cannot init log procedure" << std::endl);
294  bRTlog = false;
295  break;
296 
297  default:
298  rtmbdyn_rt_sleep(rtmbdyn_nano2count(1000000000));
299  break;
300  }
301  }
302  }
303 
305 }
306 
307 // check whether stop is commanded by real-time
308 bool
310 {
311  if (RTStpFlag == 1) {
312  StopCommanded();
313  }
314 
315  return (RTStpFlag != 0);
316 }
317 
318 // to be performed when stop is commanded by someone else
319 void
321 {
322  if (bRTHard) {
323  rtmbdyn_rt_make_soft_real_time();
324  }
325 }
326 
327 // write real-time related message when stop commanded by someone else
328 void
330 {
331  silent_cout("total overruns: " << or_counter << std::endl
332  << "total overrun time: " << t_tot << " micros" << std::endl);
333 }
334 
335 // wait for period to expire
336 void
338 {
339  rtmbdyn_rt_receive_if(NULL, &RTStpFlag);
340 
341  t1 = rtmbdyn_rt_get_time();
342  if (RTSteps >= 2 && t1 > (t0 + lRTPeriod)) {
343  or_counter++;
344  t_tot = t_tot + rtmbdyn_count2nano(t1 - t0 - lRTPeriod)/1000;
345 
346  if (bRTlog) {
347  msg.step = RTSteps;
348  msg.time = (int)rtmbdyn_count2nano(t1 - t0 - lRTPeriod)/1000;
349 
350  rtmbdyn_RT_mbx_send_if(0, 0, mbxlog, &msg, sizeof(msg));
351  }
352  }
353 
354  if (RTWaitPeriod()) {
355  rtmbdyn_rt_task_wait_period();
356 
357 #if 0
358  } else if (RTSemWait()) {
359  /* FIXME: semaphore must be configurable */
360  mbdyn_rt_sem_wait(RTSemPtr_in);
361 #endif
362  } /* else RTBlockingIO(): do nothing */
363 
364  t0 = rtmbdyn_rt_get_time();
365 
366  if (RTSteps == 2 && bRTHard) {
367  /* make hard real time */
368  rtmbdyn_rt_make_hard_real_time();
369  }
370 
371  RTSteps++;
372 }
373 
374 /* RTAISolver - end */
375 
376 RTSolverBase *
378 {
379  RTSolverBase::RTMode eRTMode;
380  unsigned long lRTPeriod;
381  unsigned long RTStackSize;
382  bool bRTAllowNonRoot;
383  int RTCpuMap;
384  ReadRTParams(pS, HP, eRTMode, lRTPeriod, RTStackSize, bRTAllowNonRoot, RTCpuMap);
385 
386  bool bRTHard = false;
387  if (HP.IsKeyWord("hard" "real" "time")) {
388  bRTHard = true;
389  }
390 
391  bool bRTlog(false);
392  std::string LogProcName;
393  if (HP.IsKeyWord("real" "time" "log")) {
394  if (HP.IsKeyWord("file" "name")){
395  const char *m = HP.GetFileName();
396  if (m == 0) {
397  silent_cerr("RTAISolver: unable to get "
398  "log process name (\"file name\") "
399  "at line " << HP.GetLineData()
400  << std::endl);
402  }
403  LogProcName = m;
404 
405  } else {
406  // built-in log process
407  LogProcName = "logproc";
408  }
409 
410  bRTlog = true;
411  }
412 
413  RTSolverBase *pRTSolver(0);
415  RTAISolver(pS, eRTMode, lRTPeriod,
416  RTStackSize, bRTAllowNonRoot, RTCpuMap,
417  bRTHard, bRTlog, LogProcName));
418 
419  return pRTSolver;
420 }
421 
void * RTSemPtr_in
Definition: rtaisolver.h:48
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
~RTAISolver(void)
Definition: rtaisolver.cc:78
virtual void Init(void)
Definition: rtsolver.cc:69
unsigned long RTStackSize
Definition: rtsolver.h:59
void Init(void)
Definition: rtaisolver.cc:148
virtual const char * GetFileName(enum Delims Del=DEFAULTDELIM)
Definition: parsinc.cc:673
void Wait(void)
Definition: rtaisolver.cc:337
RTSolverBase * ReadRTAISolver(Solver *pS, MBDynParser &HP)
Definition: rtaisolver.cc:377
void * mbxlog
Definition: rtaisolver.h:51
long long lRTPeriod
Definition: rtaisolver.h:45
virtual bool IsKeyWord(const char *sKeyWord)
Definition: parser.cc:910
volatile int RTSteps
Definition: rtsolver.h:75
bool RTSemWait(void) const
Definition: rtsolver.h:69
bool RTWaitPeriod(void) const
Definition: rtsolver.h:65
void StopCommanded(void)
Definition: rtaisolver.cc:320
void Setup(void)
Definition: rtaisolver.cc:129
long long t0
Definition: rtaisolver.h:54
RTMode eRTMode
Definition: rtsolver.h:54
#define ASSERT(expression)
Definition: colamd.c:977
RTAISolver(Solver *pS, RTMode eRTMode, long long lRTPeriod, unsigned long RTStackSize, bool bRTAllowNonRoot, int RTCpuMap, bool bRTHard, bool bRTlog, const std::string &LogProcName)
Definition: rtaisolver.cc:50
#define SAFENEWWITHCONSTRUCTOR(pnt, item, constructor)
Definition: mynewmem.h:698
void ReadRTParams(Solver *pS, MBDynParser &HP, RTSolverBase::RTMode &eRTMode, unsigned long &lRTPeriod, unsigned long &RTStackSize, bool &bRTAllowNonRoot, int &RTCpuMap)
Definition: rtsolver.cc:89
bool bRTHard
Definition: rtaisolver.h:41
const std::string LogProcName
Definition: rtaisolver.h:43
Definition: solver.h:78
std::ostream & Restart(std::ostream &out) const
Definition: rtaisolver.cc:88
struct mbrtai_msg_t msg
void * RTSemPtr_out
Definition: rtaisolver.h:49
int or_counter
Definition: rtaisolver.h:55
int RTCpuMap
Definition: rtsolver.h:61
bool IsStopCommanded(void)
Definition: rtaisolver.cc:309
int RTStpFlag
Definition: rtaisolver.h:52
bool bRTlog
Definition: rtaisolver.h:42
virtual HighParser::ErrOut GetLineData(void) const
Definition: parsinc.cc:697
void Log(void)
Definition: rtaisolver.cc:329
bool bRTAllowNonRoot
Definition: rtsolver.h:60
long long t1
Definition: rtaisolver.h:54