spin_lock()/spin_lock_irqsave() on UP and SMP machine

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by tcs » Mon, 22 Mar 2004 20:10:05



Hi:
  We have searched the whole internet for several days and read kernel
source codes but we couldn't find the answer yet. At least, we couldn't
explain what we've seen yet.

  On a UP system with UP kernel, the following codes don't do anything,
right??

   spin_lock( &lock);
   spin_lock( &lock);
   ...
   spin_unlock(&lock);
   spin_unlock(&lock);

  Please don't ask me why we wrote this code, we just need to demonstrate
that spin_lock() doesn't do anything on a UP system as the kernel source
suggests.

  Then, the above exact same code should result in a deadlock on SMP machine
with SMP kernel, right? For you can't acquire the same spin lock TWICE.

  Then, the above exact same code should result in a deadlock on UP machine
with SMP kernel, right?

  Then, the above exact same code should do nothing on SMP machines with UP
kernel, right?

  Hopefully, we got the above four answers correctly.
  Then, let's modify the above codes slightly to

  spin_lock_irqsave( &lock, flags );
  spin_lock_irqsave( &lock, flags );
  ...
  spin_unlock_irqrestore( &lock, flags );
  spin_unlock_irqrestore( &lock, flags );

  UP macine + UP kernel -> don't do anything
  SMP machine + SMP kernel -> deadlock
  UP machine + SMP kernel -> deadlock
  SMP machine + UP kernel -> dont' do anything

thank you in advance for your kindly help

tcs

 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by Ulrich Weigan » Tue, 23 Mar 2004 02:09:02



>  Then, the above exact same code should result in a deadlock on SMP machine
>with SMP kernel, right? For you can't acquire the same spin lock TWICE.
>  Then, the above exact same code should result in a deadlock on UP machine
>with SMP kernel, right?
>  Then, the above exact same code should do nothing on SMP machines with UP
>kernel, right?

Right.

Quote:>  Hopefully, we got the above four answers correctly.
>  Then, let's modify the above codes slightly to
>  spin_lock_irqsave( &lock, flags );
>  spin_lock_irqsave( &lock, flags );
>  ...
>  spin_unlock_irqrestore( &lock, flags );
>  spin_unlock_irqrestore( &lock, flags );
>  UP macine + UP kernel -> don't do anything
>  SMP machine + SMP kernel -> deadlock
>  UP machine + SMP kernel -> deadlock
>  SMP machine + UP kernel -> dont' do anything

Well, not quite -- this will always leave IRQs disabled,
as the second spin_lock_irqsave will clobber the 'flags'
variable saved by the the first one.

If you use two separate flags variables, it should do
what you expect, though.

--
  Dr. Ulrich Weigand


 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by tcs » Tue, 23 Mar 2004 11:34:44


thank you very much, it took me so much time to realize how to properly use
spin_lock(), spin_lock_irq() and spin_lock_irqsave().

Quote:> If you use two separate flags variables, it should do
> what you expect, though.

  Once we understand how spin_lock() work on Linux, then we have to ask some
design questions. In OS course we took before, we learned that spin lock is
more efficient on SMP machines because it just loops until it's allowed to
get into critical section. BUT, we never learned that spin lock is
transferred to no-op on UP machine. We mean we never learned it from
textbook. Is this specific to Linux (changing spin lock to no-op on UP
machine)? This really confused me for a long time.

best regards

tcs

 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by Ulrich Weigan » Wed, 24 Mar 2004 05:16:25



>  Once we understand how spin_lock() work on Linux, then we have to ask some
>design questions. In OS course we took before, we learned that spin lock is
>more efficient on SMP machines because it just loops until it's allowed to
>get into critical section. BUT, we never learned that spin lock is
>transferred to no-op on UP machine. We mean we never learned it from
>textbook. Is this specific to Linux (changing spin lock to no-op on UP
>machine)? This really confused me for a long time.

Well, changing spin lock to no-op on UP is simply an implementation
detail that improves efficiency while not changing the behaviour of
correct code in any way: the semantics of spin_lock/spin_unlock is
to guarantee that at any time at most one processor executes code
within the critical section.  This semantics is correctly implemented
by both the SMP and (trivially) the UP version of spin_lock.

--
  Dr. Ulrich Weigand

 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by tcs » Wed, 24 Mar 2004 16:35:17


 > Well, changing spin lock to no-op on UP is simply an implementation
Quote:> detail that improves efficiency while not changing the behaviour of

                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Quote:> correct code in any way: the semantics of spin_lock/spin_unlock is
  ^^^^^^^^^^^^^
> to guarantee that at any time at most one processor executes code
> within the critical section.  This semantics is correctly implemented
> by both the SMP and (trivially) the UP version of spin_lock.

  It does change the behavior of correct codes.
  On a UP machine, I expect the following codes to protect the critical
section

  spin_lock()
   critical section
  spin_unlock()

  but it doesn't work on Linux. The second thread acquiring a spinlock which
has been held by the other thread can spin waiting, in Linux, it doesn't.

regards

techeng

 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by Michael Schnel » Wed, 24 Mar 2004 17:29:18


AFAIK:

Originally spinlocks were just for synchronizing multiple processors. So
they don't generate any code on single processor Kernels.

But some of the "preemption" patches seem to use them as Kernel
preemption points in single processor Kernels. So they do something
there, too.

-Michael

 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by Ulrich Weigan » Thu, 25 Mar 2004 05:46:16



> > Well, changing spin lock to no-op on UP is simply an implementation
>> detail that improves efficiency while not changing the behaviour of
>                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> correct code in any way: the semantics of spin_lock/spin_unlock is
>  ^^^^^^^^^^^^^
>> to guarantee that at any time at most one processor executes code
>> within the critical section.  This semantics is correctly implemented
>> by both the SMP and (trivially) the UP version of spin_lock.
>  It does change the behavior of correct codes.
>  On a UP machine, I expect the following codes to protect the critical
>section
>  spin_lock()
>   critical section
>  spin_unlock()
>  but it doesn't work on Linux. The second thread acquiring a spinlock which
>has been held by the other thread can spin waiting, in Linux, it doesn't.

But it does work.  On a UP kernel, there can be no second thread running --
from the spin_lock to the spin_unlock, the one CPU is executing this thread
and only this thread, because Linux kernel code is not preempted.

(Note that recent kernels do enable preemption within kernel mode --
but then spin_lock is no longer a no-op even on UP, but will contain
code to temporarily switch off preemption until the spin_unlock.)

--
  Dr. Ulrich Weigand

 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by Michael Schnel » Thu, 25 Mar 2004 17:35:46


Quote:> But it does work.  

I suppose he did not know that spin_lock() can only be used within the
kernel where (traditionally) task switching is disabled.

-Michael

 
 
 

spin_lock()/spin_lock_irqsave() on UP and SMP machine

Post by tcs » Fri, 26 Mar 2004 22:58:28


Oh, this one is right on the target!
I really didn't know and spin lock makes sense now.

techeng


Quote:> > But it does work.

> I suppose he did not know that spin_lock() can only be used within the
> kernel where (traditionally) task switching is disabled.

> -Michael