* spin-locks
@ 2002-05-10 12:58 Richard B. Johnson
2002-05-10 13:24 ` spin-locks Keith Owens
0 siblings, 1 reply; 5+ messages in thread
From: Richard B. Johnson @ 2002-05-10 12:58 UTC (permalink / raw)
To: Linux kernel
Greetings lock wizards
I have discovered some things that I don't understand.
First, if I create a spin-lock in the ".data" segment it
doesn't work on a SMP machine with two CPUs. I know I am
supposed to use the macros, but I have some high-speed stuff
written in assembly that needs a spin-lock. The 'doesn't work'
is that the spin-lock seems to dead-lock, i.e., they loop
forever with the interrupts disabled. I think what's really
happening is that .data was paged and can't be paged back in
with the interrupts off. I don't know. This stuff used to
work....
In earlier versions of Linux, the locks were in .text_lock.
Now they are in : _text_lock_KBUILD_BASENAME
So, what is special about this area that allows locks to work?
And, what is special about .data that prevents them from working?
Also, there is a potential bug (ducks and hides under the desk) in
the existing spin-lock unlocking. To unlock, the lock is simply
set to 1. This works if you have two CPUs, but what about more?
Shouldn't the lock/unlock just be incremented/decremented so 'N' CPUs
can pound on it?
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Windows-2000/Professional isn't.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: spin-locks
2002-05-10 12:58 spin-locks Richard B. Johnson
@ 2002-05-10 13:24 ` Keith Owens
2002-05-10 14:06 ` spin-locks Richard B. Johnson
0 siblings, 1 reply; 5+ messages in thread
From: Keith Owens @ 2002-05-10 13:24 UTC (permalink / raw)
To: Linux kernel
On Fri, 10 May 2002 08:58:47 -0400 (EDT),
"Richard B. Johnson" <root@chaos.analogic.com> wrote:
>First, if I create a spin-lock in the ".data" segment it
>doesn't work on a SMP machine with two CPUs. I know I am
>supposed to use the macros, but I have some high-speed stuff
>written in assembly that needs a spin-lock. The 'doesn't work'
>is that the spin-lock seems to dead-lock, i.e., they loop
>forever with the interrupts disabled. I think what's really
>happening is that .data was paged and can't be paged back in
>with the interrupts off. I don't know. This stuff used to
>work....
Kernel .data sections are not paged. They are identity[*] mapped along
with the rest of the kernel text and data and are locked down.
[*] Ignoring NUMA machines which may use non-identity mappings on each
node.
>In earlier versions of Linux, the locks were in .text_lock.
>Now they are in : _text_lock_KBUILD_BASENAME
Not quite. They were all in section .text.lock but that broke when
binutils started detecting dangling references to discarded sections.
The fix was to store the lock code in the same section that called the
lock, so .text locks are in the .text section, .text.exit locks are in
the .text.exit section, no dangling references when .text.exit is
discarded.
The locks are now at the end of the section that references the lock,
preceded by a label (not a section) of _text_lock_KBUILD_BASENAME.
>So, what is special about this area that allows locks to work?
There is nothing special about the text lock code. It is just moving
the failure path out of line to speed up the normal case.
>And, what is special about .data that prevents them from working?
Again nothing. The spin lock area goes in .data, the code goes in the
relevant text section.
>Also, there is a potential bug (ducks and hides under the desk) in
>the existing spin-lock unlocking. To unlock, the lock is simply
>set to 1. This works if you have two CPUs, but what about more?
>
>Shouldn't the lock/unlock just be incremented/decremented so 'N' CPUs
>can pound on it?
Spinlocks are single cpu. Only one cpu at a time can modify the data
that is being protected by obtaining the lock.
>From your description, you are confused about spinlocking. Perhaps if
you mailed your code instead of assuming where the error was ...
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: spin-locks
2002-05-10 13:24 ` spin-locks Keith Owens
@ 2002-05-10 14:06 ` Richard B. Johnson
2002-05-10 14:17 ` spin-locks David Woodhouse
0 siblings, 1 reply; 5+ messages in thread
From: Richard B. Johnson @ 2002-05-10 14:06 UTC (permalink / raw)
To: Keith Owens; +Cc: Linux kernel
On Fri, 10 May 2002, Keith Owens wrote:
> On Fri, 10 May 2002 08:58:47 -0400 (EDT),
> "Richard B. Johnson" <root@chaos.analogic.com> wrote:
> >First, if I create a spin-lock in the ".data" segment it
> >doesn't work on a SMP machine with two CPUs. I know I am
> >supposed to use the macros, but I have some high-speed stuff
> >written in assembly that needs a spin-lock. The 'doesn't work'
> >is that the spin-lock seems to dead-lock, i.e., they loop
> >forever with the interrupts disabled. I think what's really
> >happening is that .data was paged and can't be paged back in
> >with the interrupts off. I don't know. This stuff used to
> >work....
>
> Kernel .data sections are not paged. They are identity[*] mapped along
> with the rest of the kernel text and data and are locked down.
>
> [*] Ignoring NUMA machines which may use non-identity mappings on each
> node.
>
> >In earlier versions of Linux, the locks were in .text_lock.
> >Now they are in : _text_lock_KBUILD_BASENAME
>
> Not quite. They were all in section .text.lock but that broke when
> binutils started detecting dangling references to discarded sections.
>
> The fix was to store the lock code in the same section that called the
> lock, so .text locks are in the .text section, .text.exit locks are in
> the .text.exit section, no dangling references when .text.exit is
> discarded.
>
> The locks are now at the end of the section that references the lock,
> preceded by a label (not a section) of _text_lock_KBUILD_BASENAME.
>
> >So, what is special about this area that allows locks to work?
>
> There is nothing special about the text lock code. It is just moving
> the failure path out of line to speed up the normal case.
>
> >And, what is special about .data that prevents them from working?
>
> Again nothing. The spin lock area goes in .data, the code goes in the
> relevant text section.
>
> >Also, there is a potential bug (ducks and hides under the desk) in
> >the existing spin-lock unlocking. To unlock, the lock is simply
> >set to 1. This works if you have two CPUs, but what about more?
> >
> >Shouldn't the lock/unlock just be incremented/decremented so 'N' CPUs
> >can pound on it?
>
> Spinlocks are single cpu. Only one cpu at a time can modify the data
> that is being protected by obtaining the lock.
>
> >From your description, you are confused about spinlocking. Perhaps if
> you mailed your code instead of assuming where the error was ...
Well, here is code that worked on linux 2.2.17. Same CPUs, same
everything... Just a different version of OS...
In this code, any CPU will modify (increment) the lock so we can
only have 255 CPUs before this fails <grin>...
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
.section .data
lrm_tickl: .long 0
lrm_tickh: .long 0
lockf: .byte 0
.section .text
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
# This reads the rapidly-changing tick-value and returns it as a
# long long. The output value is in carefully calculated miliseconds.
#
.global lrm_tick
.type lrm_tick,@function
.align 0x04
lrm_tick:
pushf # Restored at the end
cli
lock
incb (lockf) # Bump lock-value
1: cmpb $1,(lockf) # See if we own it
jnz 1b # Nope, spin until we do.
pushl %ebx # Save non-volatile registers
pushl %ecx
pushl %esi
pushl %edi
#
# Locks no longer work so I have to do this hack......
#
2: movl (lrm_tickl), %eax
movl (lrm_tickh), %edx
cmpl (lrm_tickl), %eax
jnz 2b
cmpl (lrm_tickh), %edx
jnz 2b
#
# Okay, we have a stable tick. Now, it's 2048 ticks/second instead
# of 1,000 ticks. Therefore we have to multiply by 1,000 and and
# divide by 2048 to get the millisecond count.
#
xorl %esi, %esi # For overflow
movl %eax, %ebx # Save times 1 low lword
movl %edx, %ecx # Save times 1 high lword
movl %esi, %edi # Save overflow
#
shl $1, %eax # Times 2
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
shl $1, %eax # Times 4
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
addl %ebx, %eax # Add the times 1 low lword
adcl %ecx, %edx # Add the times 1 high lword
adcl %edi, %esi # Add the times 1 overflow
# Now times 5
#
shl $1, %eax # Times 10
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
movl %eax, %ebx # Save times 10 low lword
movl %edx, %ecx # Save times 10 high lword
movl %esi, %edi # Save overflow
#
shl $1, %eax # Times 20
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
shl $1, %eax # Times 40
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
addl %ebx, %eax # Add the times 10 low lword
adcl %ecx, %edx # Add the times 10 high lword
adcl %edi, %esi # Add the times 10 overflow
# Now times 50
#
shl $1, %eax # Times 100
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
movl %eax, %ebx # Save times 100 low lword
movl %edx, %ecx # Save times 100 high lword
movl %esi, %edi # Save overflow
#
shl $1, %eax # Times 200
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
shl $1, %eax # Times 400
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
addl %ebx, %eax # Add the times 100 low lword
adcl %ecx, %edx # Add the times 100 high lword
adcl %edi, %esi # Add the times 100 overflow
# Now times 500
#
shl $1, %eax # Times 1000
adcl $0, %edx # Take care of CY
adcl $0, %esi # Take care of overflow
#
# Now do the division (2^11) and yes, I do know about loops.
#
shrl $1, %esi
rcrl $1, %edx # Div by 2
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 4
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 8
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 16
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 32
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 64
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 128
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 256
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 512
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 1024
rcrl $1, %eax
#
shrl $1, %esi
rcrl $1, %edx # Div by 2048
rcrl $1, %eax
#
# Return long-long in EAX:EDX
#
popl %edi
popl %esi
popl %ecx # Restore registers used
popl %ebx
lock
decb (lockf) # Release lock
popf
ret
.end
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Windows-2000/Professional isn't.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: spin-locks
2002-05-10 14:06 ` spin-locks Richard B. Johnson
@ 2002-05-10 14:17 ` David Woodhouse
2002-05-10 14:28 ` spin-locks Richard B. Johnson
0 siblings, 1 reply; 5+ messages in thread
From: David Woodhouse @ 2002-05-10 14:17 UTC (permalink / raw)
To: root; +Cc: Keith Owens, Linux kernel
root@chaos.analogic.com said:
> Well, here is code that worked on linux 2.2.17. Same CPUs, same
> everything... Just a different version of OS...
I suspect your code was protected by the BKL in 2.2.17, not by your
'spinlocks'.
root@chaos.analogic.com said:
> cli
> lock
> incb (lockf) # Bump lock-value
Ponder what happens if two CPUs get here at the same time. Lock count is
now two.
> 1: cmpb $1,(lockf) # See if we own it
> jnz 1b # Nope, spin until we do.
Now they both spin forever.
--
dwmw2
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: spin-locks
2002-05-10 14:17 ` spin-locks David Woodhouse
@ 2002-05-10 14:28 ` Richard B. Johnson
0 siblings, 0 replies; 5+ messages in thread
From: Richard B. Johnson @ 2002-05-10 14:28 UTC (permalink / raw)
To: David Woodhouse; +Cc: Keith Owens, Linux kernel
On Fri, 10 May 2002, David Woodhouse wrote:
>
> root@chaos.analogic.com said:
> > Well, here is code that worked on linux 2.2.17. Same CPUs, same
> > everything... Just a different version of OS...
>
> I suspect your code was protected by the BKL in 2.2.17, not by your
> 'spinlocks'.
>
> root@chaos.analogic.com said:
> > cli
> > lock
> > incb (lockf) # Bump lock-value
>
> Ponder what happens if two CPUs get here at the same time. Lock count is
> now two.
>
> > 1: cmpb $1,(lockf) # See if we own it
> > jnz 1b # Nope, spin until we do.
>
> Now they both spin forever.
Yep. You are correct. Obvious bug that went undetected for over
a year.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Windows-2000/Professional isn't.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-05-10 14:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-10 12:58 spin-locks Richard B. Johnson
2002-05-10 13:24 ` spin-locks Keith Owens
2002-05-10 14:06 ` spin-locks Richard B. Johnson
2002-05-10 14:17 ` spin-locks David Woodhouse
2002-05-10 14:28 ` spin-locks Richard B. Johnson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®