aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-11-13 17:17:09 +0100
committerSteven Rostedt <rostedt@rostedt.homelinux.com>2012-10-26 14:31:52 -0400
commit2a534215a456785ba16176226c9563e545dfc4f6 (patch)
tree701087d6f45439be99b159b6cefff18129a18241
parent3050d6f3fdf3c61d060212196cfe05d4605217f8 (diff)
softirq: Check preemption after reenabling interrupts
raise_softirq_irqoff() disables interrupts and wakes the softirq daemon, but after reenabling interrupts there is no preemption check, so the execution of the softirq thread might be delayed arbitrarily. In principle we could add that check to local_irq_enable/restore, but that's overkill as the rasie_softirq_irqoff() sections are the only ones which show this behaviour. Reported-by: Carsten Emde <cbe@osadl.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable-rt@vger.kernel.org Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--block/blk-iopoll.c3
-rw-r--r--block/blk-softirq.c3
-rw-r--r--include/linux/preempt.h3
-rw-r--r--net/core/dev.c6
4 files changed, 15 insertions, 0 deletions
diff --git a/block/blk-iopoll.c b/block/blk-iopoll.c
index 58916afbbda5..f7ca9b411d2a 100644
--- a/block/blk-iopoll.c
+++ b/block/blk-iopoll.c
@@ -38,6 +38,7 @@ void blk_iopoll_sched(struct blk_iopoll *iop)
list_add_tail(&iop->list, &__get_cpu_var(blk_cpu_iopoll));
__raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ);
local_irq_restore(flags);
+ preempt_check_resched_rt();
}
EXPORT_SYMBOL(blk_iopoll_sched);
@@ -135,6 +136,7 @@ static void blk_iopoll_softirq(struct softirq_action *h)
__raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ);
local_irq_enable();
+ preempt_check_resched_rt();
}
/**
@@ -204,6 +206,7 @@ static int __cpuinit blk_iopoll_cpu_notify(struct notifier_block *self,
&__get_cpu_var(blk_cpu_iopoll));
__raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ);
local_irq_enable();
+ preempt_check_resched_rt();
}
return NOTIFY_OK;
diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index ee9c21602228..020696311b0a 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -50,6 +50,7 @@ static void trigger_softirq(void *data)
raise_softirq_irqoff(BLOCK_SOFTIRQ);
local_irq_restore(flags);
+ preempt_check_resched_rt();
}
/*
@@ -92,6 +93,7 @@ static int __cpuinit blk_cpu_notify(struct notifier_block *self,
&__get_cpu_var(blk_cpu_done));
raise_softirq_irqoff(BLOCK_SOFTIRQ);
local_irq_enable();
+ preempt_check_resched_rt();
}
return NOTIFY_OK;
@@ -139,6 +141,7 @@ do_local:
goto do_local;
local_irq_restore(flags);
+ preempt_check_resched_rt();
}
/**
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index 7a2bbbb82902..11412d7d9e43 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -41,8 +41,10 @@ do { \
#ifndef CONFIG_PREEMPT_RT_BASE
# define preempt_enable_no_resched() __preempt_enable_no_resched()
+# define preempt_check_resched_rt() do { } while (0)
#else
# define preempt_enable_no_resched() preempt_enable()
+# define preempt_check_resched_rt() preempt_check_resched()
#endif
#define preempt_check_resched() \
@@ -93,6 +95,7 @@ do { \
#define preempt_enable_no_resched() do { } while (0)
#define preempt_enable() do { } while (0)
#define preempt_check_resched() do { } while (0)
+#define preempt_check_resched_rt() do { } while (0)
#define preempt_disable_notrace() do { } while (0)
#define preempt_enable_no_resched_notrace() do { } while (0)
diff --git a/net/core/dev.c b/net/core/dev.c
index fd6911756fa7..875cf67112f1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1733,6 +1733,7 @@ static inline void __netif_reschedule(struct Qdisc *q)
sd->output_queue_tailp = &q->next_sched;
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_restore(flags);
+ preempt_check_resched_rt();
}
void __netif_schedule(struct Qdisc *q)
@@ -1754,6 +1755,7 @@ void dev_kfree_skb_irq(struct sk_buff *skb)
sd->completion_queue = skb;
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_restore(flags);
+ preempt_check_resched_rt();
}
}
EXPORT_SYMBOL(dev_kfree_skb_irq);
@@ -2840,6 +2842,7 @@ enqueue:
rps_unlock(sd);
local_irq_restore(flags);
+ preempt_check_resched_rt();
atomic_long_inc(&skb->dev->rx_dropped);
kfree_skb(skb);
@@ -3663,6 +3666,7 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd)
} else
#endif
local_irq_enable();
+ preempt_check_resched_rt();
}
static int process_backlog(struct napi_struct *napi, int quota)
@@ -3735,6 +3739,7 @@ void __napi_schedule(struct napi_struct *n)
local_irq_save(flags);
____napi_schedule(&__get_cpu_var(softnet_data), n);
local_irq_restore(flags);
+ preempt_check_resched_rt();
}
EXPORT_SYMBOL(__napi_schedule);
@@ -6240,6 +6245,7 @@ static int dev_cpu_callback(struct notifier_block *nfb,
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_enable();
+ preempt_check_resched_rt();
/* Process offline CPU's input_pkt_queue */
while ((skb = __skb_dequeue(&oldsd->process_queue))) {