# 2024q1 Homework2 (quiz1+2)
contributed by < `yutingshih` >
程式碼:[linux2024-quiz](https://github.com/yutingshih/linux2024-quiz) on GitHub
## 第一週測驗題
### 測驗 1
#### 程式運作原理
測驗題中提供的程式參考 [Optimized QuickSort — C Implementation (Non-Recursive)](https://alienryderflex.com/quicksort/) 所實作的非遞迴 (non-recursive; iterative) 快速排序法,以堆疊取代遞迴函式呼叫,避免後者所帶來的額外開銷。
其中以 `begin` 和 `end` 兩個堆疊記錄串列中尚未排序好的部分,在每一輪迭代當中,會先選定 pivot 為串列首個節點,然後將整個串列分成比 pivot 小的左半部分、pivot 本身以及比 pivot 大的右半部分,並依序將其各自的起點及終點推入 `begin` 及 `end` 堆疊當中。
例如:左半部分有 `A`、`B`、`C`、`D` 四個節點,pivot 為 `D` 節點,右半部分則有 `F`、`G`、`H` 三個節點
```
left : A -> B -> C -> D
pivot : E
right : F -> G -> H
```
接著將三者的起點和終點各自推入堆疊
```
index | 0 1 2 3 4 ... 7
------+---------------------
begin | A E D
end | D E H
```
在下一輪迭代則從堆疊中拿取其中的半邊,也就是子串列 `D` 到 `H` 繼續進行排序
#### 改進實作
<!-- 使用 Linux 核心風格的 List API 改寫上述程式碼,並針對鏈結串列,提出可避免最差狀況的快速排序實作,應設計效能評比的測試程式。 -->
### 測驗 2
#### 程式運作原理
先解釋 Timsort 實作中重要的函式功能及重點:
- `find_run` 會從串列的開頭開始切出一段單調 (monotonic) 的子序列,若為遞減序列,則會將其調整為遞增序列後回傳
- `merge_at` 依照給定的比較函式 `cmp`,合併堆疊最上層的的兩個 runs
- `merge_collapse` 則會檢查堆疊 `tp` 中最上層的三個 runs 是否滿足以下條件,若不滿足則挑選 `tp->prev->prev` 及 `tp` 中較短者與中間的 `tp->prev` 進行合併,用來確保被合併的兩個 runs 長度盡可能接近
- `tp->prev->prev` 長度大於 `tp->prev` 和 `tp` 的總和
- `tp->prev` 長度大於 `tp
- `merge_force_collapse` 則不做上述條件的檢查,直接挑選 `tp->prev->prev` 及 `tp` 中較短者與中間的 `tp->prev` 進行合併
- `merge` 將兩串列合併後回傳
- `merge` 將兩串列合併後使用 `build_prev_link` 重建雙向環轉鏈結串列的鏈結
#### 改進實作
#### 整合
<!-- 將改進過的 Timsort 實作整合進 sysprog21/lab0-c,作為另一個有效的排序命令,應設計效能評比的測試程式,確保測試案例符合 Timsort 設想的資料分布樣式。 -->
## 第二週測驗題
### 測驗 1
#### 程式運作原理
<!-- 解釋上述程式碼的運作,撰寫完整的測試程式,指出其中可改進之處並實作 -->
#### 測試程式
<!-- 在 Linux 核心的 cgroups 相關原始程式碼,找出 pre-order walk 程式碼並探討 -->
### 測驗 2
#### 程式運作原理
<!-- 解釋上述程式碼的運作,撰寫完整的測試程式,指出其中可改進之處並實作 -->
#### 測試程式
<!-- 在 Linux 核心找出 LRU 相關程式碼並探討 -->
### 測驗 3
#### 程式運作原理
`find_nth_bit` 的功能是找到第 n 個為 1 的位元,回傳其為整個搜尋範圍中的第幾個位元,並 LSB (least significant bit) 定義為第 0 個位元,若找不到,則回傳搜尋範圍的大小 `size`。
`find_nth_bit` 使用到 `FIND_NTH_BIT` 巨集及 `fns` 函式
`fns` 函式透過重複呼叫 `__ffs` n 次來尋找一個字節 (word) 中第 n 個為 1 的位元的位置,每次呼叫 `__ffs` 後都會將該位元清空,連續呼叫 n 次就相當於尋找第 n 個為 1 的位元。
`GENMASK` 巨集產生自第 `l` 到第 `h` 位元為 1 的遮罩 (mask),其中最低位編號為 0
`small_const_nbits` 檢查 `nbits` 是否為大於 0 且小於等於 `BITS_PER_LONG` 的常數
`__const_hweight8`、`__const_hweight16`、`__const_hweight32` 以及 `__const_hweight64` 分別計算最低數個位元當中有多少個為 1 的位元,`hweight_long` 則和 `__const_hweight64` 行為相同
`FIND_NTH_BIT` 首先逐字節判斷是否存在第 `num` 個位元為 1,若目標存在於當前字節,則呼叫 `fns` 函式尋找第 n 個為 1 的位元,找不到則直接回傳 `size`。
<!-- 在 Linux 核心原始程式碼找出 find_nth_bit 的應用案例,並予以解說和分析,需要涵蓋 CPU affinity 相關的原始程式碼。 -->