---
# System prepended metadata

title: 2022q1 第 9 週測驗題
tags: [linux2022]

---

# [2022q1](http://wiki.csie.ncku.edu.tw/sysprog/schedule) 第 9 週測驗題
###### tags: `linux2022`

:::info
目的: 檢驗學員對 **[並行和多執行緒程式設計](https://hackmd.io/@sysprog/concurrency)** 的認知
:::

作答表單:
* ==[測驗 `1`](https://docs.google.com/forms/d/e/1FAIpQLSf0qSZqImkfHq6ComFcmMTulKSyVbWSClyQ2lIIMgsyeNfS6Q/viewform)== (Linux 核心設計)
* ==[測驗 `2`](https://docs.google.com/forms/d/e/1FAIpQLSfeaMhMykb8L884svgFToAdQjtiPH2WLoBc_CCjXG2B4AUyew/viewform)== (Linux 核心實作)

### 測驗 `1`

考慮到一個 [lock-free]((https://hackmd.io/@sysprog/concurrency)) 的軟體計時器實作，測試程式如下:
```c
#include <inttypes.h>
#include <stdio.h>                         
#include <stdlib.h>

#include "lf_timer.h"

#define EX_HASHSTR(s) #s
#define EX_STR(s) EX_HASHSTR(s)

#define EXPECT(exp)                                                      \
    do {                                                                 \
        if (!(exp))                                                      \
            fprintf(stderr, "FAILURE @ %s:%u; %s\n", __FILE__, __LINE__, \
                    EX_STR(exp)),                                        \
                abort();                                                 \
    } while (0)
    
static void callback(lf_timer_t tim, lf_tick_t tmo, void *arg)
{
    lf_tick_t tck = lf_timer_tick_get();
    printf("Timer %d expiration %#" PRIx64 " now %#" PRIx64 "\n", tim, tmo,
           tck);
    *(lf_tick_t *) arg = tck;
}   

int main(void)
{
    lf_tick_t exp_a = LF_TIMER_TICK_INVALID;
    lf_timer_t tim_a = lf_timer_alloc(callback, &exp_a);
    EXPECT(tim_a != LF_TIMER_NULL);
    EXPECT(lf_timer_set(tim_a, 1));
    EXPECT(!lf_timer_set(tim_a, 1));

    lf_timer_tick_set(0);
    lf_timer_expire();
    EXPECT(exp_a == LF_TIMER_TICK_INVALID);

    lf_timer_tick_set(1);
    lf_timer_expire();
    EXPECT(exp_a == 1);
    EXPECT(lf_timer_set(tim_a, 2));
    EXPECT(lf_timer_reset(tim_a, 3));

    lf_timer_tick_set(2);
    lf_timer_expire();
    EXPECT(exp_a == 1);
    EXPECT(lf_timer_cancel(tim_a));

    lf_timer_tick_set(3);
    lf_timer_expire();
    EXPECT(exp_a == 1);
    EXPECT(!lf_timer_reset(tim_a, UINT64_C(0xFFFFFFFFFFFFFFFE)));
    EXPECT(lf_timer_set(tim_a, UINT64_C(0xFFFFFFFFFFFFFFFE)));
    EXPECT(lf_timer_reset(tim_a, UINT64_C(0xFFFFFFFFFFFFFFFE)));

    lf_timer_expire();
    EXPECT(exp_a == 1);

    lf_timer_tick_set(UINT64_C(0xFFFFFFFFFFFFFFFE));
    lf_timer_expire();
    EXPECT(exp_a == UINT64_C(0xFFFFFFFFFFFFFFFE));

    lf_timer_free(tim_a);

    printf("timer tests complete\n");
    return 0;
}
```

預期執行輸出:
```
Timer 0 expiration 0x1 now 0x1
Timer 0 expiration 0xfffffffffffffffe now 0xfffffffffffffffe
timer tests complete
```

程式碼可參見 [lf_timer](https://gist.github.com/jserv/ee63f467f393153fd865a6b772edc63d)，使用 C11 搭配 GNU extension。

請補完程式碼，使其運作符合預期。作答規範:
* `COND` 為表示式
* `FF1` 和 `FF2` 為表示式

:::success
延伸問題:
1. 解釋上述程式碼運作原理
2. 參照 [interval-timer](https://github.com/sn0wvall/interval-timer)，撰寫 lock-based 實作，並提供可適用於 lock-based 和 lock-free timer 實作的測試程式 (含 benchmark)，並解讀實驗結果
:::

---

### 測驗 `2`

考慮到支援多個生產者—多個消費者的 bounded buffer lockfree 實作: [gist](https://gist.github.com/jserv/d2e27c8d9fc3c3e316fd91039633def5) (部分程式碼隱蔽)

程式碼使用 C11 [Atomics](https://en.cppreference.com/w/c/atomic) 和 [Threads](https://en.cppreference.com/w/c/thread) 撰寫，預期執行輸出:
```
Test: Spsc: null_pointers       : PASS
Test: Spsc: create              : PASS
Test: Spsc: empty               : PASS
Test: Spsc: full                : PASS
Test: Spsc: sums10000           : PASS
Test: Mpsc: null_pointers       : PASS
Test: Mpsc: create              : PASS
Test: Mpsc: empty               : PASS
Test: Mpsc: full                : PASS
Test: Mpsc: sums10000           : PASS
Test: Spmc: null_pointers       : PASS
Test: Spmc: create              : PASS
Test: Spmc: empty               : PASS
Test: Spmc: full                : PASS
Test: Spmc: sums10000           : PASS
Test: Mpmc: null_pointers       : PASS
Test: Mpmc: create              : PASS
Test: Mpmc: empty               : PASS
Test: Mpmc: full                : PASS
Test: Mpmc: sums10000           : PASS
```

請補完程式碼，使其執行符合預期。作答規範:
* `MMM` 是表示式，依據指定程式碼風格撰寫，以最精簡的形式