Spurred by some recent lkml/kernel-janitor religious wars on the use of spin locks, I'm trying to better understand spin locks and their application. I've decided to start at the obvious point of what exactly spin_lock() is doing. Below is how I understand spin_lock() to be expanded and what that means in context. This is looking at the x86 spinlock in 2.4.19-rc1. For those with a better understanding of this, I'd like to ask: 1 - is this understanding correct? 2 - why the use of 'rep ; nop' in the spin? 3 - why is it unnecessary to 'lock' in spin_unlock()? I don't see where the current way hurts anything, but it seems we might end up in an unnecessary spin once in a blue moon 4 - this seems to indicate that each use of spin_lock() generates redundant (although very small) code in .subsection 1 - correct? Thanks for any input and corrections. Mike This is how I understand it to operate: The initialization of a generic lock->lock sets it to 1 as a starting point. This is handled by spin_lock_init(x). Use of spin_lock(&foo->lock); gets expanded out to what we find below. The expansion operates on &foo->lock directly because of the way we've defined the assembler expansion, namely '"=m" (lock->lock)'. # ---------------- .section .text # spin_lock_string 1: lock # make next atomic decb lock.lock # --lock->lock js 2 # if (lock->lock < 0) goto 2; # meaning someone already has the lock # so we just get in line # if it started at 1, they decb to 0 # and we just came by and decb to -1 # this here deserves a 'coolness' award # because we have written this into a separate section # the above will simply fall through if we are able to # grab the lock - otherwise we go into the spin and # wait for someone else to 'movb $1, lock.lock' (aka spin_unlock()) # at which point we jmp back to 1 and try to acquire the lock again # LOCK_SECTION_START .subsection 1 # start new section [optional things here] .ifndef .text.lock.foo # only if someone else didn't already # LOCK_SECTION_NAME # setup this label in this subsection .text.lock.foo: # named depending on KBUILD_BASENAME .endif 2: cmpb $0, lock.lock # setup for branch test rep # why?? nop # why?? jle 2 # if (lock->lock <= 0) goto 2; jmp 1 # else goto 1; # to try and get the lock again # LOCK_SECTION_END .previous # .section .text or similar # which puts us back in our code # eip->instruction after spin_lock(&foo->lock); # ---------------- # spin_unlock_string # why not 'lock' instruction here? movb $1, lock.lock # lock->lock = 1; release our lock # ---------------- -- Michael Janicki Key: http://wwwkeys.pgp.net:11371/pks/lookup?op=get&search=0x9D6FAE1A Fingerprint: A153 DFC7 8B49 7E97 67B2 3DCE DA3F 3CC5 9D6F AE1A -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/