lf-lang / reactor-c

A reactor runtime written in C
Other
10 stars 23 forks source link

Improving timing precision on Linux #419

Open erlingrj opened 2 months ago

erlingrj commented 2 months ago

I got a really good tip from Henrik which is that you can prevent the CPU from changing c-states and greatly improve the wakeup accuracy. I don't understand the details of why keeping this specific file descriptor open does the trick and how portable it is, but Linux-users can try it out themselves:

This might be interesting for @soyerefsane

target C;

reactor Default {
  timer t(0, 100 msec)
  reaction(t) {=
    lf_print(PRINTF_TIME, lf_time_physical() - lf_time_logical());
  =}
}

reactor RT extends Default {
  reaction(startup) {=
    lf_scheduling_policy_t cfg;
    cfg.policy = LF_SCHED_PRIORITY;
    cfg.priority = 99;
    int res = lf_thread_set_scheduling_policy(lf_thread_self(), &cfg);
    if (res != 0) {
      lf_print_error_and_exit("lf_thread_set_scheduling_policy failed with %d", res);
    }
  =}
}

reactor CStatesRT extends Default {
  preamble {=
    #include <fcntl.h>
    #include <errno.h>
  =}
  state dma_lat_fd:int = -1
  reaction(startup) {=
    lf_scheduling_policy_t cfg;
    cfg.policy = LF_SCHED_PRIORITY;
    cfg.priority = 99;
    int res = lf_thread_set_scheduling_policy(lf_thread_self(), &cfg);
    if (res != 0) {
      lf_print_error_and_exit("lf_thread_set_scheduling_policy failed with %d", res);
    }
    /* disable dma latency, this avoids c-state transitions */
      self->dma_lat_fd = open("/dev/cpu_dma_latency", O_RDWR);
      if (self->dma_lat_fd >= 0) {
      int lat_val = 0;
      int wres = write(self->dma_lat_fd, &lat_val, sizeof(lat_val));
      if (wres < 1) {
        lf_print_error_and_exit("Failed writing %d to /dev/cpu_dma_latency (%d)",
          lat_val, errno);
      }
    } else {
      lf_print_error_and_exit("Failed to open cpu_dma_latency (%d)", self->dma_lat_fd);
    }
  =}

  reaction(shutdown) {=
    if (self->dma_lat_fd) {
      int res = close(self->dma_lat_fd);
      if (res != 0) {
        lf_print_error_and_exit("Failed to close cpu_dma_latency (%d)", res);
      }
    }
  =}
}

main reactor {
  // r = new Default()
 // r = new RT()
  r = new CStatesRT()
}