linux 核心中的非強制中斷處理__linux

來源:互聯網
上載者:User

Linux核心定義的非強制中斷如下:

static struct softirq_actionsoftirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

char *softirq_to_name[NR_SOFTIRQS] = {

       "HI","TIMER", "NET_TX", "NET_RX", "BLOCK",

       "TASKLET","SCHED", "HRTIMER",       "RCU"

};

核心啟動時註冊的非強制中斷有以下。


其註冊函數為:

void open_softirq(int nr, void(*action)(struct softirq_action *))

{

       softirq_vec[nr].action= action;

}

其實就是對全域定義的陣列變數softirq_actionsoftirq_vec[NR_SOFTIRQS]進行初始化。

enum

{

       HI_SOFTIRQ=0,

       TIMER_SOFTIRQ,

       NET_TX_SOFTIRQ,

       NET_RX_SOFTIRQ,

       BLOCK_SOFTIRQ,

       TASKLET_SOFTIRQ,

       SCHED_SOFTIRQ,

       HRTIMER_SOFTIRQ,

       RCU_SOFTIRQ,    /* Preferable RCU should always be the lastsoftirq */

       NR_SOFTIRQS

}; 註冊函數如下:

       open_softirq(HI_SOFTIRQ,tasklet_hi_action);

       open_softirq(TIMER_SOFTIRQ,run_timer_softirq);

       open_softirq(NET_TX_SOFTIRQ,net_tx_action);

       open_softirq(NET_RX_SOFTIRQ,net_rx_action);

       open_softirq(BLOCK_SOFTIRQ,blk_done_softirq);

open_softirq(TASKLET_SOFTIRQ,tasklet_action);

open_softirq(SCHED_SOFTIRQ,run_rebalance_domains);

open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);

在irq中每一個CPU都有個結構體

typedef struct {

       unsignedlong __softirq_pending;

} ____cacheline_aligned irq_cpustat_t; 用來儲存當前CPU是否有等待的中斷處理函數。

在之前的文章可以知道,系統每一次執行do_irq()結束之後,都會調用函數irq_exit(void)。在這個函數中將處理軟體中斷,

/*

 *Exit an interrupt context. Process softirqs if needed and possible:

 */

void irq_exit(void)

{

       account_system_vtime(current);

       trace_hardirq_exit();

       sub_preempt_count(IRQ_EXIT_OFFSET);

       if(!in_interrupt() && local_softirq_pending())//表示不在中斷環境下,處理軟體中斷,

              invoke_softirq();//同時有軟體中斷存在,則執行。

 

#ifdef CONFIG_NO_HZ

       /*Make sure that timer wheel updates are propagated */

       rcu_irq_exit();

       if(idle_cpu(smp_processor_id()) && !in_interrupt() &&!need_resched())

              tick_nohz_stop_sched_tick(0);

#endif

       preempt_enable_no_resched();

}

#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED

# define invoke_softirq()       __do_softirq()

#else

# define invoke_softirq()      do_softirq()

#endif

其do_softirq()函數定義如下:函數中有類似的邏輯。

asmlinkage void do_softirq(void)

{

       __u32pending;

       unsignedlong flags;

       if(in_interrupt())

              return;

       local_irq_save(flags);

       pending= local_softirq_pending();//有軟體中斷掛起,對掛起的斷進行執行。

       if(pending)

              __do_softirq();

       local_irq_restore(flags);

}

#endif

 

在處理軟體中,核心定義了一個核心線程來處理不能及時處理的非強制中斷請求。其函數為:

static int ksoftirqd(void * __bind_cpu);

#define MAX_SOFTIRQ_RESTART 10

asmlinkage void __do_softirq(void)

{

---------------

       h = softirq_vec;

       do{

              if(pending & 1) {

                     intprev_count = preempt_count();

                     kstat_incr_softirqs_this_cpu(h- softirq_vec);

 

                     trace_softirq_entry(h,softirq_vec);

                     h->action(h);

                     trace_softirq_exit(h,softirq_vec);

                     if(unlikely(prev_count != preempt_count())) {

                            printk(KERN_ERR"huh, entered softirq %td %s %p"

                                   "with preempt_count %08x,"

                                   " exited with %08x?\n", h -softirq_vec,

                                   softirq_to_name[h - softirq_vec],

                                   h->action, prev_count,preempt_count());

                            preempt_count()= prev_count;

                     }

 

                     rcu_bh_qsctr_inc(cpu);

              }

              h++;

              pending >>= 1;

       }while (pending);

       local_irq_disable();

       pending =local_softirq_pending();

       if (pending && --max_restart)

              goto restart;

       if (pending)

              wakeup_softirqd();

       lockdep_softirq_exit();

       account_system_vtime(current);

       _local_bh_enable();

}

在__do_softirq()函數中,處理掛起的非強制中斷,同來pending位來判斷的是否有中斷掛起。

入中達到了(max_restart==0)的時候,pending不為0。調用了函數wakeup_softirqd();

核心線程的建立可參考其他文章。

       switch(action) {

       caseCPU_UP_PREPARE:

       caseCPU_UP_PREPARE_FROZEN:

              p = kthread_create(ksoftirqd, hcpu,"ksoftirqd/%d", hotcpu);

 

tasklet

struct tasklet_struct

{

       structtasklet_struct *next;

       unsignedlong state;

       atomic_tcount;

       void(*func)(unsigned long);

       unsignedlong data;

};

在linux核心中有倆種類型的tasklet,

其tasklet初始化如下:

void tasklet_init(struct tasklet_struct*t,void (*func)(unsigned long), unsigned long data)

{

       t->next= NULL;

       t->state= 0;

       atomic_set(&t->count,0);

       t->func= func;

       t->data= data;

}

初始化完tasklet之後,將其加入到tasklet隊列中。

低優先順序tasklet的調度函數如下:

static inline void tasklet_schedule(structtasklet_struct *t)

{

       if(!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))

              __tasklet_schedule(t);

}

void __tasklet_schedule(structtasklet_struct *t)

{

       unsignedlong flags;

 

       local_irq_save(flags);

       t->next= NULL;

       *__get_cpu_var(tasklet_vec).tail= t;

       __get_cpu_var(tasklet_vec).tail= &(t->next);

       raise_softirq_irqoff(TASKLET_SOFTIRQ);//請求非強制中斷。

       local_irq_restore(flags);

}

高優先順序tasklet的調度函數如下:

static inline voidtasklet_hi_schedule(struct tasklet_struct *t)

{

       if(!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))

              __tasklet_hi_schedule(t);

}

void __tasklet_hi_schedule(structtasklet_struct *t)

{

       unsignedlong flags;

 

       local_irq_save(flags);

       t->next= NULL;

       *__get_cpu_var(tasklet_hi_vec).tail= t;

       __get_cpu_var(tasklet_hi_vec).tail= &(t->next);

       raise_softirq_irqoff(HI_SOFTIRQ);//請求非強制中斷。

       local_irq_restore(flags);

}

有上面的倆組函數可知,將tasklet放入到不同的tasklet_vec和tasklet_hi_vec隊列中。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.