Blue Screen and Stop Message Handling
By sharing a system with Windows, wRTOS enables developers to take advantage of Windows's components and services without depending on them for critical real-time tasks. Even after a blue screen (or a STOP message in Windows), the wRTOS Subsystem continues to run, and any application or driver built on wRTOS and/or TCP/IP can also continue to run.
What is a Blue Screen?
Blue Screens or STOP messages in Windows result from sanity checks that fail and call KeBugCheck to bring Windows to a controlled stop. This bug check keeps data corruption to a minimum and helps find out what went wrong with the system. All operating systems of some complexity do this type of checking and stopping. Real-time operating systems (RTOSes) typically do not do a controlled emergency stop because it is thought to be more important to keep the hardware running if possible.
Windows can call KeBugCheck for many reasons, such as a disk failing, or bad pointers being called. If the failure is not a complete hardware failure such as the CPU failing, which is rare, wRTOS will continue running even after a KeBugCheck is called. All RTSS processes continue to perform real-time tasks but can only perform real-time tasks. Since services and components provided by Windows are no longer available, the RTSS processes that need to keep running cannot call on Windows.
What happens in Windows?
When a Windows STOP is called:
- The Windows scheduler stops immediately.
- The video is switched from GUI mode to text mode.
- All non-boot processors on a dedicated machine are stopped.
- Drivers that have registered for notification of bug-check are informed.
- Windows dumps memory (optional).
- Windows reboots (optional).
Device drivers can register to be informed when a bug-check occurs. They are supposed to checkpoint state in memory so that determining the cause is easier.
Configuring wRTOS to Run after a Blue Screen
After a Blue Screen, you may want to cycle the equipment to a safe state or allow the real-time application to run for a reasonable time after Windows has bug checked.
- A shutdown handler is attached to each process that must continue to run before a blue screen. Only one shutdown handler is attached to a process, and it is created as a suspended thread that will be resumed if a blue screen occurs. The body of shutdown handler typically contains code to alert the process and its threads that a shutdown has occurred, while the main process and its threads continue to do the bulk of the processing.
- Once a shutdown occurs, wRTOS intercepts the bug check.
- Once all process with shutdown handlers unload, normal shutdown continues. You can set Windows to reboot automatically if desired.
See Shutdown Handling for additional information.
Deterministic APIs Work After Shutdown
In a real-time system, all critical tasks are handled by wRTOS, and monitoring and other tasks are handled by Windows. Making a call to Windows after a blue screen has occurred will hang the thread or process that calls it because the OS is no longer available to handle requests. Care must be taken to avoid calling APIs that wRTOS cannot directly process. In general, any API that is deterministic will work after a blue screen. However, some non-deterministic functions are designed to work after blue screen. When attaching shutdown handlers to your applications and drivers, adhere to the following:
- The wRTOS SDK help contains matrices of supported functions. Any function that is marked as being Deterministic will work.
- Functions that allocate memory will not work, such as calloc and malloc.
Note: After a memory pool has been enabled, you can allocate from it after the Windows STOP message appears until the memory pool has been used up.
- Functions that create objects will not work, including creation of threads, timers, objects, and variables. All initializations should be done before real-time processing begins, and critical initialization steps that fail should call RtReleaseShutdownHandler. If you need new threads after shutdown, you can create suspended threads or wait for some event or global variable to be triggered by the shutdown handler.
- Functions that use Windows will not work. Attaching a shutdown handler to a process that uses both wRTOS and Windows components is dangerous because any call to Windows will hang the thread or process.
- Real-time open (such as RtOpenEvent) calls will most likely work, but in rare circumstances, they may fail, so it is better to avoid such calls.
File Systems
A FAT or FAT32 file system requires a file system check after a blue screen. NTFS partitions do not require this check.
wRTOS Scenario
Attach a shutdown handler to process each process that needs to be running after the blue screen. That process and all threads created will continue after the blue screen.
Attaching a shutdown handler will keep the process and any threads created by the process running after a normal shutdown or a blue screen. wRTOS systems typically perform all initialization, memory allocation, and non-deterministic processing at the beginning of the process before time-critical processing begins. This is especially important when using shutdown handlers, because non-deterministic functions will not be accessible after a blue screen (and would hang the thread/process). You can design routines to be aware of the system's state, alerting them that a blue screen has occurred by pulsing an event, changing a variable, or using some similar technique. The main process should not close before the shutdown handler returns. This would prevent the shutdown handler from returning and hanging the process.
main()
{
BOOL bBlueScreen = FALSE;
RtCreateEvent()…
CreateThread()…
RtAttachShutdownHandler()…
Sleep(INFINITE);
// until shutdown handler returns
}
After a normal shutdown or blue screen, the shutdown handler function begins. Typically, the body of this thread alerts the process and its threads that a shutdown occurs, and their behavior changes accordingly. Once the necessary processing is completed, the shutdown handler returns. RtPulseEvent is called to notify any sleeping thread or other routine that a shutdown has occurred. You must include some mechanism that keeps the shutdown handler open until processing is complete.
ShutdownHandler()
{
// when shutdown occurs,
// pulse event
RtPulseEvent()
// or set a global variable
bBlueScreen = TRUE;
// continue other processing, but
// keep ShutdownHandler open
RtWaitForSingleObject()
}
This thread waits for an event to be triggered in the shutdown handler. Although threads cannot be created after a blue screen, you can create threads that don't begin processing until a blue screen occurs.
Thread1()
{
// wait until event is
// triggered
RtWaitForSingleObject()
// shutdown occurred,
// begin cleanup
}
Error Checking and Cleanup
It is not necessary (or possible) to close handles or destroy objects while in wRTOS Shutdown mode. Since memory can no longer be allocated, the memory used by these objects will not be needed and this kind of cleanup is not necessary. But care must be taken not to make requests to Windows, since the OS is no longer available and calls to it will hang the calling process or thread.
For cleanup, you may want to place any destructors, close handles, and exit functions after code like the following:
if (bBlueScreen==TRUE)
Sleep(INFINITE); // no destructors or process exits allowed
System Initialization
During system initialization, if a critical component cannot be initialized, you can release the shutdown handler by calling RtReleaseShutdownHandler.
if (!(hTimer = RtCreateTimer( NULL, stackSize, default TimerHandler, NULL,
RT_PRIORITY_MAX, CLOCK_FASTEST)))
{
printf("Shutdown: Error: Could not create the timer. GetLastError = %d\n", GetLastError());
RtReleaseShutdownHandler(hShutdown);
return ERROR_OCCURRED;
}