Running CFM-68K Code at Interrupt Time: Is Your Code at Risk?By Karen WenzelApple CFM Team |
CONTENTSDefining the Interrupt ProblemThe Solution Change Description Pre-emptive Thread Switchers Limitations Incompatibilities | Under 680x0 systems running older versions of the CFM-68K Runtime Enabler, CFM-68K code that ran at interrupt time could cause a system crash. That problem has been fixed in the 4.0 release of CFM-68K. This document describes that problem and details the remaining limitations with CFM-68K code and interrupts. The reader is assumed to be familiar with the chapters on the Mixed Mode Manager and the Code Fragment Manager as documented in Inside Macintosh: PowerPC System Software. Most applications will not need modification. Users will simply install the new extension and reboot to take advantage of the fix. Threaded applications that don't use the Apple Thread Manager will need modification. Threaded application writers should read this document for instructions on how to modify their code so that their application is protected from this problem. |
Defining the Interrupt ProblemUnder systems running older versions of the CFM-68K Runtime Enabler (prior to version 4.0), CFM-68K code that executes at interrupt time could trigger a system crash. This limitation on CFM-68K code existed because on 680x0 machines, CFM-68K Mixed Mode is not invoked by interrupts. Mixed Mode must be invoked every time a transition is made between the "classic-68K" and the "CFM-68K" runtime worlds. Mixed Mode plays the same role on the 68K as it does on the PowerPC. It serves as a runtime translation engine to manage transitions between the "classic" runtime world and the "native" (CFM) runtime world. This includes saving and restoring the A5 register on each transition. Any time a transition takes place between these two worlds, Mixed Mode must be invoked. Interrupts are a special situation with respect to Mixed Mode transitions. On the PowerPC, there is a tight integration of the interrupt system and Mixed Mode by an emulator. Native PowerPC code may run at interrupt time because the emulator performs the necessary Mixed Mode transitions. There is no need for an emulator on 68K machines. As such, mode switches don't take place between CFM-68K code that gets interrupted and a classic 68K interrupt handler that later gets invoked. CFM-68K code that runs at interrupt time could cause the A5 register to become invalid for classic code that executes after the interrupt. All subsequent A5-relative references (e.g., global data references) also become invalid. The following is an illustration of the sequence of events that could trigger this problem: In this example, a classic 68K application calls a routine in a CFM-68K shared library. In order to do so, it must go through Mixed Mode. The CFM-68K code installs an asynchronous callback routine (also written in CFM-68K code). The CFM-68K code gets interrupted and the interrupt handler calls the user's callback routine. The problem in this example is that a transition is made from CFM-68K to classic code (via the interrupt) without going through Mixed Mode. In certain situations, the wrong value of A5 could get propagated back to the classic 68K application, resulting in a crash. |
The SolutionThe 4.0 version of CFM-68K fixes the most common problems with CFM-68K code running at interrupt time. The behavior of Mixed Mode has been modified; it now saves additional information into the switch frame on each transition. However, some limitations still exist. Please read the Limitations section in this document for more information. What Now WorksThe 4.0 version of the CFM-68K Runtime Enabler will allow the following to be safely implemented (either wholly or partially) in CFM-68K code, all of which were previously unsupported and could cause a system crash.
For each of these five examples, this includes cases where: a. CFM-68K code is wrapped in a routine descriptor and passed to the system as one of the above interrupt time routines (e.g., as an I/O completion routine),
What Won't Work
There are several limitations that were in the previous versions of CFM-68K and remain limitations in the 4.0 version of CFM-68K. These limitations are discussed in depth in the Limitations section in this document. In short, they include:
|
Change DescriptionThe 4.0 version of the CFM-68K Runtime Enabler provides a new version of Mixed Mode that allows most interrupt code to be implemented in CFM-68K code. With the exception of applications that use a non-Apple pre-emptive thread scheduler, no applications will need modification. Customers will simply install a new CFM-68K Runtime Enabler in their Extensions folder to take advantage of the fix. The CFM-68K Runtime Enabler contains CFM-68K, Mixed Mode and several shared libraries. With this new release, we've added the Apple Thread Manager and
Below is a brief summary of the changes to the enabler components included in this release. CFM-68KAll of the bug fixes that were included in the PowerPC version of the Code Fragment Manager for the System 7.5.5 Update are included in this release. Refer to Technote 1069 for details of the changes to CFM. Mixed ModeMixed Mode now saves additional state information on the switch frame for a mode transition. Two new API routines have been added for pre-emptive thread switchers to save and restore Mixed Mode state. These API are only callable from classic 68K clients. There will not be a CFM-68K interface to these routines. The new Mixed Mode and Gestalt headers that include these changes will be available on E.T.O. #23. The two new API's are SaveMixedModeState
RestoreMixedModeState
Apple Thread ManagerThe Apple Thread Manager has been added to the 4.0 release of the CFM-68K Runtime Enabler. This version overrides any version of the Apple Thread Manager available before Mac OS 8. It calls the new Mixed Mode API to save and restore Mixed Mode state around a pre-emptive thread switch. |
Pre-emptive Thread SwitchersUnmodified non-Apple pre-emptive thread switchers could still trigger the A5 corruption problem if any CFM-68K code is called from a pre-emptive thread. As such, we have called out and distinguished the term "pre-emptive safe". Without CFM-68K, pre-emptive safe is synonymous with interrupt-safe. Interrupt-safe is a familiar concept to many Apple developers and interrupt task guidelines are documented in Inside Macintosh: Processes. Routines that are interrupt-safe are callable at interrupt time and therefore are callable from pre-emptive threads since these threads are triggered by interrupts. For CFM-68K code, pre-emptive safe and interrupt-safe are no longer synonymous. All CFM-68K code is inherently pre-emptive unsafe because it could be invoked by an unmodified thread switcher which would trigger the A5 bug. The new definition for the term pre-emptive safe is any software that doesn't contain or call any CFM-68K code and is otherwise deemed interrupt-safe. Conversely, code that is otherwise deemed interrupt-safe, but does contain or call CFM-68K code is not pre-emptive safe code, a.k.a. pre-emptive unsafe code.
Developers of new code who declare their code as interrupt-safe must document the pre-emptive safeness of their code. Code that is not interrupt-safe is also not pre-emptive safe; therefore, it is unnecessary to declare code as pre-emptive unsafe if it is already interrupt-unsafe. This is only necessary for code, such as plug-ins, that are provided to other developers and which could potentially be called from a pre-emptive thread. End users need not know about "pre-emptive safety". Since all CFM-68K code is inherently pre-emptive unsafe, then so is any classic service that internally uses CFM-68K code or internally uses some other classic code that itself is pre-emptive unsafe code. The following diagram is an example of pre-emptive unsafe code. All CFM-68K code is inherently pre-emptive unsafe, as defined above. In addition, classic code which in turn invokes CFM-68K code is itself pre-emptive unsafe, even if otherwise considered interrupt-safe. This new version of CFM-68K provides a means for pre-emptively threaded applications to call any interrupt-safe routine, even those that are otherwise deemed pre-emptive unsafe. A new Mixed Mode API is provided to save and restore the Mixed Mode state. Pre-emptive applications should be modified to call these services when switching threads to properly maintain the Mixed Mode state for each thread. Therefore, pre-emptively threaded applications should be separated into two categories: those that can and those that cannot call pre-emptive unsafe routines. Applications that can call pre-emptive unsafe code include:
Applications that cannot call pre-emptive unsafe code include:
|
Thanks to Erik Eidt, Pete Gontier, Jim Murphy, Eric Caspole, Cheryl Ewy, George Warner, Gene Garbutt, John Yen, David Gaxiola, Peri Frantz, Jeff Cobb, Alan Lillich, and Allan Foster.