Writing Device Drivers

Mutual-Exclusion Locks

A mutual-exclusion lock, or mutex, is usually associated with a set of data and regulates access to that data. Mutexes provide a way to allow only one thread at a time access to that data.

Table 3–1 Mutex Routines

Name 

Description 

mutex_init(9F)

Initializes a mutex 

mutex_destroy(9F)

Releases any associated storage 

mutex_enter(9F)

Acquires a mutex 

mutex_tryenter(9F)

Acquires a mutex if available; but does not block 

mutex_exit(9F)

Releases a mutex 

mutex_owned(9F)

Tests to determine if the mutex is held by the current thread. To be used in ASSERT(9F) only

Setting Up Mutexes

Device drivers usually allocate a mutex for each driver data structure. The mutex is typically a field in the structure and is of type kmutex_t. mutex_init(9F) is called to prepare the mutex for use. This is usually done at attach(9E) time for per-device mutexes and _init(9E) time for global driver mutexes.

For example,

struct xxstate *xsp;
...
mutex_init(&xsp->mu, NULL, MUTEX_DRIVER, NULL);
...

For a more complete example of mutex initialization, see Chapter 5, Driver Autoconfiguration.

The driver must destroy the mutex with mutex_destroy(9F) before being unloaded. This is usually done at detach(9E) time for per-device mutexes and _fini(9E) time for global driver mutexes.

Using Mutexes

Every section of the driver code that needs to read or write the shared data structure must do the following:

The scope of a mutex—the data it protects—is entirely up to the programmer. A mutex protects some particular data structure because the programmer chooses to do so and uses it accordingly. A mutex protects a data structure only if every code path that accesses the data structure does so while holding the mutex.