Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202636
b: refs/heads/master
c: 79640a4
h: refs/heads/master
v: v3
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Jun 2, 2010
1 parent 5d6b967 commit 3615011
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 097811bb48c7837db94d7fe5d94f0f4b5e19e78c
refs/heads/master: 79640a4ca6955e3ebdb7038508fa7a0cd7fa5527
3 changes: 2 additions & 1 deletion trunk/include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ struct Qdisc {
struct gnet_stats_basic_packed bstats;
unsigned long __state;
struct gnet_stats_queue qstats;
struct rcu_head rcu_head;
struct rcu_head rcu_head;
spinlock_t busylock;
};

static inline bool qdisc_is_running(struct Qdisc *qdisc)
Expand Down
29 changes: 25 additions & 4 deletions trunk/net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2040,8 +2040,18 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
struct netdev_queue *txq)
{
spinlock_t *root_lock = qdisc_lock(q);
bool contended = qdisc_is_running(q);
int rc;

/*
* Heuristic to force contended enqueues to serialize on a
* separate lock before trying to get qdisc main lock.
* This permits __QDISC_STATE_RUNNING owner to get the lock more often
* and dequeue packets faster.
*/
if (unlikely(contended))
spin_lock(&q->busylock);

spin_lock(root_lock);
if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
kfree_skb(skb);
Expand All @@ -2056,19 +2066,30 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE))
skb_dst_force(skb);
__qdisc_update_bstats(q, skb->len);
if (sch_direct_xmit(skb, q, dev, txq, root_lock))
if (sch_direct_xmit(skb, q, dev, txq, root_lock)) {
if (unlikely(contended)) {
spin_unlock(&q->busylock);
contended = false;
}
__qdisc_run(q);
else
} else
qdisc_run_end(q);

rc = NET_XMIT_SUCCESS;
} else {
skb_dst_force(skb);
rc = qdisc_enqueue_root(skb, q);
qdisc_run(q);
if (qdisc_run_begin(q)) {
if (unlikely(contended)) {
spin_unlock(&q->busylock);
contended = false;
}
__qdisc_run(q);
}
}
spin_unlock(root_lock);

if (unlikely(contended))
spin_unlock(&q->busylock);
return rc;
}

Expand Down
1 change: 1 addition & 0 deletions trunk/net/sched/sch_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,

INIT_LIST_HEAD(&sch->list);
skb_queue_head_init(&sch->q);
spin_lock_init(&sch->busylock);
sch->ops = ops;
sch->enqueue = ops->enqueue;
sch->dequeue = ops->dequeue;
Expand Down

0 comments on commit 3615011

Please sign in to comment.