# Linux 核心專題: 並行程式設計 > 執行人: WeiHongWi :::success :question: 提問清單 * ? ::: ## 任務簡述 回顧〈[並行和多執行緒程式設計](https://hackmd.io/@sysprog/concurrency)〉教材,以課程測驗題給定的並行程式碼為基礎,著手改進,並確保以 C11 Atomics 撰寫出正確且有效的程式碼,所有程式碼應當通過 [Thread Sanitizer](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual) 的執行時期檢測。 ## TODO: Concurrent Hashtable 重做[第 12 週測驗題](https://hackmd.io/@sysprog/linux2023-quiz12),包含延伸問題。 ### 用 C11 atomics 改寫 ### 解讀 bsd_queue.c 裡頭包含 4 個資料結構 , 有 singly-linked list 和 tail singly-linked list , queue , tail queue,在 hashtable 裡用到的是 `double linked tail queue` , 這裡就介紹 function #### TAILQ_ENTRY 和 TAILQ_HEAD #### TAILQ_FOREACH_SAFE #### TAILQ_REMOVE ### 解讀 hashtable.c 第一個資料結構為 `ht_item_t` , 其中包含 key 和 value 以及長度 , 且這些 item 用一個 double linked tail queue 去做連接.如以下程式碼: ```c typedef struct _ht_item { uint32_t hash; char kbuf[32]; void *key; size_t klen; void *data; size_t dlen; TAILQ_ENTRY(_ht_item) next; } ht_item_t; ``` 第二個資料結構為 `ht_items_list_t` , 其中包含了 spinlock 和 `ht_item_t` 的 double linked tail queue , 另外也用 double linked tail queue 來連接其他的 `ht_item_list`. 如以下程式碼: ```clike typedef struct _ht_item_list { TAILQ_HEAD(, _ht_item) head; pthread_spinlock_t lock; size_t index; TAILQ_ENTRY(_ht_item_list) iterator_next; } ht_items_list_t; ``` 第三個資料結構則為 `hashtable_t` , 其中也用 **mutex** 去避免競爭 hash table 的問題,加上前面提到屬於 `struct ht_item_list` 的 **spinlock** ,關於如何使用這兩個 lock 來達到並行, 我用 `ht_clear()` 這個函式做範例: ```c= void ht_clear(hashtable_t *table) { ... MUTEX_LOCK(table->iterator_lock); ... TAILQ_FOREACH_SAFE(list, &table->iterator_list->head, iterator_next, tmplist) { SPIN_LOCK(list->lock); ht_item_t *item = NULL; ht_item_t *tmp; TAILQ_FOREACH_SAFE(item, &list->head, next, tmp) { ... } ... SPIN_UNLOCK(list->lock); SPIN_DESTROY(list->lock); free(list); } MUTEX_UNLOCK(table->iterator_lock); ATOMIC_CAS(table->status, HT_STATUS_CLEAR, HT_STATUS_IDLE); } ``` 在第 6 和第 14 行的 `TAILQ_FOREACH_SAFE()` 用來走訪整個 double linked tail queue 第一個搜尋屬於 `struct ht_iterator_list` 的 TAILQ ,在搜尋前用 `MUTEX_LOCK()`讓其他 thread 的競爭者無法使用 第二個搜尋屬於 `struct ht_items_list` 的 TAILQ , 在搜尋前用 `SPIN_LOCK()`讓其他 thread 的競爭者無法使用. #### ht_init 和 PRNG 改寫 #### ht_grow_table() 和 internal preallocated bufferpool 改寫 ## TODO: MPMC 重做[第 9 週測驗題](https://hackmd.io/@sysprog/linux2023-quiz12)的測驗一,包含延伸問題。