Chinaunix首页 | 论坛 | 博客
  • 博客访问: 434448
  • 博文数量: 99
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 1012
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-20 16:30
个人简介

linux kernel 工程师

文章分类

全部博文(99)

文章存档

2018年(5)

2017年(12)

2016年(27)

2015年(10)

2014年(43)

2012年(2)

我的朋友

分类: LINUX

2014-02-14 10:27:37

static void net_tx_action(struct softirq_action *h)
{
 struct softnet_data *sd = &__get_cpu_var(softnet_data);

 //1. 释放completion_queue中的skb
 if (sd->completion_queue) {
  struct sk_buff *clist;
 // 注意在关中断的情况下,摘下completion_queue,  之后就遍历这个摘下来的queue了,与全局变量softnet_data中的queue已经没有冲突了

  local_irq_disable();
  clist = sd->completion_queue;
  sd->completion_queue = NULL;
  local_irq_enable();

  while (clist) {
   struct sk_buff *skb = clist;
   clist = clist->next;

   WARN_ON(atomic_read(&skb->users));
   trace_kfree_skb(skb, net_tx_action);
   __kfree_skb(skb);
  }
 }

 // 2. 调度qdisk_run
 if (sd->output_queue) {
  struct Qdisc *head;

  // 注意在关中断的情况下,摘下output_queue,  之后就遍历这个摘下来的queue了,与全局变量softnet_data中的queue已经没有冲突了
   local_irq_disable();
  head = sd->output_queue;
  sd->output_queue = NULL;
  sd->output_queue_tailp = &sd->output_queue;
  local_irq_enable();

  while (head) {
   struct Qdisc *q = head;
   spinlock_t *root_lock;

   head = head->next_sched;

   root_lock = qdisc_lock(q);
   if (spin_trylock(root_lock)) { // 获得锁成功,则清除调度状态,运行qdisc_run
    smp_mb__before_clear_bit();
    clear_bit(__QDISC_STATE_SCHED,
       &q->state);
    qdisc_run(q);   // run qdisc
    spin_unlock(root_lock);
   } else { // 得不到锁,重新调度qdisc
    if (!test_bit(__QDISC_STATE_DEACTIVATED,         
           &q->state)) {
     __netif_reschedule(q);
    } else { // QIDIS被禁止,则清除调度状态
     smp_mb__before_clear_bit();
     clear_bit(__QDISC_STATE_SCHED,
        &q->state);
    }
   }
  }
 }
}

阅读(1504) | 评论(0) | 转发(0) |
0

上一篇:qdisc的创建过程

下一篇:__dev_xmit_skb

给主人留下些什么吧!~~