更新
在检查时间分辨率后,我们尝试在内核空间中调试问题。
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中无法正常运行。
有什么想法吗?
答案 0 :(得分:2)
我更改了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);
}
答案 1 :(得分:1)
clock_gettime
的分辨率取决于平台。使用clock_getres()
在您的平台上查找解决方案。根据您的实验结果,pc-x86和目标平台上的时钟分辨率是不同的。
答案 2 :(得分:1)
在android CTS中,有一个案例有同样的问题。读取计时器两次,但它们是相同的
testThreadCpuTimeNanos失败junit.framework.AssertionFailedError at android.os.cts.DebugTest.testThreadCpuTimeNanos
答案 3 :(得分:1)
$ 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内核不同)。通常这些偏移很小,因此在大多数情况下效果可以忽略不计。
答案 4 :(得分:0)
CLOCK_THREAD_CPUTIME_ID
时钟测量CPU花费的时间,而非实时,并且您花费的时间几乎为零。此外,CLOCK_THREAD_CPUTIME_ID
(特定于线程的CPU时间)在Linux / glibc上实现不正确,甚至可能在glibc上根本不起作用。 CLOCK_PROCESS_CPUTIME_ID
或者其中任何人应该更好地工作。