aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2009-08-29 02:41:29 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-29 02:41:29 -0400
commit2bc481cf433879f0e6cdd4d899fc21ee05dcea23 (patch)
tree5afcce7af1511f105699cc74cc9df1b96b471eac /net/core
parentfd29cf72621071d1d5f9bae634a4505b05f0e58b (diff)
pktgen: spin using hrtimer
This changes how the pktgen thread spins/waits between packets if delay is configured. It uses a high res timer to wait for time to arrive. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/pktgen.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index bede00b54038..3045dd133071 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -131,6 +131,7 @@
131#include <linux/ioport.h> 131#include <linux/ioport.h>
132#include <linux/interrupt.h> 132#include <linux/interrupt.h>
133#include <linux/capability.h> 133#include <linux/capability.h>
134#include <linux/hrtimer.h>
134#include <linux/freezer.h> 135#include <linux/freezer.h>
135#include <linux/delay.h> 136#include <linux/delay.h>
136#include <linux/timer.h> 137#include <linux/timer.h>
@@ -2086,33 +2087,40 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
2086 pkt_dev->nflows = 0; 2087 pkt_dev->nflows = 0;
2087} 2088}
2088 2089
2089static inline s64 delta_ns(ktime_t a, ktime_t b)
2090{
2091 return ktime_to_ns(ktime_sub(a, b));
2092}
2093 2090
2094static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) 2091static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
2095{ 2092{
2096 ktime_t start, now; 2093 ktime_t start;
2097 s64 dt; 2094 s32 remaining;
2095 struct hrtimer_sleeper t;
2098 2096
2099 start = now = ktime_now(); 2097 hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
2098 hrtimer_set_expires(&t.timer, spin_until);
2099
2100 remaining = ktime_to_us(hrtimer_expires_remaining(&t.timer));
2101 if (remaining <= 0)
2102 return;
2100 2103
2101 while ((dt = delta_ns(spin_until, now)) > 0) { 2104 start = ktime_now();
2102 /* TODO: optimize sleeping behavior */ 2105 if (remaining < 100)
2103 if (dt > TICK_NSEC) 2106 udelay(remaining); /* really small just spin */
2104 schedule_timeout_interruptible(1); 2107 else {
2105 else if (dt > 100*NSEC_PER_USEC) { 2108 /* see do_nanosleep */
2106 if (!pkt_dev->running) 2109 hrtimer_init_sleeper(&t, current);
2107 return; 2110 do {
2108 if (need_resched()) 2111 set_current_state(TASK_INTERRUPTIBLE);
2112 hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS);
2113 if (!hrtimer_active(&t.timer))
2114 t.task = NULL;
2115
2116 if (likely(t.task))
2109 schedule(); 2117 schedule();
2110 }
2111 2118
2112 now = ktime_now(); 2119 hrtimer_cancel(&t.timer);
2120 } while (t.task && pkt_dev->running && !signal_pending(current));
2121 __set_current_state(TASK_RUNNING);
2113 } 2122 }
2114 2123 pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start));
2115 pkt_dev->idle_acc += ktime_to_ns(ktime_sub(now, start));
2116} 2124}
2117 2125
2118static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) 2126static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
@@ -3360,8 +3368,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
3360 int ret; 3368 int ret;
3361 3369
3362 if (pkt_dev->delay) { 3370 if (pkt_dev->delay) {
3363 if (ktime_lt(ktime_now(), pkt_dev->next_tx)) 3371 spin(pkt_dev, pkt_dev->next_tx);
3364 spin(pkt_dev, pkt_dev->next_tx);
3365 3372
3366 /* This is max DELAY, this has special meaning of 3373 /* This is max DELAY, this has special meaning of
3367 * "never transmit" 3374 * "never transmit"