2012年06月06日
Win32 API の CRITICAL_SECTION を pthread に移植する
(投稿したつもりで 8 ヶ月ほど下書きのまま放置されていた記事を見つけました…。せっかくなので投稿します。)
とある Windows の CRITICAL_SECTION を使ったマルチスレッドアプリを Linux に移植したのですが、pthread ライブラリを使って、とても簡単に移植できました。
とある Windows の CRITICAL_SECTION を使ったマルチスレッドアプリを Linux に移植したのですが、pthread ライブラリを使って、とても簡単に移植できました。
基本的には、以下のように、pthread ライブラリの mutex API で、CRITICAL_SECTION の API を実装しました。
ヘッダ
pthread_mutex_init() だけだと、PTHREAD_MUTEX_FAST_NP という挙動になり、ロック中にさらにロックしようとするとデッドロックになってしまいます。 PTHREAD_MUTEX_RECURSIVE_NP が CRITICAL_SECTION と同様に、再帰ロックを許す挙動となるので、mutexattr API で指定する必要があります。
参考:Port Windows IPC apps to Linux, Part 3: Mutexes, critical sections, and wait functions
2012/07/26:追記
pthread_mutexattr_init() を呼び出して mutexattr を初期化しておかないと、時々、以下のようにアサーションエラーになるようです。
参考:OBSCURE CHANGES IN UBUNTU 11.10
ヘッダ
#include <pthread.h> typedef pthread_mutex_t CRITICAL_SECTION; void InitializeCriticalSection(CRITICAL_SECTION *section); void EnterCriticalSection(CRITICAL_SECTION *section); void LeaveCriticalSection(CRITICAL_SECTION *section); 。。。本体
void InitializeCriticalSection(CRITICAL_SECTION *section) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); /* 2012/07/26 追記 */ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutex_init(section, &attr); pthread_mutexattr_destroy(&attr); } void EnterCriticalSection(CRITICAL_SECTION *section) { pthread_mutex_lock(section); } void LeaveCriticalSection(CRITICAL_SECTION *section) { pthread_mutex_unlock(section); } 。。。pthread の mutex のデフォルトの挙動が CRITICAL_SECTION とは異なる点に注意が必要です。
pthread_mutex_init() だけだと、PTHREAD_MUTEX_FAST_NP という挙動になり、ロック中にさらにロックしようとするとデッドロックになってしまいます。 PTHREAD_MUTEX_RECURSIVE_NP が CRITICAL_SECTION と同様に、再帰ロックを許す挙動となるので、mutexattr API で指定する必要があります。
参考:Port Windows IPC apps to Linux, Part 3: Mutexes, critical sections, and wait functions
2012/07/26:追記
pthread_mutexattr_init() を呼び出して mutexattr を初期化しておかないと、時々、以下のようにアサーションエラーになるようです。
tpp.c:63: __pthread_tpp_change_priority: Assertion `new_prio == -1 || (new_prio >= __sched_fifo_min_prio && new_prio <= __sched_fifo_max_prio)' failed.だいぶ昔に書いて、結局あまり使わなかったコードを、Ubuntu 11.10 64bit 環境に持ってきた際に発生して、不具合に気がつきました。
参考:OBSCURE CHANGES IN UBUNTU 11.10