【问题标题】:clock_gettime can not update instantlyclock_gettime 无法立即更新
【发布时间】:2012-06-26 14:52:11
【问题描述】:

更新

检查时间分辨率后,我们尝试在内核空间调试问题。

unsigned long long task_sched_runtime(struct task_struct *p)
{
    unsigned long flags;
    struct rq *rq;
    u64 ns = 0;

    rq = task_rq_lock(p, &flags);
    ns = p->se.sum_exec_runtime + do_task_delta_exec(p, rq);
    task_rq_unlock(rq, &flags);

    //printk("task_sched runtime\n");
    return ns; 
}

我们的新实验表明时间p->se.sum_exec_runtime 不会立即更新。但是如果我们在函数内部添加printk()。时间将立即更新。

我们正在开发一个 Android 程序。 但是,threadCpuTimenanos() 函数测量的时间在我们的平台上并不总是正确的。

经过实验,我们发现clock_gettime返回的时间不是即时更新的。 即使经过几次 while 循环迭代,我们得到的时间仍然没有改变。

这是我们的示例代码:

while(1)
{
    test = 1;
    test = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);

    printf(" clock gettime test 1 %lx, %lx , ret = %d\n",now.tv_sec , now.tv_nsec,test );

    pre = now.tv_nsec;
    sleep(1);
}

此代码在 x86 PC 上运行良好。但它不能在我们的内核 2.6.35.13 的嵌入式平台 ARM Cortex-A9 中正确运行。

有什么想法吗?

【问题讨论】:

  • 也许计数器只精确到毫秒?这个循环几乎不消耗 CPU,所以需要多轮才能达到 1ms。您是否尝试用忙碌的等待来代替睡眠?
  • 您要测量什么?过了“挂钟时间”的时间还是你的程序占用 CPU 的时间?
  • 是的,睡眠是不必要的。我们想稍后测量他。时间程序占用CPU。

标签: android c linux timer arm


【解决方案1】:

我更改了 clock_gettime 以使用 CLOCK_MONOTONIC_RAW ,将线程分配给一个 CPU,我得到不同的值。 我也在使用双皮质-A9

while(1)
{
    test = 1;
    test = clock_gettime(CLOCK_MONOTONIC_RAW, &now);

    printf(" clock gettime test 1 %lx, %lx , ret = %d\n",now.tv_sec , now.tv_nsec, test );

    pre = now.tv_nsec;
    sleep(1);
}

【讨论】:

  • 你在clock_gettimes之间有一个很大的printf,连续调用clock_gettime,你会看到有时你会得到零差异,如果分辨率下降到1ns,这真的没有意义。
【解决方案2】:

clock_gettime 的分辨率取决于平台。使用clock_getres() 在您的平台上查找分辨率。根据您的实验结果,pc-x86 和您的目标平台上的时钟分辨率是不同的。

【讨论】:

  • 感谢您的热情回复。但我们发现时间分辨率与 x86 相同。
【解决方案3】:

在android CTS中,有一个case也有同样的问题。两次读取计时器,但它们是相同的

testThreadCpuTimeNanos 失败 junit.framework.AssertionFailedError 在 android.os.cts.DebugTest.testThreadCpuTimeNanos

【讨论】:

    【解决方案4】:

    $man clock_gettime

    ...

    SMP 系统注意事项

    CLOCK_PROCESS_CPUTIME_ID 和 CLOCK_THREAD_CPUTIME_ID 时钟是在许多平台上使用来自 CPU 的计时器实现的(i386 上的 TSC,Itanium 上的 AR.ITC)。这些寄存器在 CPU 之间可能不同,因此如果将进程迁移到另一个 CPU,这些时钟可能会返回虚假结果

    如果 SMP 系统中的 CPU 具有不同的时钟源,则无法保持定时器寄存器之间的相关性,因为每个 CPU 将以稍微不同的频率运行。如果是这种情况,那么clock_getcpuclockid(0) 将返回ENOENT 来表示这种情况。只有在可以确保进程停留在某个 CPU 上时,这两个时钟才会有用。

    SMP 系统中的处理器并非在完全相同的时间启动,因此定时器寄存器通常以偏移量运行。一些架构包括尝试在启动时限制这些偏移的代码。但是,代码不能保证准确地调整偏移量。 Glibc 不包含处理这些偏移量的规定(与 Linux 内核不同)。通常这些偏移量很小,因此在大多数情况下影响可以忽略不计。

    【讨论】:

      【解决方案5】:

      CLOCK_THREAD_CPUTIME_ID 时钟测量的是 CPU 时间,而不是实时的,而且你的 CPU 时间几乎为零。此外,CLOCK_THREAD_CPUTIME_ID(特定于线程的 CPU 时间)在 Linux/glibc 上实现不正确,甚至可能在 glibc 上根本不起作用。 CLOCK_PROCESS_CPUTIME_ID 或其他任何称呼应该会更好。

      【讨论】:

      • 是的,线程中cpu消耗的时间几乎为零。但是,即使我们在一会儿带走睡眠。结果还是一样。并尝试 CLOCK_PROCESS_CPUTIME_ID 仍然没有工作。
      猜你喜欢
      • 2017-05-09
      • 2013-01-06
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      • 2012-11-10
      • 2016-08-06
      • 1970-01-01
      • 2018-11-08
      相关资源
      最近更新 更多