Thread Manager
Volume Number: 10
Issue Number: 11
Column Tag: Essential Apple Technology
Thread Manager for Macintosh Applications 
Appleās Development Guide
By Apple Computer, Inc.
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
This article will provide the reader with the motivation, architecture, and
programmatic interface of the Thread Manager. The architecture section will give some
detail of how the Thread Manager is integrated into the Macintosh environment and
some of the assumptions made in its design. The programmatic interface will then be
described with commentary on the use of each of the routines. The end contains
information such as current known bugs and compatibility issues.
Product Definition
The Thread Manager is the current MacOS solution for lightweight con current
processing. Multithreading allows an application process to be broken into simple
subprocesses that proceed con currently in the same overall application context.
Conceptually, a thread is the smallest amount of processor context state necessary to
encapsulate a computation. Practically speaking, a thread consists of a register set, a
program counter, and a stack. Threads have a fast context switch time due to their
minimal context state requirement and operate within the application context which
gives threads full application global access. Since threads are hosted by an application,
threads within a given application share the address space, file access paths and other
system resources associated with that application. This high degree of data sharing
enables threads to be "lightweight" and the context switches to be very fast relative to
the heavyweight context switches between Process Manager processes.
An execution context requires processor time to get anything done, and there can
be only one thread at a time using the processor. So, just like applications, threads
are scheduled to share the CPU, and the CPU time is scheduled in one of two ways. the
Thread Manager will provide both cooperative and preemptive threads. Cooperative
threads explicitly indicate when they are giving up the CPU. Preemptive threads can be
interrupted and gain control at (most) any time. The basis for the difference is that
there are many parts of the MacOS and Toolbox that can not function properly when
interrupted and/or executed at arbitrary times. Due to this restriction, threads using
such services must be cooperative. Threads that do not use the Toolbox or OS may be
preemptive.
Cooperative threads operate under a scheduling model similar to the Process
Manager, wherein they must make explicit calls for other cooperative threads to get
control. As a result, they are not limited in the calls they can make as long as yielding
calls are properly placed. Preemptive threads operate under a time slice scheduling
model; no special calls are required to surrender the CPU for other preemptive or
cooperative threads to gain control. For threads which are compute-bound or use
MacOS and Toolbox calls that can be interrupted, preemptive threads may be the best
choice; the resulting code is cleaner than if partial results were saved and control then
handed off to other threads of control.
Part 1: requirements summary
The Thread Manager is an operating system enhancement that will allow
applications to make use of both cooperative & preemptive multitasking within their
application context on all 680x0 based Macintosh platforms, and cooperative
multitasking on PowerPC based Macintoshes. There are two basic types of threads
(execution contexts) available: cooperative and preemptive. The different types of
threads are distinguished by their scheduling models.
The benefits of per-application multitasking are numerous. Many applications
are best structured as several independent execution contexts. An image processing
application might want to run a filter on a selected area and still allow the user to
continue work on another portion of an image. A database application may allow a user
to do a search while con currently adding entries over a network. With the Thread
Manager, it is now possible to always make applications responsive to the user, even
while executing other operations. The Thread Manager also gives applications an easy
way to organize multiple instances of same or similar code. In each example it is
possible to write the software as one thread of execution, however, application code
may be simplified by writing each class of operation as a separate thread and letting
the Thread Manager handle the interleaving of the threaded execution contexts.
These examples are not intended to be exhaustive, but they indicate the
opportunities to exploit the Macintosh system and build complex applications with this
technology. The examples show that the model for multiple threads of control must
support a variety of applications and user environments. The Thread Manager
architecture will, where possible, use the current Macintosh programming paradigms
and preserve software compatibility. The Thread Manager enhances the programming
model of the Macintosh for there is little need to develop Time Manager or VBL routines
to provide the application with a preemptive execution context. There is also no need to
save the complete state of a complex calculation in order to make WaitNextEvent or
GetNextEvent calls to be user responsive - simply yield to give the main application
thread a chance to handle interface needs.
Hardware Compatibility
The 680x0 version of the Thread Manager has the same hardware requirements
as System 7.0, that is, at least 2 megabytes of memory, and a Macintosh Plus or newer
CPU. The power version of the Thread Manager requires any Power Macintosh.
Software Compatibility
System 7.0 or greater is required for the 680x0 version of the Thread Manager
to operate. The power version of the Thread Manager requires system software for
Power Macintosh platforms.
Existing applications that know nothing about the Thread Manager have nothing to
fear. The extent of the Thread Manager's influence is to set up the main application
thread when the application is launched, and to make an appearance every so often as
the preemption timer fires off. Because there is only the application thread, the
preemption timer has nothing to do and quietly returns. Thus, the Thread Manager is
nearly transparent to existing applications, and no compatibility concerns are
expected. New applications, of course, can reap the full benefits of con current
programming, including a fairly powerful form of multitasking.
The power version of the Thread Manager is built as a Shared Library, named
ThreadsLib, that is fully integrated into the Thread Manager.
Intended Users
Developers will gain the ability to have multiple, con current, logically separate
threads of execution within their application. The Thread Manager will provide
Macintosh developers with a state of the art foundation for building the next generation
of applications using a multi-threaded application programming environment.
Another, less obvious user is system software which operates in the application
context. The rule of thumb is: Code which operates only within an application context
can use the Thread Manager, code that does not, can not.
Programmatic Interface Description
The Thread Manager performs creation, scheduling and deletion of threads. It
allows multiple independent threads of execution within an application, each having its
own stack and state. The client application can change the scheduler or context switch
parameters to optimize an application for a particular usage pattern.
Applications will interface with the Thread Manager through the use of the Trap
mechanism we know and love. The API is well defined, compelling, and easy to use-no
muss, no fuss. For those who need to get down and dirty, the Thread Manager provides
routines to modify the behavior of the scheduling mechanism and context switching
code.
The API goes through a single trap: ThreadDispatch. Parameters are transferred
on the stack and all routines return an OSErr as their result. The trap dispatch
numbers have both a parameter size and a routine number encoded in them which
allows older versions of the Thread Manager to safely reject calls implemented only by
newer versions. A paramErr is returned for calls not implemented.
The ThreadsLib is a shared library so there is no performance hit due to a trap
call, when using the Thread Manager API. There is a distinction between 680x0
threads and power threads. A 680x0 application may only use 680x0 threads, and
power applications may only use power threads. Mixing thread types (power or
680x0) within an application type (power or 680x0) is considered a programming
error and is not supported.
The context switch time for an individual thread is negligible due to the minimal
context required for a switch. The default context saved by the Thread Manager includes
all processor data, address, and FPU (when required) registers. The thread context
may be enhanced by the application (to include application specific context) which will
increase context switch times (your mileage may vary).
Both cooperative and preemptive threads are eligible for execution only when the
application is switched in by the process manager. In this way, all threads have the
full application context available to them and are executed only when the application
gets time to run.
The interleave design of one cooperative context between every preemptive
context guarantees that threads which can use the Toolbox (cooperative threads) will
be given CPU time to enhance user interface performance.
Part 2: Functional specifications
Features Overview
Per-application thread initialization is completed prior to the entering the
application, which allows applications to begin using the Thread Manager functions as
soon as their main routine begins execution. Thread clean up is not required as this is
done by the Thread Manager at application termination time.
Applications are provided with general purpose routines for thread pool creation,
counting, allocation and deletion. Basic scheduling routines are provided to acquire the
ID of the currently executing thread and to yield to any thread. Preemptive thread
scheduling routines allow a thread to disable preemption during critical sections of
code. Advanced scheduling routines give the ability to yield to a particular thread, and
get & set the state of any thread. Mechanisms are also provided to customize the thread
scheduler and add custom context switching routines.
Software Design & Technical Description
Installation: During system startup, the Thread Manager is installed into the system
and sets up system-wide globals and patch code.
Initialization: Per-application initialization is done prior to entering the
application. This allows applications to take advantage of the Thread Manager
functions as soon as they begin execution of the main application thread.
Important: The Memory Manager routine MaxApplZone must be called before any
thread other than the main application thread allocates memory, or causes
memory to be allocated (see the Constraints, Gotchas & Bugs section for more
information).
Cleanup: The Thread Manager is called by the Process Manager when an application
terminates. This gives the Thread Manager a chance to tear down the threading
mechanism for the application and return appropriate system resources, such as
memory.
Control: The Thread Manager gets control in three ways. The straightforward way is
through API calls made by a threaded application. All calls to the Thread Manager
are made through the trap ThreadDispatch (0xABF2). The less straightforward