contributed by < YoLinTsai
>
linux2021-hw
延伸問題:
pthread_create
thread
所指向的 buffer 會紀錄 thread ID,attr
是開 thread 的參數,用 NULL 就是 default attributes。start_routine()
,並將 arg
餵給 start_routine()
。pthread_cancel
pthread_join
tpool_create()
中可以發現,一發現 ptread_create
失敗,立刻會把所有 thread 取消掉,他的手法是先做 pthread_cancle
接著 pthread_join
,原因在 linux man page 中的描述:After a canceled thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status.
(Joining with a thread is the only way to know that cancellation has completed.)
pthread_cond_wait
pthread_cond_wait
便能達成這個情形,呼叫了之後 thread 會停在該處,直到被喚醒。pthread_cond_signal()
和 pthread_cond_broadcast()
,差別如同函式名稱一樣,前者一次只會喚醒其中一個,後者全部在等待該 condition variable 的通通都會喚醒。Thread A
Thread B
is_done
又被更動,直到進入 pthread_cond_wait
才把 lock 放掉,一旦被喚醒後又重新把 lock 拿回來。pthread_cleanup_push
pthread_cleanup_pop
pthread_cleanup_up
的目的在於避免 thread 結束時沒有正常收回資源,特別是 lock。pthread_setcancelstate
顧名思義這兩個 function 是用來控制 thread 取消的行為,在 pthread_setcancelstate
中,一共有兩種 state 可以選擇:
PTHREAD_CANCEL_ENABLE
PTHREAD_CANCEL_DISABLE
其中 DISABLE
在 thread 接收到 cancel 的 signal 時,不會立即取消,而是會等到 state 被改回 ENABLE
時才會取消。
不過這裡的 cancel
之所以這樣設計,就是因為他的取消並不意味馬上結束,而是在 thread 正式結束前還有待處理的事項,取消動作依序包含:
tpool_create
創建並初始化 __threadpool
和 __jobqueue
,同時確認是否有正常初始化。pthread_create
如果 create 失敗,返回值不為0,接著連續使用 pthread_cancel
和 pthread_join
去結束所有 thread。cond_nonempty
和 rwlock
初始化。(透過 pthread_cond_init
和 pthread_mutex_init
)tpool_create
中一個關鍵的部分:jobqueue_fetch(void *jobqueue)
指定給 pool->workers[i]
運行,接著來解析 jobqueue_fetch()
jobqueue_fetch()
的運作邏輯,當我們創建完成 threadpool 和 jobqueue 後,開了複數個 thread 去運行 jobqueue_fetch(),一旦等到 jobqueue 有 threadtask 被塞到 linked list 中,便嘗試執行 threadtask 中的 functiontpool_apply
會創建 treadtask_t
並新增到 pool->jobqueue 當中,特別注意 HHH
的部分呼應了 jobqueue_fetch()
的設計,當 linked_list 中從沒有 task 到出現第一個 task 時,會呼叫 pthread_cond_broadcast(&jobqueue->cond_nonempty);
喚醒待命中的 thread 去 fetch task 來執行。seconds
值為零時,便是 blocking wait,等到該 thread 執行完成才會繼續執行seconds
有值,便會用 pthread_cond_timeout
來等待 cond
的 signal ,如果等待時間超過 seconds,便將 future->flag
設成 __FUTURE_TIMEOUT
並回傳 NULLAll CLOCK_MONOTONIC variants guarantee that the time returned by consecutive calls will not go backwards, but successive calls may—depending on the architecture—return identical (not-increased) time values.
當我們用 pthread_cond_wait
阻塞 thread 時,可能有不只一個 thread 在等待該 cond
通過,用 while 來反覆監控會是一個比較合理的做法
誠實的面對自己,目前自己沒有發現可以改進的空間,對程式碼優化的敏感度還不足
TODO