Commit 906654ca authored by Joanne Hugé's avatar Joanne Hugé

Set latency target in client

parent b065e1ea
......@@ -8,6 +8,7 @@
#define _GNU_SOURCE
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <limits.h>
#include <pthread.h>
#include <sched.h>
......@@ -17,6 +18,8 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
......@@ -86,6 +89,8 @@ static enum TSNTask tsn_task;
static struct timespec measures_start;
static struct timespec measures_end;
static char send_data[MAX_BUFFER_SIZE];
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
static void help(char *argv[]) {
printf(
......@@ -113,6 +118,45 @@ static void help(char *argv[]) {
argv[0]);
}
/* Latency trick
* if the file /dev/cpu_dma_latency exists,
* open it and write a zero into it. This will tell
* the power management system not to transition to
* a high cstate (in fact, the system acts like idle=poll)
* When the fd to /dev/cpu_dma_latency is closed, the behavior
* goes back to the system default.
*
* Documentation/power/pm_qos_interface.txt
*/
static void set_latency_target(void) {
struct stat s;
int err;
errno = 0;
err = stat("/dev/cpu_dma_latency", &s);
if (err == -1) {
error(EXIT_FAILURE, errno, "WARN: stat /dev/cpu_dma_latency failed");
return;
}
errno = 0;
latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR);
if (latency_target_fd == -1) {
error(EXIT_FAILURE, errno, "WARN: open /dev/cpu_dma_latency");
return;
}
errno = 0;
err = write(latency_target_fd, &latency_target_value, 4);
if (err < 1) {
error(EXIT_FAILURE, errno, "# error setting cpu_dma_latency to %d!",
latency_target_value);
close(latency_target_fd);
return;
}
printf("# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
}
/*
* Real-time thread:
* - Sends packets at a regular intervall
......@@ -137,11 +181,11 @@ static void *packet_sending_thread(void *p) {
clock_gettime(CLOCK_REALTIME, &next);
if (thread_params.start_ts) {
if(thread_params.start_ts < ts_to_uint(next)) {
if (thread_params.start_ts < ts_to_uint(next)) {
fprintf(stderr, "start timestamp is in the past, aborting...\n");
exit(EXIT_FAILURE);
}
if(thread_params.start_ts > (ts_to_uint(next) + UINT64_C(3600000000000))) {
if (thread_params.start_ts > (ts_to_uint(next) + UINT64_C(3600000000000))) {
fprintf(stderr, "start timestamp is too high, aborting...\n");
exit(EXIT_FAILURE);
}
......@@ -192,7 +236,7 @@ static void *packet_sending_thread(void *p) {
if (thread_params.enable_threshold_tracing) {
int jitter = (egress_stats.max_interval - egress_stats.min_interval);
if ( jitter > thread_params.threshold) {
if (jitter > thread_params.threshold) {
tracemark("Threshold reached\n");
tracing(0);
printf("Threshold reached: %dus\n", jitter);
......@@ -205,11 +249,10 @@ static void *packet_sending_thread(void *p) {
previous = current;
ret = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL);
if(ret) {
if (ret) {
fprintf(stderr, "clock_nanosleep returned error: %d, aborting...\n", ret);
exit(EXIT_FAILURE);
}
}
pthread_exit(NULL);
......@@ -255,6 +298,8 @@ int main(int argc, char *argv[]) {
// Process bash options
process_options(argc, argv);
set_latency_target();
egress_params.use_etf = enable_etf;
egress_params.use_timestamps = enable_timestamps;
......@@ -415,12 +460,13 @@ static void print_histograms() {
printf(
"# Duration: %dh%d\n"
"# High kernel latencies: %" PRIu64 "\n"
"# Invalid parameters: %" PRIu64 "\n"
"# High kernel latencies: %" PRIu64
"\n"
"# Invalid parameters: %" PRIu64
"\n"
"# Missed deadlines: %" PRIu64 "\n",
duration_hour, duration_minutes, egress_stats.high_kernel_latency,
egress_stats.invalid_parameter, egress_stats.missed_deadline);
}
static void sighand(int sig_num) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment