Damien Zammit, le ven. 11 juil. 2025 06:56:30 +0000, a ecrit:
> This avoids race condition with multiple devices raising interrupts
> simultaneously on the same IRQ and causing mask to fail.
>
> TESTED: on SMP and UP+apic gnumach, boots to console and receives
> a large file over rumpnet on debian hurd-i386.
Applied, thanks!
> ---
> i386/i386/irq.c | 49 ++++++++++++++++++++++++++++++++---------
> i386/i386/irq.h | 1 +
> i386/i386at/model_dep.c | 1 +
> 3 files changed, 40 insertions(+), 11 deletions(-)
>
> diff --git a/i386/i386/irq.c b/i386/i386/irq.c
> index 91318f67..6268db18 100644
> --- a/i386/i386/irq.c
> +++ b/i386/i386/irq.c
> @@ -34,32 +34,59 @@ irq_eoi (struct irqdev *dev, int id)
> #endif
> }
>
> -static unsigned int ndisabled_irq[NINTR];
> +/* Each array elem fits in a cache line */
> +struct nested_irq {
> + simple_lock_irq_data_t irq_lock;
> + int32_t ndisabled;
> + uint32_t unused[14];
> +} __attribute__((packed)) nested_irqs[NINTR];
> +
> +void
> +init_irqs (void)
> +{
> + int i;
> +
> + for (i = 0; i < NINTR; i++)
> + {
> + simple_lock_init_irq(&nested_irqs[i].irq_lock);
> + nested_irqs[i].ndisabled = 0;
> + }
> +}
>
> void
> __disable_irq (irq_t irq_nr)
> {
> + spl_t s;
> + struct nested_irq *nirq = &nested_irqs[irq_nr];
> +
> assert (irq_nr < NINTR);
>
> - spl_t s = splhigh();
> - ndisabled_irq[irq_nr]++;
> - assert (ndisabled_irq[irq_nr] > 0);
> - if (ndisabled_irq[irq_nr] == 1)
> + s = simple_lock_irq(&nirq->irq_lock);
> +
> + nirq->ndisabled++;
> + assert (nirq->ndisabled > 0);
> + if (nirq->ndisabled == 1)
> mask_irq (irq_nr);
> - splx(s);
> +
> + simple_unlock_irq(s, &nirq->irq_lock);
> }
>
> void
> __enable_irq (irq_t irq_nr)
> {
> + spl_t s;
> + struct nested_irq *nirq = &nested_irqs[irq_nr];
> +
> assert (irq_nr < NINTR);
>
> - spl_t s = splhigh();
> - assert (ndisabled_irq[irq_nr] > 0);
> - ndisabled_irq[irq_nr]--;
> - if (ndisabled_irq[irq_nr] == 0)
> + s = simple_lock_irq(&nirq->irq_lock);
> +
> + assert (nirq->ndisabled > 0);
> + nirq->ndisabled--;
> + if (nirq->ndisabled == 0)
> unmask_irq (irq_nr);
> - splx(s);
> +
> + simple_unlock_irq(s, &nirq->irq_lock);
> }
>
> struct irqdev irqtab = {
> diff --git a/i386/i386/irq.h b/i386/i386/irq.h
> index 72bbe57b..e1f41045 100644
> --- a/i386/i386/irq.h
> +++ b/i386/i386/irq.h
> @@ -23,6 +23,7 @@
>
> typedef unsigned int irq_t;
>
> +void init_irqs (void);
> void __enable_irq (irq_t irq);
> void __disable_irq (irq_t irq);
>
> diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
> index 42dadeb8..afb4fadd 100644
> --- a/i386/i386at/model_dep.c
> +++ b/i386/i386at/model_dep.c
> @@ -176,6 +176,7 @@ void machine_init(void)
> #if defined(APIC)
> ioapic_configure();
> #endif
> + init_irqs();
> clkstart();
>
> /*
> --
> 2.45.2
>
>
>
--
Samuel
AUTHOR
FvwmM4 is the result of a random bit mutation on a hard
disk, presumably a result of a cosmic-ray or some such
thing.
(extrait de la page de man de FvwmM4)