Although you can in theory designate almost any type of code as a task, in practice you should use the following guidelines to make best use of the available processors and to avoid unnecessary bottlenecks.
Tasks should generally perform faceless processing, such as calculation-intensive work or I/O operations.
The work performed by a task should be substantially more than the time required to process the request and result notifications. If it takes much longer to notify a task and retrieve results than to execute the task itself, an application’s performance will be dramatically worse with multiprocessing. Assuming a typical intertask signaling time is 20-50 microseconds, your tasks should take at least 200-500 microseconds to execute. If you want to explicitly calculate the intertask signaling time, you can use the sample code provided in “Preemptive Task–Safe Mac OS System Software Functions.”
If your task needs to allocate memory in Mac OS 9 and earlier, you must allocate the memory prior to signaling the task, or use the function MPAllocateAligned.
Tasks should not call 68K code. The 68K emulator runs only cooperatively within the Mac OS task, and not within any preemptive task. If you must call 68K code, you can do so using a remote procedure call. See “Making Remote Procedure Calls” for more information.
You can call only preemptive task–safe Mac OS system software functions directly from a task. See Multiprocessing Gestalt Constants and “Preemptive Task–Safe Mac OS System Software Functions” to determine which functions are preemptive task–safe. Other (unsafe) system software functions must be called indirectly through remote procedure calls. See “Making Remote Procedure Calls” for more information.
Tasks should not access low-memory global data. A task may be executing at any time, including when applications that did not create them are running.
Tasks should not call into unknown code. If you allow third parties to specify a callback function, you should never call that function from a task, since you cannot control what the callback will do. Calling back into non-reentrant code could easily corrupt data or cause a system crash.
Avoid global variables. The main cause of non-reentrancy is the manipulation of global data. Tasks that manipulate global variables, global states, or buffers pointed to by global variables must use synchronization techniques to prevent other tasks from attempting to do so at the same time. Read-only global data are allowed.
Do not call any Multiprocessing Services functions at interrupt time unless you are signaling a notification mechanism. See “Notifying Tasks at Interrupt Time” for more information.
Last updated: 2007-10-31