Blue Screen and Stop Message Handling

By sharing a system with Windows, RTX64 enables developers to take advantage of components and services provided by Windows without depending on those components and services for critical real-time tasks. Even after a blue screen (or a STOP message in Windows), the RTX64 subsystem continues to run, and any application or driver built on RTX64 and/or RT-TCP/IP can also continue to run.

What is a Blue Screen?

Blue Screens or STOP messages in Windows are the result of 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 more important to keep the hardware running if at all possible.

Windows can call KeBugCheck for many reasons, such as a disk failing, or bad pointers being called. Provided the failure is not a complete hardware failure such as the CPU failing, which is rare, RTX64 will continue to run 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?

In the event a Windows STOP is called:

  1. The Windows scheduler is immediately stopped
  2. The video is switched from GUI mode to text mode.
  3. All non-boot processors on a dedicated machine are stopped.
  4. Drivers that have registered for notification of bug-check are informed.
  5. Windows dumps memory (optional).
  6. 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.

Setting up RTX64 to run after blue screen

The goal is to cycle the equipment to a safe state or allow the real-time application to run for some reasonable time after Windows has bug checked.

  1. 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 released 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.
  2. Once a shutdown occurs, RTX64 intercepts the bug check.
  3. Once all process handlers 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 RTX64, 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 RTX64 cannot directly process. In general, any API that is deterministic will work after a blue screen. However, there are also some non-deterministic functions that are designed to work after blue screen, such as printf. When attaching shutdown handlers to your applications and drivers, adhere to the following:

NOTE: RTX64 supports a local memory pool that you can enable in the RTX64 Control Panel. After this memory pool has been enabled, you can make allocations from the pool after the Windows STOP message appears until the memory pool has been used up.

File Systems

A FAT or FAT32 file system requires a file system check after a blue screen. NTFS partitions do not require this check.

RTX64 Scenario

Attach a shutdown handler to process each process that needs to be running after the blue screen. That process and all threads created by that process will continue to run 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. RTX64 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 state of the system, 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 hang the process.

main()
{
    BOOL bBlueScreen = FALSE;
    RtCreateEvent()…
    CreateThread()…
    RtAttachShutdownHandler()…
    Sleep(INFINITE);
    // until shutdown handler returns
}

After 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. Here, 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 RTX64 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;
}

Related topics: