The locking rules for this qotd_3 driver are as follows:
You must have exclusive access to do any of the following operations. To have exclusive access, you must own the mutex or you must set QOTD_BUSY. Threads must wait on QOTD_BUSY.
Test the contents of the storage buffer.
Modify the contents of the storage buffer.
Modify the size of the storage buffer.
Modify variables that refer to the address of the storage buffer.
If your operation does not need to sleep, do the following actions:
Acquire the mutex.
Wait until QOTD_BUSY is cleared. When the thread that set QOTD_BUSY clears QOTD_BUSY, that thread also should signal threads waiting on the condition variable and then drop the mutex.
Perform your operation. You do not need to set QOTD_BUSY before you perform your operation.
Drop the mutex.
The following code sample illustrates this rule:
mutex_enter(&qsp->lock); while (qsp->flags & QOTD_BUSY) { if (cv_wait_sig(&qsp->cv, &qsp->lock) == 0) { mutex_exit(&qsp->lock); ddi_umem_free(new_cookie); return (EINTR); } } memcpy(new_qotd, qsp->qotd, min(qsp->qotd_len, new_len)); ddi_umem_free(qsp->qotd_cookie); qsp->qotd = new_qotd; qsp->qotd_cookie = new_cookie; qsp->qotd_len = new_len; qsp->flags |= QOTD_CHANGED; mutex_exit(&qsp->lock);
If your operation must sleep, do the following actions:
Acquire the mutex.
Set QOTD_BUSY.
Drop the mutex.
Perform your operation.
Reacquire the mutex.
Signal any threads waiting on the condition variable.
Drop the mutex.
These locking rules are very simple. These three rules ensure consistent access to the buffer and its metadata. Realistic drivers probably have more complex locking requirements. For example, drivers that use ring buffers or drivers that manage multiple register sets or multiple devices have more complex locking requirements.