コールバック (snd_async_add_pcm_handler()) で ALSA を非同期モードで使用します。すべての ALSA のコールバックは、SIGIO シグナル ハンドラから呼び出されます。すべてのコールバックが私の関数getCurrentTimeMs()を呼び出します:
// Return current milliseconds (don't care - local time or UTC).
long long getCurrentTimeMs(void)
{
std::cout << "+"; std::cout.flush();
long long ret = 0;
#define Z
#ifdef Z
struct timespec ts;
clock_gettime( CLOCK_MONOTONIC, &ts);
ret = ts.tv_sec * 1000;
ret += ts.tv_nsec / 1000000;
#else
boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
std::cout << "."; std::cout.flush();
boost::posix_time::ptime epoch_start(boost::gregorian::date(1970,1,1));
std::cout << "."; std::cout.flush();
boost::posix_time::time_duration dur = now - epoch_start;
std::cout << "."; std::cout.flush();
ret = dur.total_milliseconds();
#endif
std::cout << "-"; std::cout.flush();
return ret;
}
#define Zにコメントすると、ブーストが使用されます。「ブースト モード」では、オーディオの再生開始から予測できない時間が経過すると、アプリケーションがハングします。strace show アプリケーションはこれでハングします:
書き込み (1、「+」...、1) = 1 gettimeofday({1332627252, 660534}, NULL) = 0 futex(0xb68dba4c, FUTEX_WAIT_PRIVATE, 2, NULL <未完成 ...>
しかし、0xb68dba4cはすべてのトレース ログで 2 ~ 3 回しか発生しませんでした。futex(0xb68dba4c ...は、すべての getCurrentTimeMs() 呼び出しで発生するものではありません。しかし、それが発生すると、すべてがハングし、そのgettimeofdayの後にのみ発生します。コンソールに「+.」が表示され、そのfutexが発生します。しかしその前に、アプリケーションは毎秒 50 回、各コールバックでgetCurrentTimeMs()を呼び出して、大量のサウンドを再生できます。
#define Zを使用すると、私のコードが使用されます。この場合、アプリケーションは問題なく動作し、数ギガバイトの WAV ファイルをハングすることなく再生できます。
アプリケーションには、boost::threadpool を介して実行される 2 つのスレッドがあり、両方ともgetCurrentTimeMs()を使用します。デッドロック エラーがあると仮定します。しかし、 #define Zがそれにどのように影響するかはわかりません。
編集:
私の質問はこのように答えられ、私はこの答えを受け入れます:
1) http://permalink.gmane.org/gmane.linux.alsa.devel/96282
2) http://answerpot.com/showthread.php? 3448138-ALSA+async+callback+re-enter+and+DEADLOCK .