ALT Linux kernel packages development
 help / color / mirror / Atom feed
From: gosha <embedded@nm.ru>
To: devel-kernel@lists.altlinux.org
Subject: Re: [d-kernel] -немного недопонял, - В kernel 2.6.16 теперь ждущие  блокировки spinlock()  не работают?] (Sergey Vlasov)
Date: Mon, 19 Jun 2006 14:27:41 +0000
Message-ID: <146102371.20060619142741@nm.ru> (raw)
In-Reply-To: <mailman.17.1150606807.13795.devel-kernel@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




      parent reply	other threads:[~2006-06-19 14:27 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-06-19  9:20 ` gosha
2006-06-19 10:04   ` Sergey Vlasov
2006-06-19 14:27 ` gosha [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=146102371.20060619142741@nm.ru \
    --to=embedded@nm.ru \
    --cc=devel-kernel@lists.altlinux.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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