The following information is provided to assist you in understanding locking:
The lockl locks (previously called conventional locks) are provided for compatibility only and should not be used in new code: simple or complex locks should be used instead. These locks are used to protect a critical section of code which accesses a resource such as a data structure or device, serializing access to the resource. Every thread which accesses the resource must acquire the lock first, and release the lock when finished.
A conventional lock has two states: locked or unlocked. In the locked state, a thread is currently executing code in the critical section, and accessing the resource associated with the conventional lock. The thread is considered to be the owner of the conventional lock. No other thread can lock the conventional lock (and therefore enter the critical section) until the owner unlocks it; any thread attempting to do so must wait until the lock is free. In the unlocked state, there are no theads accessing the resource or owning the conventional lock.
Lockl locks are recursive and, unlike simple and complex locks, can be awakened by a signal.
A simple lock provides exclusive-write access to a resource such as a data structure or device. Simple locks are not recursive and have only two states: locked or unlocked.
A complex lock can provide either shared or exclusive access to a resource such as a data structure or device. Complex locks are not recursive by default (but can be made recursive) and have three states: exclusive-write, shared-read, or unlocked.
If several threads perform read operations on the resource, they must first acquire the corresponding lock in shared-read mode. Since no threads are updating the resource, it is safe for all to read it. Any thread which writes to the resource must first acquire the lock in exclusive-write mode. This guarantees that no other thread will read or write the resource while it is being updated.
There are two types of critical sections which must be protected from concurrent execution in order to serialize access to a resource:
|thread-thread||These critical sections must be protected (by using the locking kernel services) from concurrent execution by multiple processes or threads.|
|thread-interrupt||These critical sections must be protected (by using the disable_lock and unlock_enable kernel services) from concurrent execution by an interrupt handler and a thread or process.|
When a lower priority thread owns a lock which a higher-priority thread is attempting to acquire, the owner has its priority promoted to that of the most favored thread waiting for the lock. When the owner releases the lock, its priority is restored to its normal value. Priority promotion ensures that the lock owner can run and release its lock, so that higher priority processes or threads do not remain blocked on the lock.
Attention: A kernel extension should not attempt to acquire the kernel lock if it owns any other lock. Doing so can cause unpredictable results or system failure.
A linear hierarchy of locks exists. This hierarchy is imposed by software convention, but is not enforced by the system. The lockl kernel_lock variable, which is the global kernel lock, has the the coarsest granularity. Other types of locks have finer granularity. The following list shows the ordering of locks based on granularity:
Locks should generally be released in the reverse order from which they were acquired; all locks must be released before a kernel process exits or leaves kernel mode. Kernel mode processes do not receive any signals while they hold any lock.
Locking Kernel Services
Understanding Exception Handling.