---
# System prepended metadata

title: 'Linux2023: backink'

---

> [github](https://github.com/backink/Linux2023_summer/tree/main/hw1)

## 測驗 α

目標：完成 Incomplete search tree 當中未完成的部份程式碼

原始程式碼見 [main.c](https://gist.github.com/jserv/4dfaf78cf516cc20f4bc55ce388c195d)

### α - 1

以下節錄部份程式碼

``` c
void st_remove(struct st_node **root, struct st_node *del)
{
    if (st_right(del)) {
        struct st_node *least = st_first(st_right(del));
        if (del == *root)
            *root = least;

        AAAA;
        BBBB;
        return;
    }

    if (st_left(del)) {
        struct st_node *most = st_last(st_left(del));
        if (del == *root)
            *root = most;

        CCCC;
        DDDD;
        return;
    }

    if (del == *root) {
        *root = 0;
        return;
    }

    /* empty node */
    struct st_node *parent = st_parent(del);
    if (st_left(parent) == del)
        st_left(parent) = 0;
    else
        st_right(parent) = 0;

    EEEE;
}
```

AAAA 為 ```st_replace_right(del, least);```
若 del 有 right child 則找右子樹最小值作為刪除後的替換值

BBBB 為 ```st_update(root, st_right(least))```
替換後 update 右子樹

CCCC 為 ```st_replace_left(del, most);```
若 del 有 left child 則找左子樹最大值作為刪除後的替換值

DDDD 為 ```st_update(root, st_left(most))```
替換後 update 左子樹

EEEE 為 ```st_update(root, parent);```
若刪除節點左右 child 都為 NULL，刪除完後從parent node 開始update

:::warning
因為 update 是從 bottom up 往上平衡，我認為應該要從替換節點（least 和 most）的 parent 開始向上 update，因為 least 和 most 從原本位置移掉之後，hint 值可能受到影響的節點應該會從他們的 parent 開始，但是目前的程式碼似乎沒有記錄這個節點
:::

```c 
static void __treeint_dump(struct st_node *n, int depth)
{
    if (!n)
        return;

    __treeint_dump(FFFF, depth + 1);

    struct treeint *v = treeint_entry(n);
    printf("%d\n", v->value);

    __treeint_dump(GGGG, depth + 1);
}
```
依據 inorder traversal 的原則
FFFF 為 ```st_left(n)```
GGGG 為 ```st_right(n)```

:::success
延伸問題

2. 指出上述程式碼可改進之處，特別跟 AVL tree 和 red-black tree 相比，並予以實作
3. 設計效能評比程式，探討上述程式碼和 red-black tree 效能落差
:::

### α - 2

在理解S-tree程式碼的過程中，發現在特定insert sequence 會造成搜尋特定節點會需要 O(n)時間
如圖顯示在插入new node之後，左方的樹會旋轉成右邊的形狀，且update函數在遞迴後不會update到parent節點
![](https://hackmd.io/_uploads/S1LWaDM32.jpg)
利用這樣的特性繼續插入節點，會發現形成一個左傾且接近線性的樹形（相對rotate left可以刻意製造右傾的樹），導致後續搜尋節點時會需要O(n)的時間複雜度
![](https://hackmd.io/_uploads/ry3-Awfnn.jpg)


### α - 3
測試效能

## 測驗 β

以下程式碼可針對給定的 alignment 數值，輸出大於等於 alignment 的記憶體對齊地址

目標：已知 alignment 不為 0，填補 MMMM 使程式碼輸出符合預期結果
```c 
#include <stdint.h>

static inline uintptr_t align_up(uintptr_t sz, size_t alignment)
{
    uintptr_t mask = alignment - 1;
    if ((alignment & mask) == 0) {  /* power of two? */
        return MMMM;       
    }
    return (((sz + mask) / alignment) * alignment);
}
```

### β - 1

update：答案中不能出現 alignment，修改答案在下面，最初答案仍保留方便檢視思考過程

MMMM 為 ```sz + ((alignment - (sz & mask)) & (~alignment))```
當 alignment 本身是 2 的冪，例如 alignment = b000...1000， mask 會是 b000...0111
以下分成兩種情況討論
1. 若 sz 在 alignment 以下位元有值需要向上對齊，以 sz = b011...0010 為例， ```alignment - (size & mask)``` b000...1000 - b000...0010 會等於 b000...0110（在此情況中，```& (~alignment)``` 等於 & b111...0111 不影響計算結果）
而 sz 加上此數值 b011...0010 + b000...0110 會等於將不及 alignment 長度的尾數向上補齊至一個 alignment 的位置 b011...1000
2. 若 sz 在 alignment 以下位元沒有值，是已經對齊好的狀態，例如 sz = b011...1000，```alignment - (size & mask)``` 會是 b000...1000，在 ```& (~alignment)```後會得到 0，sz 加上 0 則保持原本數值，符合已經對齊好不改變的預期結果 


Update：
MMMM 為 ```(sz + mask) & (~mask)```


:::success
延伸問題

2. 在 Linux 核心原始程式碼找出類似 align_up 的程式碼，並舉例說明其用法
:::

## 測驗 γ

HHHH 為 ```pthread_cond_wait(&qs->cond_st, &qs->mtx_st)```
根據上下文程式碼邏輯
```c 
verify(pthread_mutex_lock(&qs->mtx_st));
while (qs->st == ts_idle)
    verify(HHHH);
verify(pthread_mutex_unlock(&qs->mtx_st));
```
在獲得mutex之後，若滿足while條件（idle）則需要放棄mutex且在condition variable 基礎上等待其他thread對此condition variable發出signal，喚起等待中的thread重新獲得mutex並檢查是否可以跳出while迴圈往下執行

JJJJ 為 ```pthread_cond_signal(&qs2->cond_st)```
根據上下文程式碼邏輯
```c 
verify(pthread_mutex_lock(&qs2->mtx_st));
qs2->st = ts_term;
verify(JJJJ);
verify(pthread_mutex_unlock(&qs2->mtx_st));
```
將qs2的狀態改變（termination）之後，發出signal喚醒等待此condition variable的thread，使其跳脫等待迴圈往下執行

:::success
延伸問題
2. 以 Thread Sanitizer 找出上述程式碼的 data race 並著手修正
3. 研讀 專題: lib/sort.c，提出上述程式碼效能改進之規劃並予以實作
:::

### γ - 2
### γ - 3