I'm investigating the latency of my laptop running Ubuntu with Preempt_RT patch. I have written a C program that sleeps and wakes up periodically then reads the clock. I found that the "error" of the period is up to 300 μs. However, if I run the cyclictest provided by Ubuntu with the same thread priority, schedule policy and CPU affinity, I only got a latency of 60 μs. What can cause the difference? Why is my measured latency so high?
int64_t get_time()
{
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
return spec.tv_sec*1000*1000*1000 + spec.tv_nsec;
}
void
sleep_ns(uint64_t ns)
{
struct timespec ts;
ts.tv_sec = ns / 1000000000;
ts.tv_nsec = (ns % 1000000000);
nanosleep(&ts, NULL);
}
void *sleep(void *arg)
{
int64_t now;
struct timespec spec;
long time[600];
int i = 0;
now = get_time();
int64_t period = 10*1000*1000;
int64_t sleep_time = period;
int64_t wake_up = now + period;
while (!exit_flag) {
sleep_ns(sleep_time);
clock_gettime(CLOCK_MONOTONIC, &spec);
time[i++] = spec.tv_nsec;
wake_up = wake_up + period;
now = get_time();
sleep_time = wake_up - now;
}
for (i = 0; i < 600; i++)
{
printf("%ld\n", time[i]);
}
return 0;
}
void thread_create(pthread_t *thread_id, int policy, int priority, int cpu_id, void *(*function)(void *), void * arg)
{
struct sched_param param;
int ret;
pthread_attr_t attr;
ret = pthread_attr_init (&attr);
ret += pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);
ret += pthread_attr_setschedpolicy(&attr, policy);
ret += pthread_attr_getschedparam (&attr, ¶m);
param.sched_priority = priority;
ret += pthread_attr_setschedparam (&attr, ¶m);
if (cpu_id >= 0) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu_id, &cpuset);
ret += pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
}
ret += pthread_create(thread_id, &attr, function, arg);
if(ret!=0)
printf("Create thread %lu failed\n", *thread_id);
}
int main(int argc, char const *argv[])
{
pthread_t thread1 = 0;
thread_create(&thread1, SCHED_FIFO, 80, 2, sleep, NULL);
sleep_ns(5000000000);
exit_flag = true;
pthread_join(thread1, NULL);
}