diff options
| author | Stephen Hemminger <shemminger@vyatta.com> | 2009-08-29 02:41:29 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-08-29 02:41:29 -0400 |
| commit | 2bc481cf433879f0e6cdd4d899fc21ee05dcea23 (patch) | |
| tree | 5afcce7af1511f105699cc74cc9df1b96b471eac /net/core | |
| parent | fd29cf72621071d1d5f9bae634a4505b05f0e58b (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.c | 49 |
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 | ||
| 2089 | static inline s64 delta_ns(ktime_t a, ktime_t b) | ||
| 2090 | { | ||
| 2091 | return ktime_to_ns(ktime_sub(a, b)); | ||
| 2092 | } | ||
| 2093 | 2090 | ||
| 2094 | static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) | 2091 | static 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 | ||
| 2118 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) | 2126 | static 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" |
