Commit 2bc481cf433879f0e6cdd4d899fc21ee05dcea23
Committed by
David S. Miller
1 parent
fd29cf7262
Exists in
master
and in
4 other branches
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>
Showing 2 changed files with 30 additions and 21 deletions Side-by-side Diff
kernel/hrtimer.c
... | ... | @@ -485,6 +485,7 @@ |
485 | 485 | debug_object_init_on_stack(timer, &hrtimer_debug_descr); |
486 | 486 | __hrtimer_init(timer, clock_id, mode); |
487 | 487 | } |
488 | +EXPORT_SYMBOL_GPL(hrtimer_init_on_stack); | |
488 | 489 | |
489 | 490 | void destroy_hrtimer_on_stack(struct hrtimer *timer) |
490 | 491 | { |
... | ... | @@ -1477,6 +1478,7 @@ |
1477 | 1478 | sl->timer.function = hrtimer_wakeup; |
1478 | 1479 | sl->task = task; |
1479 | 1480 | } |
1481 | +EXPORT_SYMBOL_GPL(hrtimer_init_sleeper); | |
1480 | 1482 | |
1481 | 1483 | static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode) |
1482 | 1484 | { |
net/core/pktgen.c
... | ... | @@ -131,6 +131,7 @@ |
131 | 131 | #include <linux/ioport.h> |
132 | 132 | #include <linux/interrupt.h> |
133 | 133 | #include <linux/capability.h> |
134 | +#include <linux/hrtimer.h> | |
134 | 135 | #include <linux/freezer.h> |
135 | 136 | #include <linux/delay.h> |
136 | 137 | #include <linux/timer.h> |
137 | 138 | |
138 | 139 | |
139 | 140 | |
140 | 141 | |
141 | 142 | |
142 | 143 | |
... | ... | @@ -2086,33 +2087,40 @@ |
2086 | 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 | 2091 | static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) |
2095 | 2092 | { |
2096 | - ktime_t start, now; | |
2097 | - s64 dt; | |
2093 | + ktime_t start; | |
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); | |
2100 | 2099 | |
2101 | - while ((dt = delta_ns(spin_until, now)) > 0) { | |
2102 | - /* TODO: optimize sleeping behavior */ | |
2103 | - if (dt > TICK_NSEC) | |
2104 | - schedule_timeout_interruptible(1); | |
2105 | - else if (dt > 100*NSEC_PER_USEC) { | |
2106 | - if (!pkt_dev->running) | |
2107 | - return; | |
2108 | - if (need_resched()) | |
2100 | + remaining = ktime_to_us(hrtimer_expires_remaining(&t.timer)); | |
2101 | + if (remaining <= 0) | |
2102 | + return; | |
2103 | + | |
2104 | + start = ktime_now(); | |
2105 | + if (remaining < 100) | |
2106 | + udelay(remaining); /* really small just spin */ | |
2107 | + else { | |
2108 | + /* see do_nanosleep */ | |
2109 | + hrtimer_init_sleeper(&t, current); | |
2110 | + do { | |
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 | 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 | - | |
2115 | - pkt_dev->idle_acc += ktime_to_ns(ktime_sub(now, start)); | |
2123 | + pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start)); | |
2116 | 2124 | } |
2117 | 2125 | |
2118 | 2126 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) |
... | ... | @@ -3360,8 +3368,7 @@ |
3360 | 3368 | int ret; |
3361 | 3369 | |
3362 | 3370 | if (pkt_dev->delay) { |
3363 | - if (ktime_lt(ktime_now(), pkt_dev->next_tx)) | |
3364 | - spin(pkt_dev, pkt_dev->next_tx); | |
3371 | + spin(pkt_dev, pkt_dev->next_tx); | |
3365 | 3372 | |
3366 | 3373 | /* This is max DELAY, this has special meaning of |
3367 | 3374 | * "never transmit" |