|
@@ -403,9 +403,13 @@ class AwlSimServer(object): #+cdef
|
|
|
printError("Cannot set CPU affinity. "
|
|
|
"os.sched_setaffinity is not available.")
|
|
|
|
|
|
- def __setSched(self, allowRtPolicy=True):
|
|
|
+ def __setSched(self, allowRtPolicy=False, peripheral=False):
|
|
|
"""Set the scheduling policy and priority to what is set by
|
|
|
- AWLSIM_SCHED and AWLSIM_PRIO environment variable, if enable==True.
|
|
|
+ AWLSIM_SCHED and AWLSIM_PRIO environment variable.
|
|
|
+ If allowRtPolicy is False, then don't allow any realtime policy
|
|
|
+ and fall back to non-realtime.
|
|
|
+ If peripheral is True, then don't allow policies unsuitable for
|
|
|
+ peripheral threads. Fall back to sane alternatives.
|
|
|
"""
|
|
|
self.__rtSchedEnabled = False
|
|
|
|
|
@@ -413,19 +417,31 @@ class AwlSimServer(object): #+cdef
|
|
|
if (sched is not None and
|
|
|
sched != AwlSimEnv.SCHED_DEFAULT):
|
|
|
if not allowRtPolicy:
|
|
|
+ # Realtime is not allowed.
|
|
|
+ # Fall back to NORMAL.
|
|
|
sched = AwlSimEnv.SCHED_NORMAL
|
|
|
policy = None
|
|
|
if sched == AwlSimEnv.SCHED_NORMAL:
|
|
|
policy = getattr(os, "SCHED_OTHER", None)
|
|
|
isRealtime = False
|
|
|
elif sched == AwlSimEnv.SCHED_FIFO:
|
|
|
- policy = getattr(os, "SCHED_FIFO", None)
|
|
|
+ if peripheral:
|
|
|
+ # No FIFO for peripheral threads.
|
|
|
+ # Use RR instead.
|
|
|
+ policy = getattr(os, "SCHED_RR", None)
|
|
|
+ else:
|
|
|
+ policy = getattr(os, "SCHED_FIFO", None)
|
|
|
isRealtime = True
|
|
|
elif sched == AwlSimEnv.SCHED_RR:
|
|
|
policy = getattr(os, "SCHED_RR", None)
|
|
|
isRealtime = True
|
|
|
elif sched == AwlSimEnv.SCHED_DEADLINE:
|
|
|
- policy = getattr(os, "SCHED_DEADLINE", None)
|
|
|
+ if peripheral:
|
|
|
+ # No DEADLINE for peripheral threads.
|
|
|
+ # Use RR instead.
|
|
|
+ policy = getattr(os, "SCHED_RR", None)
|
|
|
+ else:
|
|
|
+ policy = getattr(os, "SCHED_DEADLINE", None)
|
|
|
isRealtime = True
|
|
|
policy = None #TODO we also need to set the deadline scheduling parameters.
|
|
|
if policy is None: #@nocov
|
|
@@ -527,67 +543,94 @@ class AwlSimServer(object): #+cdef
|
|
|
# We are exiting. Cannot set another state.
|
|
|
return
|
|
|
|
|
|
- if runstate == self.STATE_RUN or\
|
|
|
- runstate == self.STATE_STOP:
|
|
|
- # Reset instruction state dump.
|
|
|
- self.__insnSerial = 0
|
|
|
- for client in self.__clients:
|
|
|
- for insnStateDump in dictValues(client.insnStateDump):
|
|
|
- insnStateDump.msgs = []
|
|
|
-
|
|
|
- if runstate == self._STATE_INIT:
|
|
|
- # We just entered initialization state.
|
|
|
- printVerbose("Putting CPU into INIT state.")
|
|
|
- self.__setSched(False)
|
|
|
- self.__needOB10x = True
|
|
|
- elif runstate == self.STATE_RUN:
|
|
|
- # We just entered RUN state.
|
|
|
- self.__setSched(True)
|
|
|
- self.__startupTimeStamp = monotonic_time()
|
|
|
- if self.__needOB10x:
|
|
|
- printVerbose("CPU startup (OB 10x).")
|
|
|
- self.__sim.startup()
|
|
|
- self.__needOB10x = False
|
|
|
- printVerbose("Putting CPU into RUN state.")
|
|
|
- elif runstate == self.STATE_STOP:
|
|
|
- # We just entered STOP state.
|
|
|
- printVerbose("Putting CPU into STOP state.")
|
|
|
- self.__setSched(False)
|
|
|
- elif runstate == self.STATE_MAINTENANCE:
|
|
|
- # We just entered MAINTENANCE state.
|
|
|
- printVerbose("Putting CPU into MAINTENANCE state.")
|
|
|
- self.__setSched(False)
|
|
|
- self.__needOB10x = True
|
|
|
- else:
|
|
|
- self.__setSched(False)
|
|
|
-
|
|
|
- # Select garbage collection mode.
|
|
|
- if self.__gc_collect and self.__gc_get_count:
|
|
|
- # If we are in RUN state with realtime scheduling,
|
|
|
- # use manual garbage collection.
|
|
|
- gcMode = AwlSimEnv.getGcMode()
|
|
|
- wantManual = (gcMode == AwlSimEnv.GCMODE_MANUAL or
|
|
|
- (gcMode == AwlSimEnv.GCMODE_RT and
|
|
|
- self.__rtSchedEnabled))
|
|
|
- if runstate == self.STATE_RUN and wantManual:
|
|
|
- # Manual GC
|
|
|
- gc.disable()
|
|
|
- self.__gcManual = True
|
|
|
- self.__gcTriggerCounter = 0
|
|
|
- printVerbose("Switched to MANUAL garbage collection.")
|
|
|
+ try:
|
|
|
+ if runstate == self.STATE_RUN or\
|
|
|
+ runstate == self.STATE_STOP:
|
|
|
+ # Reset instruction state dump.
|
|
|
+ self.__insnSerial = 0
|
|
|
+ for client in self.__clients:
|
|
|
+ for insnStateDump in dictValues(client.insnStateDump):
|
|
|
+ insnStateDump.msgs = []
|
|
|
+
|
|
|
+ if runstate == self._STATE_INIT:
|
|
|
+ # We just entered initialization state.
|
|
|
+ printVerbose("Putting CPU into INIT state.")
|
|
|
+ self.__setSched(allowRtPolicy=False)
|
|
|
+ self.__needOB10x = True
|
|
|
+ elif runstate == self.STATE_RUN:
|
|
|
+ # We just entered RUN state.
|
|
|
+ self.__startupTimeStamp = monotonic_time()
|
|
|
+ if self.__needOB10x:
|
|
|
+ printVerbose("CPU startup (OB 10x).")
|
|
|
+
|
|
|
+ # In case the hardware module spawns some threads make sure these
|
|
|
+ # inherit the affinity set and sched policy for peripherals.
|
|
|
+ self.__setAffinity(core=False)
|
|
|
+ self.__setSched(allowRtPolicy=True,
|
|
|
+ peripheral=True)
|
|
|
+ try:
|
|
|
+ # Start the hardware modules.
|
|
|
+ self.__sim.hardwareStartup()
|
|
|
+ finally:
|
|
|
+ # Go back to core affinity mask and sched policy.
|
|
|
+ self.__setAffinity(core=True)
|
|
|
+ self.__setSched(allowRtPolicy=True,
|
|
|
+ peripheral=False)
|
|
|
+
|
|
|
+ # Run the CPU statup and the CPU statup OBs.
|
|
|
+ self.__sim.startup()
|
|
|
+ self.__needOB10x = False
|
|
|
+ else:
|
|
|
+ # Set core sched policy.
|
|
|
+ self.__setSched(allowRtPolicy=True,
|
|
|
+ peripheral=False)
|
|
|
+ printVerbose("Putting CPU into RUN state.")
|
|
|
+ elif runstate == self.STATE_STOP:
|
|
|
+ # We just entered STOP state.
|
|
|
+ printVerbose("Putting CPU into STOP state.")
|
|
|
+ self.__setSched(allowRtPolicy=False)
|
|
|
+ elif runstate == self.STATE_MAINTENANCE:
|
|
|
+ # We just entered MAINTENANCE state.
|
|
|
+ self.__setSched(allowRtPolicy=False)
|
|
|
+ self.__needOB10x = True
|
|
|
+ else:
|
|
|
+ self.__setSched(allowRtPolicy=False)
|
|
|
+
|
|
|
+
|
|
|
+ # Select garbage collection mode.
|
|
|
+ if self.__gc_collect and self.__gc_get_count:
|
|
|
+ # If we are in RUN state with realtime scheduling,
|
|
|
+ # use manual garbage collection.
|
|
|
+ gcMode = AwlSimEnv.getGcMode()
|
|
|
+ wantManual = (gcMode == AwlSimEnv.GCMODE_MANUAL or
|
|
|
+ (gcMode == AwlSimEnv.GCMODE_RT and
|
|
|
+ self.__rtSchedEnabled))
|
|
|
+ if runstate == self.STATE_RUN and wantManual:
|
|
|
+ # Manual GC
|
|
|
+ gc.disable()
|
|
|
+ self.__gcManual = True
|
|
|
+ self.__gcTriggerCounter = 0
|
|
|
+ printVerbose("Switched to MANUAL garbage collection.")
|
|
|
+ else:
|
|
|
+ # Automatic GC
|
|
|
+ gc.enable()
|
|
|
+ self.__gcManual = False
|
|
|
+ printVerbose("Switched to AUTO garbage collection.")
|
|
|
else:
|
|
|
- # Automatic GC
|
|
|
- gc.enable()
|
|
|
+ # Manual GC control is not available.
|
|
|
self.__gcManual = False
|
|
|
printVerbose("Switched to AUTO garbage collection.")
|
|
|
- else:
|
|
|
- # Manual GC control is not available.
|
|
|
- self.__gcManual = False
|
|
|
- printVerbose("Switched to AUTO garbage collection.")
|
|
|
|
|
|
- self.__state = runstate
|
|
|
- # Make a shortcut variable for RUN
|
|
|
- self.__running = bool(runstate == self.STATE_RUN)
|
|
|
+
|
|
|
+ self.__state = runstate
|
|
|
+ # Make a shortcut variable for RUN
|
|
|
+ self.__running = bool(runstate == self.STATE_RUN)
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ # An exception occurred. Go back to normal scheduling.
|
|
|
+ with suppressAllExc:
|
|
|
+ self.__setSched(allowRtPolicy=False)
|
|
|
+ raise e
|
|
|
|
|
|
def __getMnemonics(self):
|
|
|
return self.__sim.cpu.getConf().getMnemonics()
|
|
@@ -899,13 +942,13 @@ class AwlSimServer(object): #+cdef
|
|
|
return srcManager
|
|
|
|
|
|
def loadHardwareModule(self, hwmodDesc):
|
|
|
- hwmodName = hwmodDesc.getModuleName()
|
|
|
- printInfo("Loading hardware module '%s'..." % hwmodName)
|
|
|
-
|
|
|
# In case the hardware module spawns some threads make sure these
|
|
|
# inherit the affinity set for peripherals.
|
|
|
self.__setAffinity(core=False)
|
|
|
try:
|
|
|
+ hwmodName = hwmodDesc.getModuleName()
|
|
|
+ printInfo("Loading hardware module '%s'..." % hwmodName)
|
|
|
+
|
|
|
hwClass = self.__sim.loadHardwareModule(hwmodDesc.getModuleName())
|
|
|
self.__sim.registerHardwareClass(hwClass=hwClass,
|
|
|
parameters=hwmodDesc.getParameters())
|
|
@@ -1280,39 +1323,43 @@ class AwlSimServer(object): #+cdef
|
|
|
reply.setReplyTo(msg)
|
|
|
client.transceiver.send(reply)
|
|
|
|
|
|
+ # Message receive control flags.
|
|
|
+ RXFLG_NONE = 0 # No flags
|
|
|
+ RXFLG_EXFATAL = 1 << 0 # AwlSimError exceptions are fatal
|
|
|
+
|
|
|
__msgRxHandlers = {
|
|
|
- AwlSimMessage.MSG_ID_PING : __rx_PING,
|
|
|
- AwlSimMessage.MSG_ID_PONG : __rx_PONG,
|
|
|
- AwlSimMessage.MSG_ID_RESET : __rx_RESET,
|
|
|
- AwlSimMessage.MSG_ID_SHUTDOWN : __rx_SHUTDOWN,
|
|
|
- AwlSimMessage.MSG_ID_RUNSTATE : __rx_RUNSTATE,
|
|
|
- AwlSimMessage.MSG_ID_GET_RUNSTATE : __rx_GET_RUNSTATE,
|
|
|
- AwlSimMessage.MSG_ID_GET_AWLSRC : __rx_GET_AWLSRC,
|
|
|
- AwlSimMessage.MSG_ID_AWLSRC : __rx_AWLSRC,
|
|
|
- AwlSimMessage.MSG_ID_GET_SYMTABSRC : __rx_GET_SYMTABSRC,
|
|
|
- AwlSimMessage.MSG_ID_SYMTABSRC : __rx_SYMTABSRC,
|
|
|
- AwlSimMessage.MSG_ID_HWMOD : __rx_HWMOD,
|
|
|
- AwlSimMessage.MSG_ID_LIBSEL : __rx_LIBSEL,
|
|
|
- AwlSimMessage.MSG_ID_GET_FUPSRC : __rx_GET_FUPSRC,
|
|
|
- AwlSimMessage.MSG_ID_FUPSRC : __rx_FUPSRC,
|
|
|
-# AwlSimMessage.MSG_ID_GET_KOPSRC : __rx_GET_KOPSRC,
|
|
|
-# AwlSimMessage.MSG_ID_KOPSRC : __rx_KOPSRC,
|
|
|
- AwlSimMessage.MSG_ID_BUILD : __rx_BUILD,
|
|
|
- AwlSimMessage.MSG_ID_REMOVESRC : __rx_REMOVESRC,
|
|
|
- AwlSimMessage.MSG_ID_REMOVEBLK : __rx_REMOVEBLK,
|
|
|
-# AwlSimMessage.MSG_ID_GET_OPT : __rx_GET_OPT,
|
|
|
- AwlSimMessage.MSG_ID_OPT : __rx_OPT,
|
|
|
- AwlSimMessage.MSG_ID_GET_BLOCKINFO : __rx_GET_BLOCKINFO,
|
|
|
- AwlSimMessage.MSG_ID_GET_CPUSPECS : __rx_GET_CPUSPECS,
|
|
|
- AwlSimMessage.MSG_ID_CPUSPECS : __rx_CPUSPECS,
|
|
|
- AwlSimMessage.MSG_ID_GET_CPUCONF : __rx_GET_CPUCONF,
|
|
|
- AwlSimMessage.MSG_ID_CPUCONF : __rx_CPUCONF,
|
|
|
- AwlSimMessage.MSG_ID_REQ_MEMORY : __rx_REQ_MEMORY,
|
|
|
- AwlSimMessage.MSG_ID_MEMORY : __rx_MEMORY,
|
|
|
- AwlSimMessage.MSG_ID_INSNSTATE_CONFIG : __rx_INSNSTATE_CONFIG,
|
|
|
- AwlSimMessage.MSG_ID_GET_IDENTS : __rx_GET_IDENTS,
|
|
|
-# AwlSimMessage.MSG_ID_GET_CPUDUMP : __rx_GET_CPUDUMP,
|
|
|
- AwlSimMessage.MSG_ID_GET_CPUSTATS : __rx_GET_CPUSTATS,
|
|
|
+ AwlSimMessage.MSG_ID_PING : (__rx_PING, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_PONG : (__rx_PONG, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_RESET : (__rx_RESET, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_SHUTDOWN : (__rx_SHUTDOWN, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_RUNSTATE : (__rx_RUNSTATE, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_GET_RUNSTATE : (__rx_GET_RUNSTATE, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_GET_AWLSRC : (__rx_GET_AWLSRC, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_AWLSRC : (__rx_AWLSRC, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_GET_SYMTABSRC : (__rx_GET_SYMTABSRC, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_SYMTABSRC : (__rx_SYMTABSRC, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_HWMOD : (__rx_HWMOD, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_LIBSEL : (__rx_LIBSEL, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_GET_FUPSRC : (__rx_GET_FUPSRC, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_FUPSRC : (__rx_FUPSRC, RXFLG_EXFATAL),
|
|
|
+# AwlSimMessage.MSG_ID_GET_KOPSRC : (__rx_GET_KOPSRC, RXFLG_NONE),
|
|
|
+# AwlSimMessage.MSG_ID_KOPSRC : (__rx_KOPSRC, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_BUILD : (__rx_BUILD, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_REMOVESRC : (__rx_REMOVESRC, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_REMOVEBLK : (__rx_REMOVEBLK, RXFLG_EXFATAL),
|
|
|
+# AwlSimMessage.MSG_ID_GET_OPT : (__rx_GET_OPT, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_OPT : (__rx_OPT, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_GET_BLOCKINFO : (__rx_GET_BLOCKINFO, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_GET_CPUSPECS : (__rx_GET_CPUSPECS, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_CPUSPECS : (__rx_CPUSPECS, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_GET_CPUCONF : (__rx_GET_CPUCONF, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_CPUCONF : (__rx_CPUCONF, RXFLG_EXFATAL),
|
|
|
+ AwlSimMessage.MSG_ID_REQ_MEMORY : (__rx_REQ_MEMORY, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_MEMORY : (__rx_MEMORY, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_INSNSTATE_CONFIG : (__rx_INSNSTATE_CONFIG, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_GET_IDENTS : (__rx_GET_IDENTS, RXFLG_NONE),
|
|
|
+# AwlSimMessage.MSG_ID_GET_CPUDUMP : (__rx_GET_CPUDUMP, RXFLG_NONE),
|
|
|
+ AwlSimMessage.MSG_ID_GET_CPUSTATS : (__rx_GET_CPUSTATS, RXFLG_NONE),
|
|
|
}
|
|
|
|
|
|
def __clientCommTransferError(self, exception, client):
|
|
@@ -1327,6 +1374,7 @@ class AwlSimServer(object): #+cdef
|
|
|
self.__clientRemove(client)
|
|
|
|
|
|
def __handleClientComm(self, client): #+cdef
|
|
|
+ flags = self.RXFLG_EXFATAL
|
|
|
try:
|
|
|
msg = client.transceiver.receive(0.0)
|
|
|
if not msg:
|
|
@@ -1335,13 +1383,13 @@ class AwlSimServer(object): #+cdef
|
|
|
printInfo("Received unsupported "
|
|
|
"message 0x%02X" % msg.msgId)
|
|
|
return
|
|
|
- handler = self.__msgRxHandlers[msg.msgId]
|
|
|
+ handler, flags = self.__msgRxHandlers[msg.msgId]
|
|
|
handler(self, client, msg)
|
|
|
except AwlSimError as e:
|
|
|
- # Communication error. Just log it.
|
|
|
- # We don't forward this error to the main loop.
|
|
|
- printError(e.getReport())
|
|
|
- return
|
|
|
+ if not (flags & self.RXFLG_EXFATAL):
|
|
|
+ # Just report this nonfatal exception.
|
|
|
+ e.setReportOnlyFlag(True)
|
|
|
+ raise e
|
|
|
except TransferError as e:
|
|
|
self.__clientCommTransferError(e, client)
|
|
|
return
|
|
@@ -1613,17 +1661,21 @@ class AwlSimServer(object): #+cdef
|
|
|
printVerbose("Main loop exception: %s" % (
|
|
|
e.getMessage()))
|
|
|
|
|
|
- # Stop the CPU
|
|
|
- self.setRunState(self.STATE_STOP)
|
|
|
- # Schedule a CPU restart/rebuild.
|
|
|
- self.__needOB10x = True
|
|
|
+ if not e.getReportOnlyFlag():
|
|
|
+ # Stop the CPU
|
|
|
+ self.setRunState(self.STATE_STOP)
|
|
|
+ # Schedule a CPU restart/rebuild.
|
|
|
+ self.__needOB10x = True
|
|
|
|
|
|
# Try to add more information to the exception.
|
|
|
self.__extendAwlSimError(e)
|
|
|
|
|
|
if self.__handleExceptionServerside:
|
|
|
# Let the server handle the exception
|
|
|
- raise e
|
|
|
+ if e.getReportOnlyFlag():
|
|
|
+ printError(e.getReport())
|
|
|
+ else:
|
|
|
+ raise e
|
|
|
else:
|
|
|
# Send the exception to all clients.
|
|
|
msg = AwlSimMessage_EXCEPTION(e)
|