the 1st edition: 20130301 the 2nd edition: 20151001 the 3rd edition: 20170727 the 4th edition: 20180427這篇是個雜記, 紀錄這三個惱人的東西還有一些自己的問題。
http://tw.myblog.yahoo.com/blue-comic/article?mid=253&prev=257&l=f&fid=26
http://blog.xuite.net/jackie.xie/bluelove/46644355
在寫怎麼樣的程式時, 需要考慮 reentrant?
在寫怎麼樣的程式時, 需要考慮 thread-safe?
在 multi-thread 程式中, 需要的是 reentrant 還是 thread-safe?
- Thread-safety and POSIX.1
- Threadsafe vs re-entrant
- The difference between thread-safety and re-entrancy
問題很混亂, 不過看了 pthread 多緒程式設計 (p237), 有了比較清楚的概念:
簡單提一下 (詳細請參閱該書籍):
thread safe: 使用 mutex 來保護 global data, 而 data 不一定是變數, 可能是檔案, 可能是某個週邊。由於用了 lock, 很有可能會有 dead lock 的問題。
reentrant function: 不可使用 static, global data, 一定可以正常執行, 也不會有 dead lock 的問題。
那 reentrant function 裡頭用 mutex 保護共用資源算 thread safe 嗎? 算, 不過那就不是 reentrant function 了, 請參考 malloc() is non-reentrant but thread-safe? [duplicate] 提到 reentrant, thread-safe 是如何的不同?
malloc 是 thread safe, 但不是 reentrant, 該怎麼解釋呢? reentrant 和 thread 的行為有點微妙的不同 (感謝 tg 的朋友解惑):
list 1 thread_1() 執行到 set_list() 時, 換 thread_2 執行, list 1 L17 會卡住 thread_2, 等到 scheduler 將執行權切回 list 1 L8 後, 執行 L10 的 unlock 後, 若這時候切回 thread_2, thread_2 得以繼續執行。
reentrant 會和中斷扯上關係:
list 2 func_1 執行到 set_list() 時, 中斷發動了, 改為執行 isr_1(), isr_1 卡在 list 2 L16, 但程式再也回不到 list 2 L7 那行了, 在中斷 isr 中, 沒有做完是切不回去 func_1 的, 這是和 thread 最不一樣的行為, 所以會一直卡在 list 2 L16 那行。
所以才說, malloc 是 thread safe, 但不是 reentrant。
以上兩個說法完全相反, 該聽誰的呢?
我自己是贊同《Linux 环境编程》的說法。但不用太拘泥名詞解釋, 了解本質上的不同是比較重要的。
reentrant.cpp 是我模仿 malloc 而來, 在程式執行後, 按下 ctrl+c SIGINT, 這時候用 ps 觀察
ps aux |grep reentrant descent 7210 0.2 0.0 15232 1640 pts/68 S+ 10:12 0:01 ./reentrant
PROCESS STATE CODES Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the state of a process: D uninterruptible sleep (usually IO) R running or runnable (on run queue) S interruptible sleep (waiting for an event to complete) T stopped, either by a job control signal or because it is being traced W paging (not valid since the 2.6.xx kernel) X dead (should never be seen) Z defunct ("zombie") process, terminated but not reaped by its parent For BSD formats and when the stat keyword is used, additional characters may be displayed: < high-priority (not nice to other users) N low-priority (nice to other users) L has pages locked into memory (for real-time and custom IO) s is a session leader l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do) + is in the foreground process group
處在 interruptible sleep (waiting for an event to complete), 程式無法正常結束, 應該是卡在 L15。
reentrant.cpp L17, L18 的 for loop 單純用來 delay, 在我系統上, 大概是 3 秒, 為的是讓 SIGINT 有時間可以在
15 pthread_mutex_lock(&mutex); ... 23 pthread_mutex_unlock(&mutex);
這中間的時候送出。
而程式也無法正常結束。
ref What does the “interruptible sleep” state indicate?
ref:
- 可重入與執行緒安全 (reentrant vs thread-safe) Part1
- 可重入與執行緒安全 (reentrant vs thread-safe) Part2
- 可重入與執行緒安全 (reentrant vs thread-safe) Part3
- 进程或者线程状态 (linux and java)
再來是 memory ordering (memory barrier) 這問題:
我也被這問題困惑很久, 在 os 下寫應用程式, 幾乎沒用過這種指令, 有需要在 os 下的應用程式使用這些指令嗎? 還是被 os api 給包裝起來了呢?
這是 linux 在 x86 下使用的 memory barrier 指令。
#define mb() asm volatile("mfence":::"memory") #define rmb() asm volatile("lfence":::"memory") #define wmb() asm volatile("sfence" ::: "memory")
arm cortex m3 memory barrier 指令: isb, dsb
Binary Hacks - 駭客秘傳技巧一百招 #94 在談這個, 看完就清楚了, 可是我不知道怎麼寫程式測試這個情形。
不過這樣的話, 在 os 下寫應用程式也會遇到這問題才是, 可是卻沒看過在 os 下的 c 應用程式用上這種指令。
multi-thread 程式要突破兩關:
- lock 機制 (使用 test-and-set 硬體指令實作)
- memory ordering (使用 memory barrier 指令)
1 通常由 os api 提供 (x86 可用 bts/xchg 實作, arm cortex M3 可用 ldrex/strex 來實作)。
2 我就沒看過在 os 下的應用程式要怎麼用, 只看過在 driver 階段有使用過。這篇提到 memory barrier pthread 已經實作在裡頭了。
thread 程式的共享變數還需要用 volatile 來宣告, 僅僅加上 lock 是不夠的。
ref:
详解C语言中volatile关键字
剖析为什么在多核多线程程序中要慎用volatile关键字?
ref memory barrier (ptt damody provides):
下一個類似的問題是:
mutex/semaphore and spin lock, 你知道的, 我要的不是教科書的解釋, 我想要實作這些東西出來, 能實作出來就真能代表懂了。
目前我在 arm cortex-m3 使用 ldrex/strex 實作出 spin lock。
Linux内核同步机制之(一):原子操作
這篇做了很好的解釋。
Linux内核同步机制之(三):memory barrier
蜗窝科技出版的文章, 質/量都很好。
ref:
Fast Atomic Counters With the x86 LOCK Prefix:
http://www.codemaestro.com/reviews/8
整理得很好 例子淺顯易懂 受教了
回覆刪除