在 NCTUns4.0 之前(含 4.0)都有個共同的問題,就是 simulatiopn time 最大限制在 4200 second 內,這問題存在已久,前一陣子(好大一陣子)學弟的任務要突破這依限制,才去認真的看了一下這問題的關鍵點。
4200怎麼算出來?
4200怎麼算出來,這問題有意思了,先知道怎麼算要解決問題就容易多了,許多人都以為因為使用 32bits 變數存放 tick 關係所致,的確看到 4200 很容易聯想到這裡,因為 32bits 最大可以存放 4,294,967,296 這麼大,但事實並不是如此簡單。
32bits 變數 + 最小 ticks 單位 1ns
當這兩樣資訊放在一起時,上面的推論就產生矛盾了,因為在 NCTUns 設計中,最小的 tick 等於 1ns,如此一來,32bits 的容量也不過可以存放 4.2 秒的大小老早就爆炸了,就算以預設值 1tick = 100ns 來計算也只有 429.4 秒而已,那 4200sec 怎麼出來的?
64bits Memory Mapping
答案當然是使用 64bits 的變數來儲存,在我接手的時候 engine 裡面就已經採用了大量的 64bits 變數做運算,當然包括 tick 也是,因此才可以應付使用 1tick = 1ns 時模擬 4200sec 的狀況。這時候問題又來了,既然已經使用 64bits 變數存放 tick ,為什麼還會有 4200sec 的限制?
關鍵:32bits overflow
因為在 kernel 裡面,早期 hacking timer 時並沒有考慮太多狀況,所以大多以 long (32bits) 變數做計算,而在較舊的 linux kernel 中 timer 刻度只有到 us ,但後來以版本已經支援到 ns 了,因此許多計算都是以 us 或者 ns 為基底計算,而非我們的 tick,所以 4200sec 就是因為 kernel 中 32bits 加上 overflow 所產生的限制。
然而在 32 位元的機器中,CPU 並無法直接支援 64bits 計算的指令,因此都是使用兩段式計算來完成除法運算,所以最主要的問題點就在於當發生乘、除法運算時,需要注意是否產生 overflow 或是 underflow 的情況,解決後就可以順利支援超過 4200sec 的模擬 case。
經過 wghuang 的努力,我再加以調整後列出所有必須注意的地方,以下 function 也已經在新版 kernel 處理完畢:
- kernel/timer.c::schedule_timeout_us()
- kernel/nctuns_callout.c::nctuns_callback()
- kernel/nctuns_callout.c::nctuns_add_tun_event()
- kernel/nctuns_syscall.c::sys_NCTUNS_usleep_After_Msg_Send()
我在修正問題時採用改寫 NCTUNS_ticks_to_xxx (include/linux/nctuns_ticks.h) 等系列的 macro,因此上面四個點並不是每個都需要更動,但需要注意。
... Read more.




