* 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