On Wed, Mar 5, 2008 at 4:34 AM, Lukas Razik <[EMAIL PROTECTED]> wrote:
> Hello all!
>
> In a work handler (of a work queue) I want to avoid the concurrently
> usage of a socket (because there can be more worker-threads on a SMP
> system)...
>
> My first idea was to use spin_lock_irqsave in the work handler:
> ...
> spin_lock_irqsave(&tx_d->lock, flags);
> sock_sendmsg(...);
> spin_unlock_irqrestore(&tx_d->lock, flags);
> ...
> but if I do that, I get this message from the kernel:
> BUG: warning at kernel/softirq.c:137/local_bh_enable()
> [<b0121808>] local_bh_enable+0x38/0x79
> [<b021d445>] lock_sock+0x89/0x91
> [<b016ebb0>] mntput_no_expire+0x11/0x6a
> [<b025cc6a>] inet_autobind+0x8/0x52
> [<b025d5de>] inet_sendmsg+0x1c/0x3f
> [<b021b1d7>] sock_sendmsg+0xce/0xe8
> [<b012d65d>] autoremove_wake_function+0x0/0x2d
> [<b01165c6>] __wake_up_sync+0x31/0x4b
> [<f0b27c60>] ethos_tx_action+0x1f0/0x280 [ethos]
> [<b01176ab>] try_to_wake_up+0x355/0x35f
> [<b012a960>] run_workqueue+0x72/0xaf
> [<f0b27a70>] ethos_tx_action+0x0/0x280 [ethos]
> [<b012b220>] worker_thread+0xd9/0x10d
> [<b01176b5>] default_wake_function+0x0/0xc
> [<b012b147>] worker_thread+0x0/0x10d
> [<b012d591>] kthread+0xc2/0xed
> [<b012d4cf>] kthread+0x0/0xed
> [<b0101005>] kernel_thread_helper+0x5/0xb
>
>From the stack trace, the warning are generated by the
"WARN_ON_ONCE(irqs_disabled());" line below. This is because u have
disabled IRQ. But this function can be used both with and without it
being enabled. If
void local_bh_enable(void)
{
#ifdef CONFIG_TRACE_IRQFLAGS
unsigned long flags;
WARN_ON_ONCE(in_irq());
#endif
WARN_ON_ONCE(irqs_disabled());
#ifdef CONFIG_TRACE_IRQFLAGS
local_irq_save(flags);
#endif
/*
* Are softirqs going to be turned on now:
*/
if (softirq_count() == SOFTIRQ_OFFSET)
trace_softirqs_on((unsigned long)__builtin_return_address(0));
/*
* Keep preemption disabled until we are done with
* softirq processing:
*/
sub_preempt_count(SOFTIRQ_OFFSET - 1);
if (unlikely(!in_interrupt() && local_softirq_pending()))
do_softirq();
dec_preempt_count();
#ifdef CONFIG_TRACE_IRQFLAGS
local_irq_restore(flags);
#endif
preempt_check_resched();
}
>
> Then I tried:
> ...
> spin_lock(&tx_d->lock);
> sock_sendmsg(...);
> spin_unlock(&tx_d->lock);
> ...
> and I get no error messages anymore but now a nice person asked me if
> that's safe and I think it isn't because interrupts are on in work
> handlers or not?
>
spin locks are for very quick turnaround usage. meaning that if u
apply spin lock, and call some API (like sock_send() is, IMHO, an
example, as verified by the long chain of functions listed in the
stack trace above) that is going to take some time, that is u may end
up another CPU spinning on the spin-locks - meaning the CPU will go
into 100% utilization number.
Most important is this - never use spin locks whenever u call
something that can sleep. Not sure if local_bh_enabled() can sleep
or not, most likely YES, because preempt_check_resched() is meant for
rescheduling, is likely to allow sleeping. And u wrap a sleepable
function around a spin lock - that is the scenario of the classic "CPU
100% usage" bug.
I think a mutex_lock() is better. What others think?
> So why do I get the error message?
> What can I use instead of spin_lock_irqsave?
>
> Many Thanks for your answers!
>
> Best regards
> Lukas
>
--
Regards,
Peter Teoh
--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [EMAIL PROTECTED]
Please read the FAQ at http://kernelnewbies.org/FAQ