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