|
Technote 1137Disabling Interrupts on the Traditional Mac OSBy Quinn "The Eskimo!" |
CONTENTSIntroduction
| This Technote describes how to disable interrupts on the traditional Mac OS. It also includes a long discussion of why you should not disable interrupts, and outlines other system services that you can use to avoid disabling interrupts. This Note is directed at developers who are building kernel-level software, such as device drivers, or application software that makes heavy use of Mac OS "interrupt time." In general, application developers should not need to disable interrupts. |
IntroductionDTS recommends that third-party developers avoid disabling interrupts on Mac OS, although we recognize that there are circumstances for which disabling interrupts is the only solution. The purpose of this Note is to highlight the possible alternatives to disabling interrupts and -- if you decide that none of these meet your needs -- to minimize errors when performing this tricky task. This note should not be construed as an encouragement to disable interrupts needlessly. The note is broken up into four sections:
|
RationaleWhy is DTS so against disabling interrupts? It is because:
This section will explore each area in turn. LatencyDisabling interrupts increases the interrupt latency of the system. This is bad for system functions, like Sound Manager, that require good interrupt latency in order to operate correctly. While somewhat long in the tooth, DTS Technote HW 16 "I Was a Teenage DMA Junkie" describes some background on this issue. Performance PenaltyAs described in the following section, there is no way to disable interrupts quickly on Mac OS. If you're running PowerPC code, you have to take a Mixed Mode Manager switch in order to disable interrupts. If you're building 680x0 software, it's possible that your code will be run on a real 680x0 microprocessor with virtual memory enabled, in which case the modification of the SR register is a privileged operation which the system must emulate for you. Both of these represent a performance penalty. AvoidabilityThe Mac OS provides many low-level primitives that you can use to avoid disabling interrupts. While it's true that many of these routines eventually do disable interrupts, using them saves you some effort and allows Apple to improve the system "behind your back." |
Background MaterialThis section describes the traditional Mac OS interrupt architecture, which is modeled directly after the interrupt architecture on the 680x0 microprocessors. If you're already familiar with the 680x0 interrupt architecture, you may want to skip this section. About 680x0 Interrupt LevelsThe 680x0 SR register contains a three bit field that determines the current interrupt mask, a value from 0 to 7. If the priority of an incoming interrupt (the interrupt's level) is greater than the current interrupt mask, the 680x0 (or the emulated 680x0, if you're running on a PowerPC-based computer) will raise the interrupt mask to that level and service the interrupt. The following table summarizes the common uses for the various interrupt levels:
The 680x0 SR register is a privileged register; it can only be accessed from code running in 680x0 supervisor mode. When you access the SR register from user mode, the 680x0 takes a privilege violation exception. The traditional Mac OS catches this exception and emulates the offending instruction. So, apart from the slow down caused by the exception, you can ignore this restriction and access the SR register from any 680x0 software. For more information on SR register emulation, consult Technote 1094 "Virtual Memory Application Compatibility". Interrupt Levels on a PowerPCThe raw PowerPC processor only has a single-interrupt-state bit: interrupts are either masked or they aren't. The interrupt mask bit is a privileged bit, so you must be running the native PowerPC processor in native supervisor mode to be able to access it. However, Mac OS runs all PowerPC code (except the nanokernel, see the next section) in user mode, so you cannot access the PowerPC interrupt mask bit from PowerPC code. Mac OS Interrupt Architecture on PowerPCAs described above, the 680x0 and PowerPC microprocessors have quite different interrupt architectures. One of the key features of the Mac OS interrupt architecture on PowerPC-based computers is that it emulates the 680x0 interrupt architecture. This is necessary because a significant quantity of code (both in the traditional Mac OS and third party) needs to disable interrupts, including selectively masking interrupts at a specific level. For example, consider the traditional Mac OS serial driver. As serial interrupts occur at level 2, the serial driver interrupt handler knows that, as long as it keeps the interrupt mask at 2 or higher, no other serial interrupt can occur. Many drivers use this assumption to provide concurrency control for their global data structures.
So, for compatibility purposes, all interrupts on Power Macintosh computers are prioritorized as if they were on a 680x0-based computer. When external hardware interrupts the PowerPC processor, the interrupt is initially serviced by the nanokernel, which takes one of two actions depending on the state of the machine:
The emulator executes 680x0 instructions atomically with respect to interrupts, as they were in the original 680x0 processors. This preserves the atomicity implied in 680x0 interrupt-handling code. The dynamic recompiling emulator may check for interrupts with less granularity due to the larger sections of native code it builds. In summary, on a Power Macintosh, all interrupts are routed by the nanokernel through the emulator for servicing to achieve faithful emulation of 680x0 interrupts levels and to keep 680x0 instructions indivisible. Theoretical Background for |
Note: |
AvoidanceBefore disabling interrupts, you should investigate the following system services to see if you can use them instead. OS UtilitiesThe ancestors of all atomic operations on the Mac OS are the OS Utilities routines Deferred TasksIf you place all your critical sections in deferred tasks, you can take advantage of the Deferred Task Manager's guarantee that all deferred tasks are serialized. Open Transport UtilitiesOpen Transport provides a plethora of kernel-level services, including the following interrupt safe constructs:
All of these OT primitives are implemented completely in native code on the PowerPC. |
IMPORTANT: |
SummaryDTS recommends that developers avoid disabling interrupts. Mac OS provides many alternatives to disabling interrupts. If none of these alternatives meet your needs, you can disable interrupts by setting the interrupt mask in the 680x0 SR register. To do this from PowerPC code, you must call 680x0 software using Mixed Mode Manager. If you do this, you should use the code from |
|
Acknowledgments |
Thanks to Mark Cookson, Pete Gontier, Jim Luther, Jim Murphy, Paul Resch, and Alex Rosenberg. |
|
To contact us, please use the Contact Us page. |
Updated: 31-August-98 |