September 95 - Balance of Power: The Power Macintosh: The Next Generation
Balance of Power:
The Power Macintosh: The Next Generation
Dave Evans
The Power Macintosh computer just keeps moving forward. The latest generation
brings greatly improved performance and adds the PCI expansion bus and the
PowerPC 603 and 604 processors. Software changes that improve performance
include the following:
- an improved 680x0 emulator
- a native Resource Manager
- native networking (Open Transport)
- native device drivers
- an improved Memory Manager
I'll describe these new features and
discuss how you can maintain compatibility with the new Power Macintosh
computers and with future changes to the Mac OS.
THE
IMPROVED EMULATOR
First delivered with the Power Macintosh 9500 computer, the new emulator
improves on the original in one key way: it actually recompiles 680x0 code into
native PowerPC code. Since large portions of the Mac OS are still in 680x0
code, this new emulator speeds up most common operations and offers significant
improvements for 680x0 code with tight loops.
Recompiling doesn't mean converting 680x0 instructions one for one into PowerPC
instructions. Fully emulating a 680x0 instruction still takes a few PowerPC
instructions. But recompiled code is more efficient and optimized. The original
emulator had to decipher each instruction every time it was executed, but
recompiled code from the new emulator is analyzed once and then executed many
times.
Because it takes extra time to recompile code, the emulator doesn't immediately
translate all 680x0 code. It operates just like its predecessor until it
encounters a loop or similar repetition. Then, instead of emulating the same
code repeatedly, it translates the instructions into native code and caches the
result. Subsequent calls to that code simply execute the native translation,
greatly improving performance.
The cache of translated 680x0 code must stay coherent with memory, much like
the caches on the Motorola 68040 processor. Therefore, whenever your software
modifies code or changes application jump tables, you should flush the
instruction cache. (See the Macintosh Technical Note "Cache as Cache Can" (HW
6) for a more detailed description of cases where flushing the instruction
cache is necessary.) In the past you could call Gestalt and check the processor
type to flush only on a 68040. Since the new emulator supports only the 68020
instruction set -- and Gestalt will indicate that a 68020 is installed -- you
should now flush any time you modify code or change jump tables.
The best way to flush 680x0 code in the cache is with FlushCodeCacheRange,
which flushes only the invalid portion of the emulator's cache.
FlushInstructionCache also works but can degrade performance by wastefully
purging recompiled code that's still valid. These routines are documented in
Inside Macintosh: Memory. The C prototype for FlushCodeCacheRange is as follows:
OSErr FlushCodeCacheRange(void *address,
unsigned long count);
In
680x0 assembly, you would use
MyFlushCodeCacheRange Proc
; On entry A0 = address, D0 = # of bytes
; Trashes A0, A1, D0. Result in D0, Z bit set.
;
movea.l D0,A1 ; # bytes in A1
moveq #$9,D0 ; selector
_HWPriv ; A098
tst.w D0 ; result == noErr
rts
OTHER
SOFTWARE CHANGES
The first Power Macintosh computer ported critical portions of the Macintosh
Toolbox to native PowerPC code. Ultimately we'll take all of the Mac OS native,
but for now we've focused on areas that most increase overall performance. So,
starting with the Power Macintosh 9500, we've added a native Resource Manager,
the native Open Transport networking stack, and native device drivers. I'll
discuss each of these in turn and then mention improvements to the Modern
Memory Manager.
Even though many calls to the Resource Manager are bound by I/O bottlenecks,
porting the Resource Manager to native PowerPC code still substantially
improves performance. Often to complete a request the Resource Manager need
only look up existing information and return it, and even if file I/O is
required the data is often in the system disk cache. For these reasons, many
Resource Manager calls will execute much faster on the new machines.
Native Open Transport networking provides a stream-based interface for
networking that's independent of the network protocol. You can now implement a
variety of network solutions without concerning yourself with protocol details.
Documentation on Open Transport is provided on this issue's CD.
Native device drivers provide both a performance improvement and an improved
system programming interface (SPI). This SPI is available with all PCI-based
Macintosh computers, starting with the Power Macintosh 9500. For more
information on these drivers, see the article "Creating PCI Device Drivers" in
develop Issue 22 and Designing PCI Cards and Drivers for Power Macintosh
Computers, available from Apple Developer Catalog.
Although not new, the native Modern Memory Manager has been improved in two
important ways:
- Many of the routines are now implemented as "fat" binaries instead of all
native code. When your 680x0 code calls the Memory Manager, it will now execute
680x0-based routines, eliminating the Mixed Mode environment switch once needed
to call the native routines. Reducing the number of these switches can
measurably improve performance.
- The bus error handlers have been removed, significantly increasing the
performance of many of the simple Memory Manager calls and allowing a number of
the calls to be made into fat traps. Bugs discovered during the process of
removing the handlers have been fixed.
Handles passed to the Memory Manager
now go through a rigorous check before they can affect other Memory Manager
data structures; however, without the nearly foolproof bus error handling, it's
a little more likely that you'll pass an invalid address and crash. If you
crash in the MemoryMgr code fragment while testing on the new Power Macintosh
computers, you probably passed an invalid pointer or handle. You can use the
Debugging Modern Memory Manager to aggressively catch these application
errors.
Note also that the bus error handlers would allow system (and even application)
heaps to become corrupted, deteriorating the overall user experience without
causing the machine to crash. This is much less likely to happen now, but if
structures do get corrupted other than by the Memory Manager, a system crash
will result.
Also available starting with the latest Power Macintosh machines is support for
very large hard disk volumes. In the past, only 2-gigabyte volumes were
allowed; then with System 7.5 we relaxed that restriction to 4-gigabyte
volumes. But many of you were still hungry for more, so now we allow up to 2
terabytes (that's 2000 gigabytes) of file system address space per volume.
Unless you're developing utilities and drivers compatible with the new volume
sizes, though, you really don't need to pay attention to the new large-volume
support, because the API remains unchanged. The only time an application might
want to take advantage of the new support is when it wants to know before
attempting to save to disk whether there's enough free space on the volume.
Even in this case, the application won't be able to save a file bigger than the
existing limit of 2 GB, and the old version of GetVInfo will return values that
are "high-water marked" at 2 GB for compatibility reasons, even if more space
is available.
If you really do want to know how much space is available, you can do so
through an extension to the File Manager API. We extended the API because the
existing 32-bit size information was too small to address volumes and files
larger than 4 GB. You'll use the following new routine to get 64-bit sizes:
pascal OSErr PBXGetVolInfo(XVolumeParam
paramBlock, Boolean async);
This
routine takes an extended VolumeParam structure, named XVolumeParam, which
you'll find declared in an updated Files.h interface file on the CD. Before
using this routine, be sure to call Gestalt with the gestaltFSAttr selector; if
the response parameter has the gestaltFSSupports2TBVolumes bit set, the new
routine is available. Note that there are also extended Read and Write calls
for drivers that want to support volumes larger than 4 GB.
PCI
AND NUBUS
Starting with the PCI-based Power Macintosh computers, support for the
NuBus
(TM)-specific Slot Manager goes away. Some applications used to
call the Slot Manager directly to get video and other device information. This
will no longer work, so we've provided better methods: the Display Manager API
has been extended for all the video device information you'll need, and the new
Name Registry API will give you device information independent of the specific
expansion bus implementation.
One example of the improved Display Manager API is the way you get display
modes for video devices. With the Slot Manager this took a lot of code, but the
Display Manager gives you one encompassing routine:
pascal OSErr DMNewDisplayModeList(
GDHandle theGDevice,
unsigned long reserved,
unsigned long *modeCount,
DMListType *theDisplayModeList,
unsigned long modeListFlags);
With
this and other new Display Manager routines, you can avoid the Slot Manager
altogether when gathering display information. But if you must access other
device information, you can use the bus-neutral Name Registry, which manages a
tree of device objects that you can access as a linked list. Look for the new
header files (Displays.h and NameRegistry.h) on this issue's CD.
MAINTAINING
COMPATIBILITY
As Apple improves the Mac OS, compatibility with the documented APIs and SPIs
is ensured -- but don't assume that if your application runs fine on existing
machines, it will continue to do so in the future. We can't ensure complete
compatibility if application code makes invalid assumptions or uses unsupported
parts of the Mac OS. There are some things you can do to help ensure that your
applications will run on future versions of the Mac OS.
First, use only the officially documented APIs. For example, don't assume that
the Z status bit will be set correctly on exit from a trap unless it's
documented. As we take more traps native, the 680x0 status register becomes
irrelevant and such checks break. Here's an example of 680x0 code that now
breaks because it assumes the Z status bit will be set by Get1Resource:
move.l #'DAVE',-(sp)
clr.w -(sp)
_Get1Resource
beq.s error ; BAD!
You
also shouldn't expect results in registers if the trap isn't documented to
return them there. It's true that some traps used to accidentally exit with
useful data in register D0 or A0, but if that's not documented as part of the
API it won't be supported in the future.
Second, test your software using EvenBetterBusError, the Debugging Modern
Memory Manager, and any other debugging tools that are appropriate (look in the
Testing & Debugging folder on the CD). Stress-testing your software with
these tools will catch many errors that otherwise would go unnoticed.
EvenBetterBusError catches most stray references to nil, such as writing to
location 0 or using nil pointers and handles. The Debugging Modern Memory
Manager catches those occasions when you damage a heap or pass invalid
addresses.
Finally, as I've said in previous columns, don't use RS/6000 POWER instructions
in your native code. Although the PowerPC 601 processor supports many of them,
the new 603 and 604 processors do not. We've made an attempt to emulate the
POWER instructions in software for these new processors, but this emulation is
very expensive. When a 603 or 604 encounters one
of these now-illegal instructions, it stops everything and calls our new
illegal-instruction handler, which recognizes the instruction that was used and
attempts to use a valid one instead. This operation is very time consuming; if
your performance-critical code includes POWER instructions, you'll see a severe
slowdown. As described in this column in develop Issue 21, you should use the
DumpXCOFF tool to check your code for any POWER instructions.
NEW
DIRECTIONS
Apple will continue to take advantage of RISC technology and will both improve
existing performance and add new functionality. Make sure your code uses
documented interfaces so that it will stay compatible and run on future
generations of the Power Macintosh. And be sure to check out Open Transport and
PCI device drivers -- they're exciting new directions that will take you closer
to the next generation of the Mac OS today.
DAVE EVANS and fellow Apple engineer Rus Maxham rode 2000 miles on their
motorcycles this summer. They journeyed through the lush Central Valley of
California, the blistering heat of the southern Arizona deserts, and the neon
glitz of Las Vegas. Along the way they enjoyed the camaraderie of fellow bikers
and were rescued in their hour of need by a sympathetic motorcycling couple who
housed them as Rus rebuilt his BMW's rear drive assembly.*
Thanks to Bill Knott, Eric Traut, and Jack Valois for reviewing this column.*
Special thanks to Randy and Peggy Marlatt of Flagstaff, Arizona, for road
support.*