Side Effects in ISRs and Signal Handlers Confuse Optimizer

Last reviewed: July 17, 1997
Article ID: Q44723
6.00 6.00a 6.00ax 7.00 | 6.00 6.00a | 1.00 1.50
MS-DOS                 | OS/2       | WINDOWS
kbtool

The information in this article applies to:

  • The Microsoft C/C++ Compiler (CL.EXE) included with:

        - Microsoft C for MS-DOS, versions 6.0, 6.0a, and 6.0ax
        - Microsoft C for OS/2, versions 6.0 and 6.0a
        - Microsoft C/C++ for MS-DOS, versions 7.0
        - Microsoft Visual C++ for Windows, versions 1.0 and 1.5
    

SUMMARY

It can be dangerous to allow the Microsoft C compiler to perform loop optimization on code that contains global variables that may be modified in interrupt service routines (ISR) or signal handlers. For example, consider the following code

   int TimerCount = 1000;

   while( TimerCount );
   printf( "Timer expired." );

where an ISR is concurrently executing the following:

   void interrupt far ISR()
   {
       TimerCount--;
   }

MORE INFORMATION

This is acceptable code and performs a simple task--it waits for a global timer variable to reach 0, indicating that the ISR has been executed a specified number of times. However, the loop optimization optionally performed by the compiler results in the while() loop being completely removed from the executable code. Because the compiler does not know that the ISR is simultaneously accessing TimerCount, it sees no reason to keep an expression that obviously evaluates to true and does nothing but waste time. This is NOT a problem with the compiler. Section 2.1.2.3 of the 7 December 1988 ANSI C draft standard states the following:

   An actual implementation need not evaluate part of an expression
   if it can deduce that its value is not used and that no needed
   side effects are produced (including any caused by calling a
   function or accessing a volatile object).

Because C 5.1 does not semantically implement the "volatile" keyword, there is no way to indicate that TimerCount is volatile and that the expression involving TimerCount should not be removed from the program by the optimizer. Thus, it is reasonable for the compiler to assume that this expression is not necessary and may be safely removed. With C versions 6.0 and later, the volatile keyword has been implemented and can be used to solve this problem.

When writing code for ISRs or signal handlers that expect conditions that the compiler cannot predict, care should be used in the choice of optimizations; if needed, an assembly code listing should be generated with the /Fc or /Fs /Fa switches and examined for the optimization's effect. Disabling optimization with /Od may result in slower executable programs but will prevent optimizer side effects.


Additional reference words: kbinf 1.00 1.50 6.00 6.00a 6.00ax 7.00 8.00
8.00c
KBCategory: kbtool
KBSubcategory: CLIss
Keywords : kb16bitonly


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 17, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.