How accurate nanosleep is in Ubuntu with PREEMPT_RT patch?

115 Views Asked by At

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, &param);
    param.sched_priority = priority;
    ret += pthread_attr_setschedparam (&attr, &param);
    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);
}
0

There are 0 best solutions below