Advanced Search
Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

Technical Q&A OPS19
Making Data Executable


Q: I'm writing a program that constructs machine code on the fly. How do I correctly flush the processor cache so that I can execute the newly constructed instructions?

A: This answer depends on the instruction set architecture (ISA) of the code you are constructing:

  • If you are constructing 68K code, you must call FlushCodeCacheRange and, if that returns an error, call FlushCodeCache.
  • If you are constructing PowerPC code, you must call MakeDataExecutable.
IMPORTANT:
The answer is independent of the ISA of the code you are running. For example, if you're writing PowerPC code that constructs 68K code, you must call FlushCodeCacheRange and not MakeDataExecutable. Similarly, if you are writing 68K code that constructs PowerPC code, you must call MakeDataExecutable.
WARNING:
You can not make 68K data executable using either FlushInstructionCache or FlushDataCache. To correctly make 68K data executable, you must flush both caches in the right order. FlushCodeCacheRange and FlushCodeCache do this for you, which is why we strongly recommend you use them exclusively.

For a detailed description of how the Macintosh cache architecture affects software, see DTS Technote HW 06 Cache as Cache Can.

The DTS sample code library "MoreIsBetter" contains a module ("MoreOSUtils") that shows how to make data executable as 68K or PowerPC code. This module handles all of the complexities described below.

There are a number of important things to remember when calling the above routines:

  • FlushCodeCacheRange is not exported by InterfaceLib on Mac OS 8.1 and below. If you want to use FlushCodeCacheRange from CFM code prior to Mac OS 8.5, you must write your own Mixed Mode glue. Technote 1127 In Search of Missing Links describes the general technique for doing this.
  • FlushCodeCacheRange is exported by InterfaceLib on Mac OS 8.5 and above. To access it, you must link with the InterfaceLib stub library from Universal Interfaces 3.2 or above.
  • Various versions of Universal Interfaces have one or two of the following bugs:
  1. Wrong prototype for FlushCodeCacheRange -- Older versions of Universal Interfaces define FlushCodeCacheRange to have a void result rather than an OSErr. This is a problem because the correct cache flushing algorithm requires you to test the result from FlushCodeCacheRange.
  2. Wrong Conditional -- Older versions of Universal Interfaces conditionally define FlushCodeCacheRange so that it's not available to CFM code. But, as explained above, it's important to call FlushCodeCacheRange if you generate 68K code, even if you generate the 68K instructions using PowerPC code.

The following table shows which versions of Universal Interfaces have which of these problems:

Universal Interfaces Version Bogus Prototype Bogus Conditional
2.1.4 and below Yes Yes
3.0, 3.0.1, 3.1 No Yes
3.2 No No
  • PowerPC-based computers always implement FlushCodeCacheRange, so you never need to call FlushCodeCache if you're executing PowerPC code.
  • Some older 68K-based computers may not implement _HWPriv, the trap underlying FlushCodeCacheRange. If your software might be run on 68K-based computers, you should test for the availability of the _HWPriv trap before calling FlushCodeCacheRange.
  • MakeDataExecutable has no trap. If you're running classic 68K code on a PowerPC-based computer, you must make explicit CFM and Mixed Mode calls to execute this routine. Technote 1077 Calling CFM Code From Classic 68K Code describes a general technique for doing this.
  • BlockMove is possibly the easiest way to flush the 68K instruction cache, especially when you're moving large chunks of 68K code. Inside Macintosh: Memory documents that BlockMove will do whatever flushing is appropriate when any block 12 bytes and bigger is moved.

For more information about instruction caches on the Macintosh, see:

Updated: 12-April-1999


Developer Documentation | Technical Notes | Development Kits | Sample Code

Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2004 Apple Computer, Inc.
All rights reserved. | Terms of use | Privacy Notice