5

私はクロスプラットフォームの C++ エンジンを Android に移植してきましたが、pthread_mutex_lockを呼び出すと不可解に (そして一貫性なく) ブロックされることに気付きました。このエンジンはすでにいくつかのプラットフォームで長年動作しており、問題のあるコードは何年も変更されていないため、デッドロックまたはバグのあるコードではないかと思います。それはAndroidへの私のポートでなければなりません..

これまでのところ、pthread_mutex_lock でブロックするコードの場所がいくつかあります。また、完全に再現できるわけではありません。ハングしても、LogCat に疑わしい出力はありません。

このようにミューテックスコードを変更しました(簡潔にするために編集...実際のコードはすべての戻り値をチェックします):

void MutexCreate( Mutex* m )
{
#ifdef WINDOWS
    InitializeCriticalSection( m );
#else ANDROID
    pthread_mutex_init( m, NULL );
#endif
}


void MutexDestroy( Mutex* m )
{
#ifdef WINDOWS
    DeleteCriticalSection( m );
#else ANDROID
    pthread_mutex_destroy( m, NULL );
#endif
}

void MutexLock( Mutex* m )
{
#ifdef WINDOWS
    EnterCriticalSection( m );
#else ANDROID
    pthread_mutex_lock( m );
#endif
}

void MutexUnlock( Mutex* m )
{
#ifdef WINDOWS
    LeaveCriticalSection( m );
#else ANDROID
    pthread_mutex_unlock( m );
#endif
}

MutexCreate を変更して、エラー チェックと再帰的ミューテックスを作成しようとしましたが、問題ありませんでした。エラーやログ出力も得られなかったので、ミューテックス コードに問題がないか、エラー/ログが表示されていませんでした。OS はミューテックスの不適切な使用をどのように正確に通知しますか?

エンジンはミューテックスを含む静的変数を多用します。よく見えないけど、何か問題あるの?代わりにヒープに割り当てられるように多くのミューテックスを変更し、同じ動作が発生したため、私はそれを疑っています。しかし、それは、いくつかの静的ミューテックスを見逃したためかもしれません。私はおそらくここでストローをつかんでいます。

以下を含むいくつかの参考文献を読みました。

http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_mutex_init.html

http://www.embedded-linux.co.uk/tutorial/mutex_mutandis

http://linux.die.net/man/3/pthread_mutex_init

Android NDK ミューテックス

Android NDK の問題 pthread_mutex_unlock の問題

4

1 に答える 1

2

「エラーチェック」ミューテックスは、いくつかのこと (非再帰的ミューテックスを再帰的に使用しようとする試みなど) をチェックしますが、目を見張るものはありません。

「実際のコードはすべての戻り値をチェックする」と言ったので、pthread呼び出しがゼロ以外の値を返すと、おそらくコードが爆発します。(なぜあなたの pthread_mutex_destroy が2つの引数を取るのか分かりません;コピー&ペーストエラーを想定しています。)

pthread コードは Android 内で広く使用されており、既知のハングアップがないため、pthread 実装自体に問題がある可能性は低いです。

ミューテックスの現在の実装は 32 ビットに収まるので、整数として出力すると、現在の状態 (技術的に、過去のある時点での状態)*(pthread_mutex_t* mut)を把握できるはずです。bionic/libc/bionic/pthread.c の定義は次のとおりです。

/* a mutex is implemented as a 32-bit integer holding the following fields
 *
 * bits:     name     description
 * 31-16     tid      owner thread's kernel id (recursive and errorcheck only)
 * 15-14     type     mutex type
 * 13        shared   process-shared flag
 * 12-2      counter  counter of recursive mutexes
 * 1-0       state    lock state (0, 1 or 2)
 */

tid「高速」ミューテックスのタイプは 0 で、フィールドを設定しません。実際、汎用ミューテックスの値は、0 (保持されていない)、1 (保持されている)、または 2 (保持され、競合あり) です。値がこれらのいずれでもない高速なミューテックスを見かけた場合は、何かがやってきてそれを踏みつけた可能性があります。

また、再帰的ミューテックスを使用するようにプログラムを構成する場合、ビットを引き出すことで (trylock が停止しようとしていることを示したときにミューテックス値を出力するか、gdb で状態をダンプすることにより)、どのスレッドがミューテックスを保持しているかを確認できることも意味します。ハングしたプロセスで)。これに加えて の出力によりps -t、ミューテックスをロックしたスレッドがまだ存在するかどうかがわかります。

于 2012-12-11T00:46:51.473 に答える