html5-img
1 / 13

Race Condition

제 43 강 : Interrupt(III) Race Condition. Race Condition. Race Condition. New IRQ request should guarantee minimum time for previous IRQ processing Interrupt disables further CPU interrupt local_irq_enable() reenables CPU interrupt. ‘. CPU. CPU. CPU. CPU. shared memory. PIC.

Télécharger la présentation

Race Condition

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 제43강 : Interrupt(III) Race Condition Race Condition

  2. Race Condition New IRQ request should guarantee minimum time for previous IRQ processing Interrupt disables further CPU interrupt local_irq_enable()reenablesCPU interrupt ‘ CPU CPU CPU CPU shared memory PIC irq_desc[ ] ISR timer IRQ Hard Disk IRQ1 Network IRQ2 action g1() g2() Floppy Disk IRQ3 SCSI action IRQm f1() f2() Many IRQ lines are competing for PIC Interrupt disables PIC ack(irq) reenables PIC operation Many CPU’s are competing to access shared variablespin_lock( ) spin_unlock( )

  3. CPUi do_IRQ() ack() access selected irq_desc[IRQm] PIC request CPUk access released from IRQm selected irq_desc[IRQm] do-IRQ() – critical section irq_desc[IRQm] becomes a shared variable do_IRQ() becomes critical section needmutual exclusion by spinlock() must run atomically should not be preempted in the middle  CPU interrupt disabled

  4. ISR is not a critical section CPU CPU CPU CPU CPU shared memory PIC irq_desc[ ] ISR timer Hard Disk IRQ IRQ1 Network IRQ2 action g1() g2() Floppy Disk IRQ3 SCSI action IRQm f1() f2() handle_IRQ_event() is not a critical section because IRQm requests are serialized at particular CPUk spin-unlock() before entering handle_IRQ_event() CPU interrupt enabledbefore entering handle_IRQ_event() do_IRQ() handle_IRQ_event() Multiple CPU’s compete for irq_desc[IRQm] irq_desc[IRQm] becomes a shared variable do_IRQ() is a critical section mutual exclusion byspinlock() do_IRQ() must run atomically should not be preempted in the middle  CPU interrupt disabled

  5. irq_desc[ ] ISR timer IRQ1 Network IRQ2 action g1() g2() IRQ3 SCSI action IRQm f1() f2() asmlinkage unsigned int do_IRQ(struct pt_regs regs) { int irq = regs.orig_eax & 0xff; /* get irq vector on stack, put it into local variable */ irq_desc_t *desc = irq_desc + irq; /* pointer to array */ struct irqaction * action; unsigned int status; irq_enter(); kstat_this_cpu.irqs[irq]++; spin_lock(&desc->lock); /* wait if locked */ desc->handler->ack(irq); status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); /* dev not waiting any more*/ status |= IRQ_PENDING; /* Ack’ed. Need to handle it. */ action = NULL; /* initial value for action == NULL */ if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { action = desc->action; status &= ~IRQ_PENDING; status |= IRQ_INPROGRESS; } descstatus = status; if (unlikely(!action)) goto out; /* If nothing has been assigned to action, do nothing */

  6. irq_desc[ ] ISR timer IRQ1 Network IRQ2 action g1() g2() IRQ3 SCSI action IRQm f1() f2() for (;;) { irqreturn_t action_ret; spin_unlock(&desc->lock); action_ret = handle_IRQ_event(irq, &regs, action); /* call handler */ spin_lock(&desc->lock); if (!noirqdebug) note_interrupt(irq, desc, action_ret); if (likely(!(desc->status & IRQ_PENDING)))/*Re-check PENDING. I cleared before*/ break; /* It remains in reset state. Exit do_IRQ() */ desc->status &= ~IRQ_PENDING; /* New arrival. I handle it. Still INPROGRESS */ } desc->status &= ~IRQ_INPROGRESS; /* No longer INPROGRESS */ out: desc->handler->end(irq); spin_unlock(&desc->lock); irq_exit(); return 1; }

  7. irq_desc[ ] ISR timer IRQ1 Network IRQ2 action g1() g2() IRQ3 SCSI action IRQm f1() f2() int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) { int status = 1; /* Force the "do bottom halves" bit */ int retval = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= action->flags; retval |= action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); return retval; } ISR is device specific operation ISR does not share variable ISR is not a critical section ISR execution does not have to be atomic This CPU may be interrupted while in ISR PIC can interrupt this CPU while it is running ISR

  8. asmlinkage unsigned int do_IRQ(struct pt_regs regs) { int irq = regs.orig_eax & 0xff; irq_desc_t *desc = irq_desc + irq; struct irqaction * action; unsigned int status; irq_enter(); kstat_this_cpu.irqs[irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); status|= IRQ_PENDING; /* signal arrived. Just acked */ action = NULL; if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { action = desc->action; status &= ~IRQ_PENDING; /* we commit to handling */ status|= IRQ_INPROGRESS;/* we’re handling it */ } desc->status = status; if (unlikely(!action)) goto out; 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); if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; } desc->status &= ~IRQ_INPROGRESS; out: desc->handler->end(irq); spin_unlock(&desc->lock); irq_exit(); return 1; } int handle_IRQ_event( ….) { int status = 1; int retval = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= actionflags; retval |= actionhandler(irq, action->dev_id, regs); action = actionnext; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); return retval; } Critical Top-Half Interrupt Handler Non-critical Top-Half

  9. asmlinkage unsigned int do_IRQ(struct pt_regs regs) { int irq = regs.orig_eax & 0xff; irq_desc_t *desc = irq_desc + irq; struct irqaction * action; unsigned int status; irq_enter(); kstat_this_cpu.irqs[irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); status|= IRQ_PENDING; /* signal arrived. Just acked */ action = NULL; if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { action = desc->action; status &= ~IRQ_PENDING; /* we commit to handling */ status|= IRQ_INPROGRESS;/* we’re handling it */ } desc->status = status; if (unlikely(!action)) goto out; irq_desc[ ] ISR timer IRQ1 Network IRQ2 action g1() g2() IRQ3 SCSI action IRQm f1() f2() 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); if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; } desc->status &= ~IRQ_INPROGRESS; out: desc->handler->end(irq); spin_unlock(&desc->lock); irq_exit(); return 1; } int handle_IRQ_event( ….) { int status = 1; int retval = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= actionflags; retval |= actionhandler(irq, action->dev_id, regs); action = actionnext; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); return retval; } If this ISR needs too much time to complete work for this device this ISR just sets a bit here, meaning “more work needs to be done for this device (Bottom Half required)” This bit is called “soft-irq pending bit” Then this interrupt handler terminates. This bit is processed later by do_softirq() function

  10. Love, Chapter 7 When & who calls do_softirq()? • Returning hardware interrupt handler • before do_IRQ() returns • it calls irq_exit()  do_softirq() 2. kernel thread • low priority kernel thread called ksoftirqd_CPUn • Itruns ksoftirq() function, which calls do_softirq() • Any code (such as network subsystem) • checks softirq pending bit and calls do_softirq() Bovet, p. 150

  11. PIC NIC IRQ Floppy Disk Urgent/non-urgent work in TCP/IP ack() CPUi selected move packet to socket update irq_desc[IRQm] IP move packet from NIC to memory ftp TCP do_IRQ()

  12. PIC NIC IRQ Floppy Disk Which part is done in which moduleTCP/IP • [Hardware] -- NIC(Network Interface Card) • receives a packet from network • issues interrupt to CPUN • [Top Half] -- Interrupt Handler • Critical Top half (do_IRQ()) Ack, assign a CPU for IRQnetwork • Non-Critical Top half (ISR) Allocates struct sk_buff for packet copy packet from NIC to sk_buff raise “bottom half required” (set bit) • [Bottom Half] -- do_softirq() • delivers packet to IP protocol handler • remote? – forward packet to other host • local? – invoke TCP handler • delivers packet to TCP handler • delivers packet to the socket associated with the portk

  13. Device requests interrupt PIC select CPU & Sends signal to CPU Top half & Bottom half(TCP/IP example) (1) Interrupt CPU (CPU/PIC is interrupt disabled) (4) exit I.H. Top Half Bottom Half Later … do_IRQ() ISR (5) kernel executes bottom half (if the bit is set) ack IP handler routes packet data Assign CPU to IRQ TCP handler Assembles Data Insert data Into socket Wakeup application Assigned CPU runs ISR which copies data from NIC to kernel (3) Schedule bottom halves (i.e. set bottom half bits)

More Related