Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Mar 2007 05:26:20 -0300
From:      Duane Whitty <duane@dwlabs.ca>
To:        freebsd-hackers@freebsd.org
Cc:        Duane Whitty <duane@dwlabs.ca>
Subject:   Locking etc. (Long, boring, redundant, newbie questions)
Message-ID:  <20070328082620.GA1052@dwpc.dwlabs.ca>

next in thread | raw e-mail | index | archive | help
Hello again,

I know this is trivial material but I believe I
have finally come to an understanding about some
things that I have been struggling with.  Maybe
by putting this in words I can help some other newbies
like myself who are hoping to eventually understand
more advanced topics and contribute to FreeBSD.
But please, correct me if you would on topics I still 
do not have correct. And thanks in advance for your
help and patience!

I have been reading non-stop as much as I can on
synchronizing code execution.  In the FreeBSD docs,
and in other docs, there is talk about mutexes
that block and mutexes that sleep.  But this is
not true is it.  What is really meant is that
depending on the type of mutex a thread is trying
to acquire, the thread will either spin or it will
sleep waiting for the lock to become available.
Am I correct so far?

Maybe this method of talking about mutexes happens
because we don't manipulate lock structures directly,
but rather use routines which acquire these locks
for us in a consistent way.  So for instance when
we call mtx_lock(&some_lock) and the lock is contested,
our thread sleeps.  It gets put on a sleep queue
waiting for the lock to become available so that we
can safely access the kernel data structure which this
mutex protects.  Is this accurate so far?

Along the same line as above, if we call mtx_lock_spin(&some_lock),
and the lock is contested, our thread trying to acquire
the lock spins.  This means we go into a tight loop
monopolizing whichever CPU we are running on until
the mutex becomes available.  But, if we spin for so long
that we use up our quantum of time scheduled to us, a panic
happens, because when we try to acquire a spin mutex,
interrupts are turned off and so we can't do a context
switch.  If a thread slept with interrupts disabled,
then interrupts would stay disabled, which must not 
happen.

[insert]

I'm not very sure on this point, but is the above the reason why
interrupt service routines, also known as Fast ISRs (?), use
mtx_lock_spin() mutexes?  They are supposed to be as fast as
possible, and they don't context switch.  As well, isn't it
basically agreed upon that Fast ISRs are really the only
place to use spin mutexes?  Maybe I'm way off here but it
sure would be nice finally putting this one away.

A somewhat newer (?) type of locking procedure is where a thread
will spin when trying to acquire a lock which is contested, for
about the same amount of time as it would take to do a context
switch.  If this time is roughly (approached|exceeded)? then
the thread sleeps.  The reasoning is that in the time it would
take to do a context switch if the thread were to sleep, the
lock the thread is trying to acquire may become available.  If we
get lucky and the lock becomes available while we are spinning
then we have been more efficient.  I hope I am still on
the right track here?


Another item in the documentation I had confused as being part
of the above issue(s) is that it is permissible for a thread to
sleep while holding certain types of locks and that for other
types of locks a thread must not sleep.  Am I correct in my
understanding now that a thread must not sleep while holding
a mutex because doing so could lead to a deadlock?

Another scenario I have just learned is that a semaphore should
not be wrapped inside a mutex, for the same reason; a deadlock.
I guess this is just a specific case of not allowing the 
possibilty of a thread sleeping while holding a mutex, which is
what could happen if a thread is waiting on any kind of
condition variable?

If I am mostly correct (I hope), my enlightenment, if I have any
came about when I started working on the System V IPC code.
When I started trying to learn about semaphores I found out
I needed to learn about a lot of other stuff.  And still do. Perhaps the
most difficult thing is translating from textbook type
examples to real kernel code.  Anyhow, I hope this message
wasn't too long or unbearable.  Please send me any comments
that you would like to, on or off list.

Thanks again!

Duane Whitty

P.S.

I think I'm just about
ready to tackle fixing
sysv sems to wakeup
just the proper number
of processes, now that I
think I know what an
up'ed semaphore is, what
a semaphore set is for, how
semops work, and adjust on 
exit values, and not least,
undos. My head hurts  :-)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070328082620.GA1052>