Document

advertisement
Kernel Locking
Techniques
by Robert Love
presented by Scott Price
Introduction
Locking can be very tough to implement correctly
Poorly designed locking can result into code that is hard to read and
performs poorly.
Locking is needed to synchronize code paths in the kernel.
Critical sections require combinations of concurrent or re-entrance
protection and proper ordering of events
Improper designed locking can result in crashes and other oddities.
++i shared is dangerous so all shared memory in the kernel needs to
have some type of locking.
two threads can access i at the same time and could increment i once or
could increment i twice.
I++ example
No Lock
Lock
SMP Locks in Uniprocessor
Kernel
Interrupt handlers, preemptible kernel and any
code that can block can all create locking
issues
If your running SMP machine or not, anyone
could use your code. So you have to make
sure code is safe on both SMP and unicore
combinations of CONFIG_SMP and
CONFIG_PREEMPT in varying locking
support
Lock everything appropriate and make sure all
situations are covered.
Bad things that Happen
When we don’t Lock Kernel
Atomic Operations
Complex locking primitives are built off atomic operations. They are the
building blocks of kernel locks
Atomic operations are like add and subtract but perform in one
uninterruptible operation
two types of Atomic operators exist. Ones that work on integers and
ones that work on bits
You cannot pass an atomic type to anything but an atomic operation.
Some architectural limitations do not expect atomic operations to have
more then 24 bits
Atomic Operations and interrupts
When we have shared data that is accessed by normal kernel
code and Interrupt handler code, we need to have atomic
operations to both acquire the lock and disable interrupts at the
same time.
If we do not use an atomic operations to both lock and disable
interrupts, an interrupt can possibly happen during a locking
phase. The interrupt will try to acquire the lock and can possibly
deadlock
Besides this issue we can use locks without disabling interrupts
Spinlocks
Are a Simple single-holder lock.
If process attempts to acquire a lock and it is
not available, the process will keep trying to
acquire the lock (spinning) until the lock is
available.
Once the lock is acquired you can process the
critical region and release the lock
SMP
Unicore
Spinlocks
Spinlocks should only be used when the lock
is not going to be held very long. Or other
processes will spin doing nothing.
Do not use spin locks on processes that will
go to sleep. Or else a deadlock could occur.
spin_lock_irqsave() and
spin_unlock_irqrestore() are atomic
operations that acquire the lock and disable
interrupts with one atomic operation
we need to both acquire the lock and disable
interrupts in one operation or else we could
have a race condition
Semaphores
Semaphores are sleeping locks because they can
cause a task to sleep on contention instead of spin.
They are used when you are going to take hold of a lock
for a long time
There is overhead for putting task to sleep and waking
task up. This should not be used for locks that are held
for a short amount of time.
Semaphores have a queue for how many threads are
waiting. If the number is positive, this is the amount of
threads that are waiting on the queue.
If negative, the semaphore is unavailable and the
absolute value is the usage count
Semaphore
Semaphores manipulate 2 methods up(), down() they
increment/decrement the wait queue
up_interruptible() the calling process is added to the wait
queue and blocked
down_interruptible() the process obtains the semaphore
up and down increment of semaphores have to atomic
operations
Reader/Writer Locks
is safe for multiple threads to read data concurrently. As long as nothing
modifies the data
R/W locks allow multiple concurrent readers but only a single writer.
If data is access, it naturally divides into clear reading and writing
patterns especially with greater amount of reading time, then writing
time. If so R/W locks are preferred
R/W spinlock is called rwlock, similar to spinlock with the exception of
separate R/W locking
R/W locks can give appreciable optimization
Attempting to acquire exclusive access while holding reader access
will deadlock
reader/writer locks
spinlock version
semaphore version
Big-Reader Locks
Provide a spinning lock
that is very fast to acquire
for reading but incredibly
slow to acquire for writing
Ideal for situations with
many readers and a few
writers
Only used for special
cases.
Big-Kernel locks
Global kernel lock BKL
Still exist today but lots of work went into removing it for more
fine-grained localized locks
a spinning lock that is recursive so two consecutive request
will not deadlock the process like a spinlock will do
A process can sleep and enter the scheduler while holding.
When a process is holding, if another process enters the
scheduler, the lock is dropped so other processes can obtain
it.
It exist but shouldn't use other locks are more efficient
Preemptive Control
Linux kernel is fully preemptible
Allows processes to be preempted by higher priority processes even if there is a
process running in the kernel
Preemptible kernel creates synchronization issues of SMP
Kernel preemption is synchronized by SMP locks so most issues are solved writing
SMP safe code.
Introduces a few new locking issues
For preemptible situations, we can disable and enable the preemption if needed
Conclusion
SMP reliability and scalability in the linux kernel are
improving since SMP was introduce
Future holds better performance
Kernel developers should do their part by writing code
that implements smart, sane, proper locking with an eye
to both scalability and reliability!!
OR ELSE!
This could happen!!!
Download