# 2022q1 第 13/14/15 週課程問答簡記 ## Kelvin [memory pool](https://en.wikipedia.org/wiki/Memory_pool) lab0: insert_head, remove (斷開節點間的連結), delete (真正釋放記憶體的操作) ## Uduru0522 circular buffer 程式碼如何確保 thread-safe? ## kdnvt 針對 mpscq 的 pop,若用 CAS,程式碼可以如何改寫? ```c= if (CAS(tail, self)) { CAS(...) // for same tail and head. } else { head = LOAD() while (...) { ...check if new head } } ``` 針對[第十五週的測驗](https://hackmd.io/@sysprog/linux2022-quiz15) ```graphviz digraph BST { node [fontname="Arial" ]; l1 [ label = "1" ]; l21 [ label = "2" ]; l22 [ label = "3" ]; l31 [ label = "4" ]; l32 [label = "5" ]; l33 [color=red shape=rect label = "6" ]; l34 [color=red shape=rect label = "7" ]; l41 [color=blue shape=rect label = "8" ]; l42 [color=blue shape=rect label = "9" ]; l43 [color=blue shape=rect label = "10" ]; l1 -> { l21 l22 }; l21 -> { l31 l32 }; l22 -> { l33 l34 }; l31 -> { l41 l42 }; l32 -> { l43} } ``` 我認為 `void minheap_init(unsigned long nr_items, struct heap_item *h)` 是想要對 leaf 做 `do_sift_up` 。第一個 for 迴圈是對最底層的藍色節點,第二個 for 迴圈則是對倒數第二層的紅色節點。因為 heap 的結構是 complete binary ,所以 leaf 一定在這兩層。但是因為 `do_sift_up` 只要遇到 parent 比較小就會停下,因此這個程式是有錯的。考慮以下情況: ```graphviz digraph BST { node [fontname="Arial" ]; l1 [ label = "100" ]; l21 [ label = "2" ]; l22 [ label = "3" ]; l31 [ label = "4" ]; l32 [label = "5" ]; l33 [color=red shape=rect label = "6" ]; l34 [color=red shape=rect label = "7" ]; l41 [color=blue shape=rect label = "8" ]; l42 [color=blue shape=rect label = "9" ]; l43 [color=blue shape=rect label = "10" ]; l1 -> { l21 l22 }; l21 -> { l31 l32 }; l22 -> { l33 l34 }; l31 -> { l41 l42 }; l32 -> { l43} } ``` 因為初始化的過程中所有 leaf 的 parent 都比較小,因此最上面的 100 不會被動到。 要修正程式其中一個辦法是讓 `do_sift_up` 繼續往上檢查。如下: ```c static void do_sift_up(unsigned long idx, unsigned long nr_items, struct heap_item *h) { assert(idx > 0); if (idx == 1) return; uint64_t v = h[idx].key; unsigned long pidx = parent(idx); uint64_t pv = h[pidx].key; if (pv < v){ do_sift_up(pidx, nr_items, h); return; } struct heap_item tmp = h[pidx]; h[pidx] = h[idx]; h[idx] = tmp; do_sift_up(pidx, nr_items, h); } ``` 但這樣會加重 heap 的操作成本,因此我認為較好的方法還是對第一個以外的所有節點都做原版的 `do_sift_up` 。或是寫兩個版本的 `do_sift_up` ,在初始化時使用沉重版本,並在一般操作時使用原版。 ## Kelvin [2022q1 quiz15](https://hackmd.io/@cantfindagoodname/linux2022-quiz15)
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.