2012年06月06日

Win32 API の CRITICAL_SECTION を pthread に移植する

(投稿したつもりで 8 ヶ月ほど下書きのまま放置されていた記事を見つけました…。せっかくなので投稿します。)

とある Windows の CRITICAL_SECTION を使ったマルチスレッドアプリを Linux に移植したのですが、pthread ライブラリを使って、とても簡単に移植できました。


基本的には、以下のように、pthread ライブラリの mutex API で、CRITICAL_SECTION の API を実装しました。
ヘッダ
#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

トラックバックURL

コメントする

名前
URL
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード