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()がパケットを送ってそれで終わり、というのがふつーな実装方法なのかと思っていたが、私が非常識なだけだろうか。
これもパフォーマンス上の理由かな?