understanding spin_lock()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




  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/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux