rcu鎖所使用的乙個機制 dynticks

2021-08-25 01:30:34 字數 1408 閱讀 1773

可以睡眠的rcu鎖很大程度上有益於系統的實時性,因為不用禁用搶占了,該rcu鎖巧妙的使用兩個「階段」來跟蹤rcu的狀態,內部維持著乙個狀態機,該狀態機的其中兩個狀態需要所有cpu的確認,也就是說只有所有cpu都確認了之後,狀態機才能向前推進,這就暴露出乙個缺點,就是在nohz啟用的情況下,如果乙個cpu不再接收時鐘中斷,那麼它就沒有機會執行確認,結果就是所有的和rcu相關的cpu需要等待很長一段時間才能推進rcu狀態機,一直等到這個停掉時鐘心跳的cpu重新開始心跳,怎麼解決這個問題呢?核心中引入了乙個叫做dynticks的機制,該機制很簡單,就是當乙個cpu處於心跳停止狀態的時候可以直接跳過它,不需要它的確認,畢竟它上面是不可能操作read-rcu鎖的,**實現也非常清晰:

static inline void rcu_enter_nohz(void)

smp_mb(); /* cpus seeing ++ must see prior rcu read-side crit sects */

__get_cpu_var(dynticks_progress_counter)++;

if (unlikely(__get_cpu_var(dynticks_progress_counter) & 0x1)) else {

write_unlock_bh(&udp_hash_lock);

return 0;

以上列舉的這一段**的目的是取得乙個沒有使用的埠,眾所周知,udp埠的大小是16位,是65536個,取得乙個沒有使用的埠的最直觀的方法就是設定乙個65536個元素的陣列,陣列元素為乙個結構體,包含兩個元素,乙個是從0到65535的數字,另乙個是是否已經被使用,程式邏輯就是遍歷這個陣列,然後得到乙個是否被使用欄位是0的即可,但是這個演算法非常拙劣,浪費空間不說,時間複雜度也不見得很低,於是想到了雜湊演算法,將如此之大數目的數字雜湊到一些有限的桶內,這就必須將這些數字進行分類了,linux核心取了128這個不大不小的數字,也就是result & (udp_htable_size - 1)這句**體現的,這樣的話一共就會有128個雜湊桶,顯然的會有很多的埠會衝突,從而連線到一條衝突鏈上。

為何linux核心採用這麼一種演算法呢,比如為何要取得最小的衝突鏈呢,這是因為為了在後面的第二個for迴圈中從最小size的衝突連開始尋找衝突鏈中的可用埠,size最小的結果就是udp_lport_inuse內部遍歷的時候開銷最小。事實上該函式的兩個for分別實現了兩種尋找空閒埠的方式,第乙個for迴圈的優先順序比第二個for迴圈的優先順序要高,也就是說首先尋找衝突鏈為空的,如果找到,那麼後面就不用費事遍歷衝突鏈了,如果沒有找到,那麼就從最小size的衝突鏈開始遍歷,一條一條衝突鏈迴圈遍歷,這也是第二個for的作用,當然從最小size衝突鏈開始遍歷比較節省開銷了。

該函式的乙個要點就是在於將問題分解成了兩個部分,第乙個部分是雜湊優化,第二個部分是不得已的遍歷,同時在問題第乙個部分求解當中為第二部分埋下了伏筆,這就是得到了最小size的衝突鏈,可謂奇妙!

乙個windows訊息機制使用

最近一直搞那改版後的遊戲啟動介面,在主視窗加了個樹形控制項。設計了個ctree類繼承於ctreectrl,再放了個樹形控制項物件m treectrl作為主視窗類cserver的成員。現在遇到的問題是,點選了樹形控制項的某個節點如何設定相應的資料到主介面的乙個控制項上。點選事件是在ctree類裡響應的...

使用semaphore寫乙個顯示鎖

這裡只是將semaphore包裝了一下,注意當semaphore的構造引數是1時,本身就是乙個顯示鎖 public class semaphorelock public void unlock public static void main string args catch interrupted...

python裡使用dir函式檢視乙個類所有成員函式

如果乙個類是別人編寫的,又沒有幫助文件,怎麼樣來檢視所有成員函式呢?就可以使用下面的 file builtin dir example 2.py class a def a self pass def b self pass class b a def c self pass def d self ...