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 4-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) |
Test sif the mutex is held by the current thread. To be used in ASSERT(9F) only. |
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, "xx mutex", MUTEX_DRIVER, NULL); ...
For a more complete example of mutex initialization see Chapter 5, 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.
Every section of the driver code that needs to read or write the shared data structure must do the following:
Acquire the mutex.
Access the data.
Release the mutex.
For example, to protect access to the busy flag in the state structure:
... mutex_enter(&xsp->mu); xsp->busy = 0; mutex_exit(&xsp->mu); ....
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. For additional guidelines on using mutexes see Appendix G, Advanced Topics.