Commit 2bc481cf433879f0e6cdd4d899fc21ee05dcea23

Authored by Stephen Hemminger
Committed by David S. Miller
1 parent fd29cf7262

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

... ... @@ -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 {
... ... @@ -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"