2010年3月8日 星期一

from linux thread to protothread

去年在使用 buildroot/uClibc 環境移植 linux 過程中
由於編譯時對於 thread 選項選取預設的 linuxthreads 而非較為完整的 NTPL
因 thread 行為模式的緣故, 造成 IP 廠商提供的 OpenGL ES 環境無法正常運作
當時觀察到主要的錯誤在於每個 thread 取得的 pid 是不相同的
明顯地, 這不符合 thread 一般的認知, 然而這也與 linux thread 實作演進有相當的關係
(而linuxthreads 演進到 NTPL 的過程, 請參考 wikipedia 上的關於linux thread的歷史, 這裡就不詳加說明.)

在碰到這樣結果的當下, 稍微感到有些訝異
現今 thread 的概念在 OS 教科書中是一大重點
而 thread programming tutorial/guide 更是垂手可得
利用 thread 來改善系統效能, 更是常見於日常的程式中
這些資訊多到讓人產生一種 thread 的存在是理所當然似地
看著 wikipedia 中對於 thread 的說明, 跟教科書其實相去不遠

撇開 user-level/kernel-level 的優缺 和 1:1, N:1, N:M 的 Model 不同的理論不談
kernel-level threads 間的 context switch 可能可以較容易理解, 或是寄情於OS的能力
其中最引人入勝的莫過於 user-level threads 間又是如何達成的?

對於 user-level thread 的考量點有二
1. 如何於 user space 維護 thread context
2. thread switch 的時機點
preemptive or non-preemptive

其中 1.又取決於針對 2.的考量決定複雜的程度
可以想見, 可能必須在 process 中建構屬於 thread 的context
從 PC register, stack, 甚至可能細到 signal, 取決於實作的規劃

複雜者可能如 FSU Thread 在user-level 中實作了 POSIX thread

另外常見的 user-level thread 方式是提供特定的 I/O 與 switch API
讓 programmer 決定可以選擇切換的時機
這類者像GNU Portable Thread 即為一例
對於 GNU Pth 的細節技術可以參考這篇論文
主要在於使用泛 unix 的 ucontext/setjmp 支援

然而確也可能簡單到像 Contiki 中使用的 protothread
(與 coroutine 不同的地方在於 protothread 是 stack-less)
其概念可以拜讀 Simon Tatham 關於 coroutine 的大作
jserv 於 2006 年也對 coroutine 做了簡單的介紹
其精神在於僅存放 thread 所在的狀態, 以利於切換時跳至正確的位置

由於不停地在 thread 中切換, 若 thread 的 execution time 過小
搭配 sleep 的時機不佳, 簡單者是浪費 cpu 的 busywaiting
然而延伸而言, 卻也會影響 scheduling 與 cpu freqency 切換的判斷
而需要 computation 時, thread 間執行時間的比例, 與 sleep 可能造成降低效能
而這些都與使用 user-level thread API 實作 thread routine 的方式有很大的關係

儘管 thread 帶給 programmer 許多便利性
然而需要注意 thread 在各種環境下的特性, 才能夠正確地使用

沒有留言:

整合 MT-32 摹擬音源的 dosbox-patched

dosbox 對於許多老玩家並不陌生 提供了簡單的方式讓使用者能執行 DOS, Win 3.1/9x 的程式 相信多數用途是用來懷舊喜愛的遊戲 而音樂在遊戲中扮演相當重要的角色 在沒有強力計算與空間存放來支援 MP3/AAC 等 HQ 音樂 除了 sample rate 不高的...