Race condition
This presentation is the property of its rightful owner.
Sponsored Links
1 / 13

Race Condition PowerPoint PPT Presentation


  • 171 Views
  • Uploaded on
  • Presentation posted in: General

제 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.

Download Presentation

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Race condition

제43강 : Interrupt(III) Race Condition

Race Condition


Race condition1

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( )


Do irq critical section

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


Isr is not a critical section

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


Race condition

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 */


Race condition

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;

}


Race condition

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


Race condition

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


Race condition

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


When who calls do softirq

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


Urgent non urgent work in tcp ip

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()


Which part is done in which module tcp ip

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


Top half bottom half tcp ip example

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)


  • Login