clock_gettime can not update instantly

2019-05-20 07:43发布

Update

After checking the time resolution, we tried to debug the problem in kernel space.

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; 
}

Our new experiment shows that the time p->se.sum_exec_runtime is not updated instantly. But if we add printk() inside the function. the time will be updated instantly.

Old

We are developing an Android program. However, the time measured by the function threadCpuTimenanos() is not always correct on our platform.

After experimenting, we found that the time returned from clock_gettime is not updated instantly. Even after several while loop iterations, the time we get still doesn't change.

Here's our sample code:

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);
}

This code runs okay on an x86 PC. But it does not run correctly in our embedded platform ARM Cortex-A9 with kernel 2.6.35.13.

Any ideas?

5条回答
劫难
2楼-- · 2019-05-20 08:15

In the android CTS, there is a case that has the same problem. read timer twice but they are the same

testThreadCpuTimeNanos fail junit.framework.AssertionFailedError at android.os.cts.DebugTest.testThreadCpuTimeNanos

查看更多
祖国的老花朵
3楼-- · 2019-05-20 08:15

The CLOCK_THREAD_CPUTIME_ID clock measures CPU time spent, not realtime, and you're spending almost-zero CPU time. Also, CLOCK_THREAD_CPUTIME_ID (the thread-specific CPU time) is implemented incorrectly on Linux/glibc and likely does not even work at all on glibc. CLOCK_PROCESS_CPUTIME_ID or whatever that one's called should work better.

查看更多
三岁会撩人
4楼-- · 2019-05-20 08:18

I changed the clock_gettime to use the CLOCK_MONOTONIC_RAW , assigned the thread to one CPU and I get different values. I am also working with a dual cortex-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);
}
查看更多
乱世女痞
5楼-- · 2019-05-20 08:26

The resolution of clock_gettime is platform dependent. Use clock_getres() to find the resolution on your platform. According to the results of your experiment, clock resolutions on pc-x86 and on your target platform are different.

查看更多
Melony?
6楼-- · 2019-05-20 08:32

$man clock_gettime

...

Note for SMP systems

The CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID clocks are realized on many platforms using timers from the CPUs (TSC on i386, AR.ITC on Itanium). These registers may differ between CPUs and as a consequence these clocks may return bogus results if a process is migrated to another CPU.

If the CPUs in an SMP system have different clock sources then there is no way to maintain a correlation between the timer registers since each CPU will run at a slightly different frequency. If that is the case then clock_getcpuclockid(0) will return ENOENT to signify this condition. The two clocks will then only be useful if it can be ensured that a process stays on a certain CPU.

The processors in an SMP system do not start all at exactly the same time and therefore the timer registers are typically running at an offset. Some architectures include code that attempts to limit these offsets on bootup. However, the code cannot guarantee to accurately tune the offsets. Glibc contains no provisions to deal with these offsets (unlike the Linux Kernel). Typically these offsets are small and therefore the effects may be negligible in most cases.

查看更多
登录 后发表回答