Setting and Restoring the A5 Register
Setting and Restoring the A5 Register
Suppose you want to alert the user about something important that happens
when your application is running in the background. To do so, you can use the
Notification Manager to install a notification request. You request a
notification by passing the Notification Manager the address of a
notification record, which contains information about the ways in which the
Notification Manager should alert the user. One of the fields in the
notification record (nmRefCon) is a reference constant that is reserved for
your application's use. When you set up a notification request, you can use that
field to hold the value in the A5 register. The code example below illustrates
how to save the current value in the A5 register and pass that value to a
response procedure.
// Passing A5 to a notification response procedure
// Assuming inclusion of MacHeaders
#include <Notification.h>
// Prototype for utility routine to pass A5 to notification response
void PassA5ToNotification(void);
void PassA5ToNotification(void)
{
NMRec myNotif; // a notification record
// Prototype for response procedure
// NOTE: It uses pascal style calling conventions
pascal void SampleResponse(NMRecPtr);
myNotif.qType = nmType; // Set queue type
myNotif.nmMark = 1; // put mark in Application Menu
myNotif.nmIcon = NULL; // no alternating ICON
myNotif.nmSound = (Handle)-1; // play system alert sound
myNotif.nmStr = nil; // no alert box
myNotif.nmResp = (NMProcPtr)&SampleResponse;
// set response procedure
myNotif.nmRefCon = SetCurrentA5(); // pass A5 to notification task
}
The key step is to save the value of the CurrentA5 global variable in a location
where the response procedure can find it-in this case, in the nmRefCon field.
You must call SetCurrentA5 at non-interrupt time (or else you cannot be
certain that it is returning you the correct value).
When the notification's response procedure executes, the first thing it should
do is set register A5 to the application's value of CurrentA5. The response
procedure needs to set up the application's A5 because it may execute at a time
when that application is not the active application. The code example below
shows a simple response procedure that sets up A5, modifies a global variable,
and then re stores A5.
You can use similar techniques with other routines that may execute when
your application is not in control of the CPU. However, not every manager
provides such facilities for passing the value of an application's CurrentA5 to a
task or completion routine. For example, the Time Manager task record does
not contain a field that you can use to store this value. As a result, you need to
use other techniques to pass that value to a
Time Manager task. Using Application Global Variables in Tasks
in the Time Manager shows an example of one technique for doing this.
// Setting up and restoring A5
// Assuming Inclusion of MacHeaders
#include <Notification.h>
Boolean gNotifReceived; // application global to show alert was received
// Prototype your SampleResponse like this
// NOTE that it uses Pascal style calling conventions
// since it is to be called from the ToolBox
pascal void SampleResponse(NMRecPtr);
pascal void SampleResponse (NMRecPtr nmReqPtr)
{
long oldA5; // A5 when procedure is called
oldA5 = SetA5(nmReqPtr->nmRefCon); // set A5 to the app's A5
gNotifReceived = TRUE; // set an application global to show
//alert was received
oldA5 = SetA5(oldA5); // restore A5 to original value
}
Note: Many optimizing compilers may put the address of a global
variable into a register before the call to SetA5, thereby possibly
generating incorrect references to global data. To avoid this problem,
you can divide your completion routine into two separate routines,
one to set up and restore A5 and one to do the actual completion work.
Check the documentation for your development environment to see if
this division is necessary, or contact Macintosh Developer Technical
Support.