pthread_cond_timedwait在CPU负载较大时延迟计时

时间:2017-04-04 15:10:50

标签: c++ c linux timeout posix

在为对象编写单元测试时,我注意到当CPU上有大量负载时,pthread_cond_timedwait不会很快超时。如果这些负载没有放在CPU上,一切正常。然而,当负载被放到系统上时,我发现无论我将超时设置为多长时间,真正的延迟都会消失大约50-100ms。

例如,这是从程序的单个间隔打印输出,其中使用函数GetTimeInMs找到最后和当前时间。

// Printout, values are in ms
Last: 89799240
Current: 89799440
Period Length: 200
Expected Period: 100

从我所看到的这个问题通常是由使用相对时间而不是绝对时间引起的,但据我所知,我们正确地使用绝对时间。如果你精彩的人可以帮助我弄清楚这里做错了什么,我将非常感激。

此处显示了使用timedwait的功能。请注意,基于我已完成的时序调试,我知道生成的额外时间是通过timedwait调用完成的,所以我没有包含其他不需要的代码。

bool func(unsigned long long int time = 100) // ms
{
    struct timespec ts;
    pthread_mutex_lock(&m_Mutex);

    if (0 == m_CurrentCount)
    {
       // Current time + delay in ns
       unsigned long long int absnanotime = (GetTimeInMs()+time)*1000000;

       struct timespec ts;
       ts.tv_nsec = absnanotime % 1000000000ULL;
       ts.tv_sec =  absnanotime / 1000000000ULL;

       do
       {
          if (0 != pthread_cond_timedwait(&m_Condition, &m_Mutex, &ts))
          {
             // In the case I am testing, I hope to get here via timeout in 100 ms
             pthread_mutex_unlock(&m_Mutex);
             return false;
          }
       }
       while (!m_CurrentCount);
    }

    pthread_mutex_unlock(&m_Mutex);
    return true;
}

unsigned long long int GetTimeInMs()
{
   unsigned long long int time;
   struct timespec ts;
   clock_gettime(CLOCK_MONOTONIC, &ts);
   time = ts.tv_nsec + ts.tv_sec * 1000000000ULL; 
   time = time / 1000000ULL; // Converts to ms
   return time;
}

用于初始化func中使用的类变量的代码。

void init()
{
   pthread_mutex_init(&m_Mutex, NULL);
   pthread_condattr_init(&m_Attr);
   pthread_condattr_setclock(&m_Attr, CLOCK_MONOTONIC);
   pthread_cond_init(&m_Condition, &m_Attr);
}

模拟CPU负载的CPU eater线程正在循环运行以下。

void cpuEatingThread()
{
    while (false == m_ShutdownRequested);
    {
      // m_UselessFoo is of type float*
      m_UselessFoo = new float(1.23423525);
      delete m_UselessFoo;
    }
}

2 个答案:

答案 0 :(得分:2)

当等待超时时,线程可能会在没有任何优先级提升或任何其他此类操作的情况下准备就绪。如果该框已加载,则就绪线程可能不会立即运行。

通常将临时优先级提升应用于准备就绪的线程 - 这有助于提高信号在超时之前到达的“通常”情况下的整体性能。超时通常更像是一个“不寻常”的事件,通常会发出某种不会重复的故障,因此线程在超时时就绪,可以等待轮流:)

答案 1 :(得分:2)

对于一般的定时等待,要求是他们将等待至少,只要他们的论点。如果你想要精确的时间,这不是正确的工具;你需要一些保证特定时间的东西,而这通常只能在实时操作系统(RTOS)中使用。