X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=Documentation%2FDocBook%2Fkernel-locking.tmpl;h=644c3884fab94eb22001e8876f20a36e7e1d7995;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=4fd97de055ca87a04d0ba59cba6c5231b0941d4d;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index 4fd97de05..644c3884f 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -1,4 +1,6 @@ - + + @@ -220,7 +222,7 @@ Two Main Types of Kernel Locks: Spinlocks and Semaphores - There are two main types of kernel locks. The fundamental type + There are three main types of kernel locks. The fundamental type is the spinlock (include/asm/spinlock.h), which is a very simple single-holder lock: if you can't get the @@ -228,20 +230,26 @@ very small and fast, and can be used anywhere. - The second type is a semaphore + The second type is a mutex + (include/linux/mutex.h): it + is like a spinlock, but you may block holding a mutex. + If you can't lock a mutex, your task will suspend itself, and be woken + up when the mutex is released. This means the CPU can do something + else while you are waiting. There are many cases when you simply + can't sleep (see ), and so have to + use a spinlock instead. + + + The third type is a semaphore (include/asm/semaphore.h): it can have more than one holder at any time (the number decided at initialization time), although it is most commonly used as a - single-holder lock (a mutex). If you can't get a semaphore, - your task will put itself on the queue, and be woken up when the - semaphore is released. This means the CPU will do something - else while you are waiting, but there are many cases when you - simply can't sleep (see ), and so - have to use a spinlock instead. + single-holder lock (a mutex). If you can't get a semaphore, your + task will be suspended and later on woken up - just like for mutexes. Neither type of lock is recursive: see - . + . @@ -326,7 +334,7 @@ Note that you can also use spin_lock_irq() or spin_lock_irqsave() here, which stop - hardware interrupts as well: see . + hardware interrupts as well: see . @@ -403,7 +411,7 @@ The same softirq can run on the other CPUs: you can use a - per-CPU array (see ) for better + per-CPU array (see ) for better performance. If you're going so far as to use a softirq, you probably care about scalable performance enough to justify the extra complexity. @@ -545,120 +553,120 @@ Table of Locking Requirements - - - - -IRQ Handler A -IRQ Handler B -Softirq A -Softirq B -Tasklet A -Tasklet B -Timer A -Timer B -User Context A -User Context B - - - -IRQ Handler A -None - - - -IRQ Handler B -spin_lock_irqsave -None - - - -Softirq A -spin_lock_irq -spin_lock_irq -spin_lock - - - -Softirq B -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock - - - -Tasklet A -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock -None - - - -Tasklet B -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock -spin_lock -None - - - -Timer A -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock -spin_lock -spin_lock -None - - - -Timer B -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock -spin_lock -spin_lock -spin_lock -None - - - -User Context A -spin_lock_irq -spin_lock_irq -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -None - - - -User Context B -spin_lock_irq -spin_lock_irq -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -down_interruptible -None - - - - -
+ + + + +IRQ Handler A +IRQ Handler B +Softirq A +Softirq B +Tasklet A +Tasklet B +Timer A +Timer B +User Context A +User Context B + + + +IRQ Handler A +None + + + +IRQ Handler B +spin_lock_irqsave +None + + + +Softirq A +spin_lock_irq +spin_lock_irq +spin_lock + + + +Softirq B +spin_lock_irq +spin_lock_irq +spin_lock +spin_lock + + + +Tasklet A +spin_lock_irq +spin_lock_irq +spin_lock +spin_lock +None + + + +Tasklet B +spin_lock_irq +spin_lock_irq +spin_lock +spin_lock +spin_lock +None + + + +Timer A +spin_lock_irq +spin_lock_irq +spin_lock +spin_lock +spin_lock +spin_lock +None + + + +Timer B +spin_lock_irq +spin_lock_irq +spin_lock +spin_lock +spin_lock +spin_lock +spin_lock +None + + + +User Context A +spin_lock_irq +spin_lock_irq +spin_lock_bh +spin_lock_bh +spin_lock_bh +spin_lock_bh +spin_lock_bh +spin_lock_bh +None + + + +User Context B +spin_lock_irq +spin_lock_irq +spin_lock_bh +spin_lock_bh +spin_lock_bh +spin_lock_bh +spin_lock_bh +spin_lock_bh +down_interruptible +None + + + + + @@ -1582,7 +1590,7 @@ the amount of locking which needs to be done. Our final dilemma is this: when can we actually destroy the removed element? Remember, a reader might be stepping through - this element in the list right now: it we free this element and + this element in the list right now: if we free this element and the next pointer changes, the reader will jump off into garbage and crash. We need to wait until we know that all the readers who were traversing the list when we deleted the