1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/rtsolver.cc,v 1.19 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 #include "myassert.h"
35 #include "solver.h"
36 #include "solver_impl.h"
37 #include "rtsolver.h"
38 #include "rtaisolver.h"
39 #include "rtposixsolver.h"
40 extern "C" { int get_nprocs_conf(void); int get_nprocs(void); }
41
42 extern "C" {int get_nprocs(void);}
43
44 /* RTSolverBase - begin */
45
RTSolverBase(Solver * pS,RTMode eRTMode,unsigned long lRTPeriod,unsigned long RTStackSize,bool bRTAllowNonRoot,int RTCpuMap,bool bNoOutput)46 RTSolverBase::RTSolverBase(Solver *pS,
47 RTMode eRTMode,
48 unsigned long lRTPeriod,
49 unsigned long RTStackSize,
50 bool bRTAllowNonRoot,
51 int RTCpuMap,
52 bool bNoOutput)
53 : pS(pS),
54 eRTMode(eRTMode),
55 lRTPeriod(lRTPeriod),
56 RTStackSize(RTStackSize),
57 bRTAllowNonRoot(bRTAllowNonRoot),
58 RTCpuMap(RTCpuMap),
59 bNoOutput(bNoOutput)
60 {
61 ASSERT(RTStackSize > 0);
62 ASSERT(lRTPeriod > 0);
63 }
64
~RTSolverBase(void)65 RTSolverBase::~RTSolverBase(void)
66 {
67 NO_OP;
68 }
69
70 void
Init(void)71 RTSolverBase::Init(void)
72 {
73 /* if using real-time, clear out any type of output */
74 if (bNoOutput) {
75 pS->SetNoOutput();
76 }
77
78 mbdyn_reserve_stack(RTStackSize);
79 }
80
81 // check whether stop is commanded by real-time
82 bool
IsStopCommanded(void)83 RTSolverBase::IsStopCommanded(void)
84 {
85 return false;
86 }
87
88 /* RTSolverBase - end */
89
90 void
ReadRTParams(Solver * pS,MBDynParser & HP,RTSolverBase::RTMode & eRTMode,unsigned long & lRTPeriod,unsigned long & RTStackSize,bool & bRTAllowNonRoot,int & RTCpuMap)91 ReadRTParams(Solver *pS, MBDynParser& HP,
92 RTSolverBase::RTMode& eRTMode,
93 unsigned long& lRTPeriod,
94 unsigned long& RTStackSize,
95 bool& bRTAllowNonRoot,
96 int& RTCpuMap)
97 {
98 eRTMode = RTSolverBase::MBRT_UNKNOWN;
99 /* FIXME: use a safe default? */
100 if (HP.IsKeyWord("mode")) {
101 if (HP.IsKeyWord("period")) {
102 eRTMode = RTSolverBase::MBRT_WAITPERIOD;
103
104 } else if (HP.IsKeyWord("semaphore")) {
105 /* FIXME: not implemented yet ... */
106 eRTMode = RTSolverBase::MBRT_SEMAPHORE;
107
108 } else if (HP.IsKeyWord("io")) {
109 eRTMode = RTSolverBase::MBRT_IO;
110
111 } else {
112 silent_cerr("RTSolver: unknown realtime mode "
113 "at line " << HP.GetLineData()
114 << std::endl);
115 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
116 }
117 }
118
119 switch (eRTMode) {
120 case RTSolverBase::MBRT_UNKNOWN:
121 eRTMode = RTSolverBase::MBRT_WAITPERIOD;
122 silent_cerr("RTSolver: unknown realtime mode; "
123 "assuming periodic "
124 "at line " << HP.GetLineData()
125 << std::endl);
126 // fallthru
127
128 case RTSolverBase::MBRT_WAITPERIOD:
129 lRTPeriod = -1;
130 if (HP.IsKeyWord("time" "step")) {
131 long long p = HP.GetInt();
132
133 if (p <= 0) {
134 silent_cerr("RTSolver: illegal time step "
135 << p << " at line "
136 << HP.GetLineData()
137 << std::endl);
138 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
139 }
140
141 lRTPeriod = p;
142
143 } else {
144 silent_cerr("RTSolver: need a time step for real time "
145 "at line " << HP.GetLineData()
146 << std::endl);
147 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
148 }
149 break;
150
151 case RTSolverBase::MBRT_SEMAPHORE:
152 // impossible, right now
153 break;
154
155 case RTSolverBase::MBRT_IO:
156 break;
157
158 default:
159 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
160 }
161
162 RTStackSize = 1024;
163 if (HP.IsKeyWord("reserve" "stack")) {
164 long size = HP.GetInt();
165
166 if (size <= 0) {
167 silent_cerr("RTSolver: illegal stack size "
168 << size << " at line "
169 << HP.GetLineData()
170 << std::endl);
171 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
172 }
173
174 RTStackSize = size;
175 }
176
177 bRTAllowNonRoot = false;
178 if (HP.IsKeyWord("allow" "nonroot")) {
179 bRTAllowNonRoot = true;
180 }
181
182 RTCpuMap = 0xFF;
183 if (HP.IsKeyWord("cpu" "map")) {
184 #ifndef HAVE_SCHED_SETAFFINITY
185 silent_cerr("warning: \"cpu map\" unsupported (ignored)" << std::endl);
186 #endif // ! HAVE_SCHED_SETAFFINITY
187
188 int cpumap = HP.GetInt();
189 // NOTE: there is a hard limit at 4 CPU
190 int ncpu = std::min(get_nprocs(), 4);
191 int newcpumap = (2 << (ncpu - 1)) - 1;
192
193 /* i bit non legati ad alcuna cpu sono posti a zero */
194 newcpumap &= cpumap;
195 if (newcpumap < 1 || newcpumap > 0xFF) {
196 char buf[16];
197 snprintf(buf, sizeof(buf), "0x%02X", (unsigned)cpumap);
198 silent_cerr("RTSolver: illegal cpu map " << buf
199 << " at line " << HP.GetLineData()
200 << std::endl);
201 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
202 }
203 RTCpuMap = newcpumap;
204 }
205 }
206
207 RTSolverBase *
ReadRTSolver(Solver * pS,MBDynParser & HP)208 ReadRTSolver(Solver *pS, MBDynParser& HP)
209 {
210 if (HP.IsKeyWord("POSIX")) {
211 return ReadRTPOSIXSolver(pS, HP);
212 }
213
214 #ifdef USE_RTAI
215 if (!HP.IsKeyWord("RTAI")) {
216 pedantic_cerr("ReadRTSolver: missing real-time model; "
217 "assuming RTAI at line " << HP.GetLineData()
218 << std::endl);
219 }
220
221 return ReadRTAISolver(pS, HP);
222
223 #else // ! USE_RTAI
224 if (HP.IsKeyWord("RTAI")) {
225 silent_cerr("ReadRTSolver: need to configure --with-rtai "
226 "to use RTAI real-time solver "
227 "at line " << HP.GetLineData() << std::endl);
228
229 } else {
230 silent_cerr("ReadRTSolver: need to configure --with-rtai "
231 "to use default RTAI real-time solver "
232 "at line " << HP.GetLineData() << std::endl);
233 }
234
235 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
236 #endif // ! USE_RTAI
237 }
238
239 /* RTSolver - end */
240
241