Ethernet device polling(5)

ハンドラへの引数として渡されるint countについて見ていく。
これは1回のpollingで最大何パケット受信するのかを決める変数で、netisr_pollmore/netisr_pollではこれを動的にスケジュールする事でパフォーマンスを最適化するように意図されている模様。

さて、実際にはどのようになっているのか。
例えば、netisr_poll()からbgeのbge_poll()が呼ばれる場合を想定する。
netisr_poll()はcyclesを調整してからhandlerに渡す:

	cycles = (residual_burst < poll_each_burst) ?
		residual_burst : poll_each_burst;
	residual_burst -= cycles;

	for (i = 0 ; i < poll_handlers ; i++)
		pr[i].handler(pr[i].ifp, arg, cycles);

bge_poll()はcountを受けとって、自分のscに突っ込み、bge_rxeof()を呼ぶ:

        sc->rxcycles = count;
        bge_rxeof(sc);

bge_rxeof()では、当然パケット取り込み作業をrxcycles回で打ち切る為のコードが仕込まれている:

        while(sc->bge_rx_saved_considx !=
            sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx) {
                struct bge_rx_bd        *cur_rx;
                uint32_t                rxidx;
                struct mbuf             *m = NULL;
                uint16_t                vlan_tag = 0;
                int                     have_tag = 0;

#ifdef DEVICE_POLLING
                if (ifp->if_capenable & IFCAP_POLLING) {
                        if (sc->rxcycles <= 0)
                                break;
                        sc->rxcycles--;
                }
#endif

こんな感じだ。

ちなみにbgeではbge_txeof()もether_pollのコンテキスト内で実行している(元々割り込みコンテキスト内で実行していた)が、そういうものだろうか?
てっきりドライバ名_start()がパケットを送ってそれで終わり、というのがふつーな実装方法なのかと思っていたが、私が非常識なだけだろうか。
これもパフォーマンス上の理由かな?