Try   HackMD

linux2021: foxhoundsk

測驗 δ 1

實作缺失位於函式 con_pop 中:

node_t *node = queue->first;             /* Node to be removed */
node_t *new_header = queue->first->next; /* become the first in the queue */

/* Queue is empty */
if (!new_header) {
    mtx_unlock(queue->first_mutex);
    return NULL;
}

其中指標 node 要提取的節點不應為 queue->first,因為第一次執行 pop 操作時,會將 dummy 節點取出。 後者用於保證 queue 的頭尾 (first 以及 last) 一致性。倘若將其提取出來,queue 會在經歷至少一次的 pop/push 操作並且只剩一個節點時,無法將最後一個節點取出,因為本實做需要 dummy 節點總是存在。

也就是說,發生問題時,即便 queue 中仍然有未處理的節點,應用程式還是會拿到 NULL (表示 queue 中沒有未處理的節點),而不是最後一個節點的內容。

因此,此程式實際運作時,最後一個要提取存放 kill signal 的節點的 pop thread 總是無法完成提取操作,進而無法讓 thrd_join 完成等待。

解決方法

可以將 con_pop 修改為:

void *con_pop(con_queue_t *queue) { mtx_lock(queue->first_mutex); -- node_t *node = queue->first; /* Node to be removed */ -- node_t *new_header = queue->first->next; /* become the first in the queue */ ++ node_t *node = queue->first->next; /* Node to be removed */ /* Queue is empty */ -- if (!new_header) { ++ if (!node) { mtx_unlock(queue->first_mutex); return NULL; } /* Queue not empty: retrieve data and rewire */ void *return_value = node->value; /* BBB */ -- queue->first->next = new_header; ++ queue->first->next = node->next; mtx_unlock(queue->first_mutex); /* Free removed node and return */ free(node); return return_value; }

以使得執行 pop 操作時,總是提取從 first 算起的第二個節點,也就是應用程式感興趣的最舊的節點 (queue->first->next),以解決第一次呼叫 con_pop 時,將 dummy 節點移出 queue 的問題。

答案 BBB (L17) 貌似不是 node->value ?

測驗 δ 2

測驗 ϵ 1

測驗 ϵ 2

測驗 ζ 1

測驗 ζ 2