* Re: [d-kernel] -немного недопонял, - В kernel 2.6.16 теперь ждущие блокировки spinlock() не работают?] (Sergey Vlasov)
@ 2006-06-19 9:20 ` gosha
2006-06-19 10:04 ` Sergey Vlasov
2006-06-19 14:27 ` gosha
1 sibling, 1 reply; 3+ messages in thread
From: gosha @ 2006-06-19 9:20 UTC (permalink / raw)
To: devel-kernel-request@lists.altlinux.org
Здравствуйте.
>Значит, этот тест был выполнен на ядре *-up, где spin_lock()
>действительно ничего не делает. Spinlock используются только на SMP
>для синхронизации между несколькими процессорами. Код, пытающийся
>рекурсивно захватить один и тот же spinlock на одном процессоре,
>недопустим - это гарантированный deadlock.
> И в include/linux/spinlock*.h ничего похожего на разблокировку/ блокировку ....
>Все реализации spinlock архитектурно-зависимые, и поэтому лежат в
>include/asm-*.
фрагмент include/linux/spinlock.h :
-------------------------------------------------------
#if defined(CONFIG_SMP)
# include <asm/spinlock.h> // прикомпилируются только в случае многопроцессорных систем
#else
# include <linux/spinlock_up.h>
#endif
-------------------------------------------------------
фрагмент include/linux/compiler.h :
-------------------------------------------------------
#ifdef __CHECKER__
....................
# define __acquire(x) __context__(1)
# define __release(x) __context__(-1)
#else
..........................
# define __acquire(x) (void)0
# define __release(x) (void)0
#endif
-------------------------------------------------------
фрагмент include/linux/spinlock_api.h:
-------------------------------------------------------
#define __LOCK(lock) do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)
#define __UNLOCK(lock) do { preempt_enable(); __release(lock); (void)(lock); } while (0)
#define _spin_lock(lock) __LOCK(lock)
#define _spin_unlock(lock) __UNLOCK(lock)
-------------------------------------------------------
Т.е. для однопроцессорных систем ждущие блокировки spinlock() и не должны ничего делать в
принципе?? Судя по коду это так, но это как бы нелогично...
Напр касок кода /kernel/irq/hahdle.c :
-------------------------------------------------------
/* do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts have their own specific handlers). */
fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
{
irq_desc_t *desc = irq_desc + irq;
struct irqaction * action;
unsigned int status;
kstat_this_cpu.irqs[irq]++;
if (CHECK_IRQ_PER_CPU(desc->status)) {
irqreturn_t action_ret;
/* No locking required for CPU-local interrupts: */
if (desc->handler->ack)
desc->handler->ack(irq);
action_ret = handle_IRQ_event(irq, regs, desc->action);
desc->handler->end(irq);
return 1;
}
spin_lock(&desc->lock);
if (desc->handler->ack)
desc->handler->ack(irq);
/*
* REPLAY is when Linux resends an IRQ that was dropped earlier
* WAITING is used by probe to mark irqs that are being tested
*/
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
status |= IRQ_PENDING; /* we _want_ to handle it */
/*
* If the IRQ is disabled for whatever reason, we cannot
* use the action we have.
*/
action = NULL;
if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
action = desc->action;
status &= ~IRQ_PENDING; /* we commit to handling */
status |= IRQ_INPROGRESS; /* we are handling it */
}
desc->status = status;
/*
* If there is no IRQ handler or it was disabled, exit early.
* Since we set PENDING, if another processor is handling
* a different instance of this same irq, the other processor
* will take care of it.
*/
if (unlikely(!action))
goto out;
/*
* Edge triggered interrupts need to remember
* pending events.
* This applies to any hw interrupts that allow a second
* instance of the same irq to arrive while we are in do_IRQ
* or in the handler. But the code here only handles the _second_
* instance of the irq, not the third or fourth. So it is mostly
* useful for irq hardware that does not mask cleanly in an
* SMP environment.
*/
for (;;) {
irqreturn_t action_ret;
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, regs, action);
spin_lock(&desc->lock);
if (!noirqdebug)
note_interrupt(irq, desc, action_ret, regs);
if (likely(!(desc->status & IRQ_PENDING)))
break;
desc->status &= ~IRQ_PENDING;
}
desc->status &= ~IRQ_INPROGRESS;
out:
/*
* The ->end() handler has to deal with interrupts which got
* disabled while the handler was running.
*/
desc->handler->end(irq);
spin_unlock(&desc->lock);
return 1;
}
---------------------------------------------------------------------------
Также все работает в режиме CONFIG_DEBUG_SPINLOCK :
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
# include <linux/spinlock_api_smp.h>
#else
# include <linux/spinlock_api_up.h>
#endif
---------------------------------------------------------------------------
Так и должно быть??? У меня во всех книжках по линуксу написано, что это ждущая блокировка
и оно должно работать как мутекс!
---------------------------------------------------------------------------
--
С Уважением,
gosha
mailto:embedded@nm.ru
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [d-kernel] -немного недопонял, - В kernel 2.6.16 теперь ждущие блокировки spinlock() не работают?] (Sergey Vlasov)
2006-06-19 9:20 ` [d-kernel] -немного недопонял, - В kernel 2.6.16 теперь ждущие блокировки spinlock() не работают?] (Sergey Vlasov) gosha
@ 2006-06-19 10:04 ` Sergey Vlasov
0 siblings, 0 replies; 3+ messages in thread
From: Sergey Vlasov @ 2006-06-19 10:04 UTC (permalink / raw)
To: gosha, ALT Linux kernel packages development
[-- Attachment #1: Type: text/plain, Size: 2567 bytes --]
On Mon, Jun 19, 2006 at 09:20:20AM +0000, gosha wrote:
> >Значит, этот тест был выполнен на ядре *-up, где spin_lock()
> >действительно ничего не делает. Spinlock используются только на SMP
> >для синхронизации между несколькими процессорами. Код, пытающийся
> >рекурсивно захватить один и тот же spinlock на одном процессоре,
> >недопустим - это гарантированный deadlock.
>
> > И в include/linux/spinlock*.h ничего похожего на разблокировку/ блокировку ....
>
> >Все реализации spinlock архитектурно-зависимые, и поэтому лежат в
> >include/asm-*.
[...]
> Т.е. для однопроцессорных систем ждущие блокировки spinlock() и не
> должны ничего делать в принципе?? Судя по коду это так, но это как бы
> нелогично...
И что здесь нелогичного? Блокировки этого типа предназначены только для
синхронизации на SMP, при наличии только одного процессора ждать просто
нечего.
> Напр касок кода /kernel/irq/hahdle.c :
> -------------------------------------------------------
> /* do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts have their own specific handlers). */
> fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
[...]
spin_lock здесь обеспечивает защиту от модификации данных другими
процессорами; предполагается, что на одном и том же процессоре __do_IRQ()
не может быть вызвана рекурсивно для обработки того же самого прерывания.
> Также все работает в режиме CONFIG_DEBUG_SPINLOCK :
[...]
Да, это сделано специально, чтобы была хоть какая-то возможность
отлавливать некоторые ошибки в использовании spinlock без SMP.
> Так и должно быть??? У меня во всех книжках по линуксу написано, что это
> ждущая блокировка и оно должно работать как мутекс!
spinlock и mutex в Linux - существенно разные типы блокировок. Блокировки
типа semaphore/mutex могут использоваться только в том случае, если
допускается переход в состояние ожидания (sleep) - в случае, если mutex
уже занят другим процессом, выполняется переключение контекста на один из
других процессов, готовых к выполнению. В случае spinlock выполняется
просто ожидание освобождения в цикле без переключения контекста - поэтому
spinlock может использоваться, например, в обработчике прерываний.
Вообще, если в однопроцессорной системе процессор ожидает освобождения
spinlock-а, освободить его теоретически мог бы только какой-то обработчик
прерывания (если прерывания в этот момент разрешены), но подобное
использование spinlock считается ошибкой, поэтому поведение их в подобном
случае может быть любым.
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [d-kernel] -немного недопонял, - В kernel 2.6.16 теперь ждущие блокировки spinlock() не работают?] (Sergey Vlasov)
2006-06-19 9:20 ` [d-kernel] -немного недопонял, - В kernel 2.6.16 теперь ждущие блокировки spinlock() не работают?] (Sergey Vlasov) gosha
@ 2006-06-19 14:27 ` gosha
1 sibling, 0 replies; 3+ messages in thread
From: gosha @ 2006-06-19 14:27 UTC (permalink / raw)
To: devel-kernel
>Значит, этот тест был выполнен на ядре *-up, где spin_lock()
>действительно ничего не делает. Spinlock используются только на SMP
>для синхронизации между несколькими процессорами. Код, пытающийся
>рекурсивно захватить один и тот же spinlock на одном процессоре,
>недопустим - это гарантированный deadlock.
> И в include/linux/spinlock*.h ничего похожего на разблокировку/ блокировку ....
>Все реализации spinlock архитектурно-зависимые, и поэтому лежат в
>include/asm-*.
фрагмент include/linux/spinlock.h :
-------------------------------------------------------
#if defined(CONFIG_SMP)
# include <asm/spinlock.h> // прикомпилируются только в случае многопроцессорных систем
#else
# include <linux/spinlock_up.h>
#endif
-------------------------------------------------------
фрагмент include/linux/compiler.h :
-------------------------------------------------------
#ifdef __CHECKER__
....................
# define __acquire(x) __context__(1)
# define __release(x) __context__(-1)
#else
..........................
# define __acquire(x) (void)0
# define __release(x) (void)0
#endif
-------------------------------------------------------
фрагмент include/linux/spinlock_api.h:
-------------------------------------------------------
#define __LOCK(lock) do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)
#define __UNLOCK(lock) do { preempt_enable(); __release(lock); (void)(lock); } while (0)
#define _spin_lock(lock) __LOCK(lock)
#define _spin_unlock(lock) __UNLOCK(lock)
-------------------------------------------------------
Т.е. для однопроцессорных систем ждущие блокировки spinlock() и не должны ничего делать в
принципе?? Судя по коду это так, но это как бы нелогично...
Напр касок кода /kernel/irq/hahdle.c :
-------------------------------------------------------
/* do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts have their own specific handlers). */
fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
{
irq_desc_t *desc = irq_desc + irq;
struct irqaction * action;
unsigned int status;
kstat_this_cpu.irqs[irq]++;
if (CHECK_IRQ_PER_CPU(desc->status)) {
irqreturn_t action_ret;
/* No locking required for CPU-local interrupts: */
if (desc->handler->ack)
desc->handler->ack(irq);
action_ret = handle_IRQ_event(irq, regs, desc->action);
desc->handler->end(irq);
return 1;
}
spin_lock(&desc->lock);
if (desc->handler->ack)
desc->handler->ack(irq);
/*
* REPLAY is when Linux resends an IRQ that was dropped earlier
* WAITING is used by probe to mark irqs that are being tested
*/
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
status |= IRQ_PENDING; /* we _want_ to handle it */
/*
* If the IRQ is disabled for whatever reason, we cannot
* use the action we have.
*/
action = NULL;
if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
action = desc->action;
status &= ~IRQ_PENDING; /* we commit to handling */
status |= IRQ_INPROGRESS; /* we are handling it */
}
desc->status = status;
/*
* If there is no IRQ handler or it was disabled, exit early.
* Since we set PENDING, if another processor is handling
* a different instance of this same irq, the other processor
* will take care of it.
*/
if (unlikely(!action))
goto out;
/*
* Edge triggered interrupts need to remember
* pending events.
* This applies to any hw interrupts that allow a second
* instance of the same irq to arrive while we are in do_IRQ
* or in the handler. But the code here only handles the _second_
* instance of the irq, not the third or fourth. So it is mostly
* useful for irq hardware that does not mask cleanly in an
* SMP environment.
*/
for (;;) {
irqreturn_t action_ret;
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, regs, action);
spin_lock(&desc->lock);
if (!noirqdebug)
note_interrupt(irq, desc, action_ret, regs);
if (likely(!(desc->status & IRQ_PENDING)))
break;
desc->status &= ~IRQ_PENDING;
}
desc->status &= ~IRQ_INPROGRESS;
out:
/*
* The ->end() handler has to deal with interrupts which got
* disabled while the handler was running.
*/
desc->handler->end(irq);
spin_unlock(&desc->lock);
return 1;
}
---------------------------------------------------------------------------
Также все работает в режиме CONFIG_DEBUG_SPINLOCK :
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
# include <linux/spinlock_api_smp.h>
#else
# include <linux/spinlock_api_up.h>
#endif
---------------------------------------------------------------------------
Так и должно быть??? У меня во всех книжках по линуксу написано, что это ждущая блокировка
и оно должно работать как мутекс!
---------------------------------------------------------------------------
--
С Уважением,
gosha
mailto:embedded@nm.ru
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2006-06-19 14:27 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-19 9:20 ` [d-kernel] -немного недопонял, - В kernel 2.6.16 теперь ждущие блокировки spinlock() не работают?] (Sergey Vlasov) gosha
2006-06-19 10:04 ` Sergey Vlasov
2006-06-19 14:27 ` gosha
ALT Linux kernel packages development
This inbox may be cloned and mirrored by anyone:
git clone --mirror http://lore.altlinux.org/devel-kernel/0 devel-kernel/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 devel-kernel devel-kernel/ http://lore.altlinux.org/devel-kernel \
devel-kernel@altlinux.org devel-kernel@altlinux.ru devel-kernel@altlinux.com
public-inbox-index devel-kernel
Example config snippet for mirrors.
Newsgroup available over NNTP:
nntp://lore.altlinux.org/org.altlinux.lists.devel-kernel
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git