contributed by < qwe661234
>
linux2021
queue element
queue
list head
container_of
GCC uses the extension attribute when using the -ansi flag to avoid warnings in headers with GCC extensions.
ANSI C 標准允許變量0的常量被強制轉換成任何一種類型的指針,並且轉換的結果是個 NULL, 所以 (type *) 0 就是資料型別為 type *的 NULL 指針, 雖然取用 NULL 指針去指向 member 是非法的, 但前面加上 typeof 後, 編譯器不會去訪問 NULL->member, 而是單純去取 member 的資料型別
它的作用是獲取 struct 中某個成員相對於該 struct 首元素地址的偏移量
reference:
list_entry
list_add_tail function
Black: original
Red: after function
list_del function
Black: original
Red: after function
list_empty function
檢查 list head 是否有連接 node
list_is_singular function
檢查 list head 後面是否只連接一個 node
list_splice_tail function
將所有以 list 為 list head 的 list node 接在以 head 為 list head 的最後一個 list node 之後
Black: original
Red: after function
Result
list_cut_position
將由 head_from 為list head 的第一個 list_node 至 node (parameter 中的 node) 接在 list head head_to 之後
Black: original
Red: after function
Result
get_middle function
以 slow 一次走訪一格 list_node, fast 一次走訪兩格 list_node 的方式, 當fast 走訪一整個 list 將要回到 list head 時, slow 剛好會走到 list 的中間點
重構list_merge function
和 get_middle function
:
將list_merge function
和 get_middle function
合寫成一個 function, 因為 list_merge function 中的 head_from 就是 get_middle function 中的 list, 所以合寫後只須傳入兩個參數, 不需要再多傳入 middle node
變更為:
list_merge function
將兩個 list 排序並合併, if 的部份是因為 get_middle 的機制, 如果切分時只有一個 list node, 那個 list node 會接在 lhs 上, 所以只要 lhs 沒有接任何 list node, 那 rhs 必然也沒有接任何 list node, 故可以直接結束 funciton
重構 list_merge function
:
如果 rhs 為空就把 lhs 的 list node 接在 head 之後, lhs 為空則 rhs 必為空,所以行14即可實做, 且 list head 為空就會跳出迴圈, 無須一開始的兩個 if
Ex: N = =
原理是確保16個 bit 都能變為1, 最後做+1是為了得到最接近且比 N 大的 power of two, 接著 >> 1 (也就是除以2), 就可以得到最接近且比 N 小的 power of two
is_power_of_2
原理:
Ex n = , & = != 0, 若 n = , & = 0
roundup_pow_of_two
rounddown_pow_of_two
1UL 是代表值為1的 unsigned long
roundup_pow_of_two 和 rounddown_pow_of_two 都有使用到 fls_long
fls 為 find last set bit 的縮寫,就是找到傳入參數的最靠近 MSB 且是1的 bit 是第幾個 bit 並回傳. 將 1UL << 回傳值即可得到比參數 n 大且最靠近的 pow_of_two => __roundup_pow_of_two
, 將回傳值 - 1 再將 1UL << 回傳值即可得到比參數 n 小且最靠近的 pow_of_two => __rounddown_pow_of_two
, 在執行 function 前會先考慮系統是64 bit 架構還是32 bit
fls_long
fls
and __fls
_read & 7 與 _read % 8 同義, 用來看8 bit 中 read 的 lhs 有幾個 bit, 剩下 rhs 就是 8 - lhs
Ex: _read = 4
_read / 8 是用來看要從 src 的第幾個 bytes 開始讀起
Ex: _read = 20 (20 / 8 = 2) 所以 source 會指向 src 的第2個 bytes
read_mask 用來避免讀入不該讀的部份
Ex: 要讀入 bit 0 - 5, mask = 11111100b, 用來避免讀入 bit6, 7
write_mask 用來保留不須寫入的部份的原始內容
Ex: 要寫入 bit 0 - 5, mask = 00000011b, 用來保留 bit6, 7 的原始內容
bitsize 是用來看這一輪要寫入幾個 bits, 因為一輪只能最多寫8個 bits, Ex: count = 13, 那第一輪就寫入8個 bits, 第二輪再寫入5個 bits
read_lhs > 0 代表沒有對齊, Ex: lhs = 3, 代表要以 bit 2到下一個 bytes 的 bit 1組成8 bit 來處理
bitsize 如果<8代表要用 read_mask 來避免讀入不該讀的部份
write_lhs 是要保留不寫入的部份, write_rhs 是要寫入新 data 的部份, Ex: write_lhs = 2
這邊是把還沒寫完的 bit 寫入下一個 bytes, 一樣先把不寫入的部份做保留, 然後寫入要寫入的部份
這邊是把寫完的 bit 扣掉, 如果 count 還>0 代表要繼續寫下一輪
一次copy 64個bit
cstr buffer
interning pool and hash table
由測試程式的運作來解說 funciton 的功能
測試程式
CSTR_BUFFER(a)
首先建立一個 cstr_buffer a
cstr_cat(a, "Hello ")
將字串 "Hello" 接在 buffer 中的 cstring 的 cstr 指標後
如果 buffer 中 cstring 的 type 是 ONSTACK, str 會一個字一個字接上, 如果 buffer 中 cstring 的 type 不是 ONSTACK 或要字串長度超過 CSTR_STACK_SIZE, 則以 tmp 保存目前 buffer 中 cstring 並以 cstr_cat2 連接
cstr_cat2
用來連接非 ONSTACK 和長度超過 CSTR_STACK_SIZE 的字串
用 cstr_cat2
連接完成的字串長度如果 < CSTR_INTERNING_SIZE 會做 cstr_interning
, 如果沒有會回傳一個連接完成的 cstring
這個次是程式並沒有進到 cstr_cat2
cstr_cat2
中的 hash_blob
是用來計算 hash table 的 key value 之後會被進一步被 hash function 轉換程 index
hash_blob
完成字串連接後會做 CSTR_LITERAL(hello, "Hello string"), 其中 CSTR_LITERAL() 會執行 cstr_clone
如果要 clone 的字串長度小於 CSTR_INTERNING_SIZE, 那就會先去 interning pool 中找, 如果有一樣的會回傳已存在 pool 中的字串, 如果沒有則會複製一份新的新字串並存於 interning pool 和 hash_table 中, 回傳新字串, 如果 > CSTR_INTERNING_SIZE 就直接複製一份新的 cstring
CSTR_LOCK
鎖上一個 spinlock 等待 interning 完成再 CSTR_UNLOCK()
release lock
它會先做一次 interning 如果回傳的 cstring 是空的代表 hash table 不存在 或是 hash table 超過 threshold, 此時需要 expand
expand
就是初始化 hash table size 成 HASH_START_SIZE 或是 新簡一個 double size 的 hash table, 並把之前 hash table 中的 node insert 進去
如果 hash table 存在, 先去 interning pool 中找, 如果有一樣的會回傳已存在 pool 中的字串, 如果沒有則會複製一份新的新字串並存於 interning pool 和 hash table 中, 回傳新字串