Specifications
D
evice Driver Programming
11-4
Using the Synchronization Primitives 11
The synchronization primitives to use in a multithreaded environment are spin locks, sleep
locks, and synchronization variables. The choice of the type of primitives to be used
depends on the way the data are accessed, the amount of contention for the data, and the
duration of the accesses.
The following sections describe these synchronization primitives and explain their usage.
It might be worthwhile to mention that there are some special compilation options with
which you must become familiar when programming with locking primitives. These com-
pilation options are used when recompiling the kernel to enforce the order by which the
locks can be nested, gather lock statistics, or use a debug version of the locking primitives.
These options are as follows:
• _LOCKTEST
This compilation option enforces the lock ordering protocol within the driver.
Drivers and modules must use hierarchy values from within a defined range. Hierar-
chy values must be chosen such that locks are acquired in order of increasing hierar-
chy number. The lock must have a hierarchy value that is strictly greater than the
hierarchy values associated with all locks currently held by the calling context. Note
that the hierarchy values specified within a DDI/DKI driver are never checked
against those of locks in the base kernel. As a result, a DDI/DKI driver can assume
that the scope for the hierarchy used is local to the driver—that is, assuming that the
driver does not call into any other DDI/DKI driver(s) with a lock held. Also, a driver
need not worry about the relationship between these values and those used in the
base kernel.
• _MPSTAT
This compilation option is used for gathering statistics. The statistics data gathered
are either performance data or debugging data. All of these data are available via
separately provided function calls.
The performance data are stored in the lock control structure itself. This includes the
number of acquisition attempts and the number of collisions. The performance data
allow a programmer to identify lock contentions and to fine tune their applications.
The debugging data are stored in a log. These data include the name of the primitive,
the operation, the name of the requesters, the disposition (resultant operation),
block, and so on. These data allow you to isolate deadlocks and race conditions.
• DEBUG
This compilation option is used to allow extra sanity checking in some locking
functions. This compilation option is necessary for enabling the spin lock hierarchy
checking and spin lock statistics gathering in the kernel. Note that this option also
enables the _LOCKTEST and _MPSTAT options.