ALSA回调(SIGIO处理程序)有时会在boost :: posix_time :: microsec_clock :: local_time()中的某处挂起

时间:2012-03-25 00:11:30

标签: c++ audio boost alsa

我在异步模式下使用ALSA和回调(snd_async_add_pcm_handler())。每个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 显示应用程序挂起:

        write(1, "+"..., 1)                     = 1
        gettimeofday({1332627252, 660534}, NULL) = 0
        futex(0xb68dba4c, FUTEX_WAIT_PRIVATE, 2, NULL <unfinished ...>
    

    但是 0xb68dba4c 在所有跟踪日志中仅发生了2到3次。 futex(0xb68dba4c ...... 不是每次getCurrentTimeMs()调用时发生的事情。但是当它发生时,一切都会挂起,只有在 gettimeofday 之后才会发生; i在控制台上看到“+。”,然后发生了 futex 。但在此之前,应用程序可以播放大量声音,每次回调调用 getCurrentTimeMs()每秒50次这么神秘......

    使用 #define Z 使用我的代码。在这种情况下,应用程序运行良好 - 播放数十亿字节的无挂起的WAV文件。

    应用程序有2个线程通过boost :: threadpool运行,并且都使用 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

  • 1 个答案:

    答案 0 :(得分:1)

    如果这对我来说是这样的,有两种异步调度需要考虑:异步线程和异步中断(“信号”)。线程彼此独立运行,除非它们明确同步;信号是异步调度的,但是抢占和阻止它们传递到的任何线程。它看起来非常像你正在调用的boost函数或iostream通过锁定来实现线程安全,这使得它们在中断处理程序中调用_un_safe,因为处理程序抢占的线程很可能已经锁定了。

    您可能要做的一件事就是安排将所有信号传递给一个不执行任何其他操作的线程 - 可能在启动时立即启动线程并让主线代码在那里运行,而原始主线程专用于信号处理