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

Set latency target in client

parent b065e1ea
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <error.h> #include <error.h>
#include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
...@@ -17,6 +18,8 @@ ...@@ -17,6 +18,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
...@@ -86,6 +89,8 @@ static enum TSNTask tsn_task; ...@@ -86,6 +89,8 @@ static enum TSNTask tsn_task;
static struct timespec measures_start; static struct timespec measures_start;
static struct timespec measures_end; static struct timespec measures_end;
static char send_data[MAX_BUFFER_SIZE]; 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[]) { static void help(char *argv[]) {
printf( printf(
...@@ -113,6 +118,45 @@ static void help(char *argv[]) { ...@@ -113,6 +118,45 @@ static void help(char *argv[]) {
argv[0]); 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: * Real-time thread:
* - Sends packets at a regular intervall * - Sends packets at a regular intervall
...@@ -137,11 +181,11 @@ static void *packet_sending_thread(void *p) { ...@@ -137,11 +181,11 @@ static void *packet_sending_thread(void *p) {
clock_gettime(CLOCK_REALTIME, &next); clock_gettime(CLOCK_REALTIME, &next);
if (thread_params.start_ts) { 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"); fprintf(stderr, "start timestamp is in the past, aborting...\n");
exit(EXIT_FAILURE); 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"); fprintf(stderr, "start timestamp is too high, aborting...\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -192,7 +236,7 @@ static void *packet_sending_thread(void *p) { ...@@ -192,7 +236,7 @@ static void *packet_sending_thread(void *p) {
if (thread_params.enable_threshold_tracing) { if (thread_params.enable_threshold_tracing) {
int jitter = (egress_stats.max_interval - egress_stats.min_interval); int jitter = (egress_stats.max_interval - egress_stats.min_interval);
if ( jitter > thread_params.threshold) { if (jitter > thread_params.threshold) {
tracemark("Threshold reached\n"); tracemark("Threshold reached\n");
tracing(0); tracing(0);
printf("Threshold reached: %dus\n", jitter); printf("Threshold reached: %dus\n", jitter);
...@@ -205,11 +249,10 @@ static void *packet_sending_thread(void *p) { ...@@ -205,11 +249,10 @@ static void *packet_sending_thread(void *p) {
previous = current; previous = current;
ret = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL); ret = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL);
if(ret) { if (ret) {
fprintf(stderr, "clock_nanosleep returned error: %d, aborting...\n", ret); fprintf(stderr, "clock_nanosleep returned error: %d, aborting...\n", ret);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
pthread_exit(NULL); pthread_exit(NULL);
...@@ -255,6 +298,8 @@ int main(int argc, char *argv[]) { ...@@ -255,6 +298,8 @@ int main(int argc, char *argv[]) {
// Process bash options // Process bash options
process_options(argc, argv); process_options(argc, argv);
set_latency_target();
egress_params.use_etf = enable_etf; egress_params.use_etf = enable_etf;
egress_params.use_timestamps = enable_timestamps; egress_params.use_timestamps = enable_timestamps;
...@@ -415,12 +460,13 @@ static void print_histograms() { ...@@ -415,12 +460,13 @@ static void print_histograms() {
printf( printf(
"# Duration: %dh%d\n" "# Duration: %dh%d\n"
"# High kernel latencies: %" PRIu64 "\n" "# High kernel latencies: %" PRIu64
"# Invalid parameters: %" PRIu64 "\n" "\n"
"# Invalid parameters: %" PRIu64
"\n"
"# Missed deadlines: %" PRIu64 "\n", "# Missed deadlines: %" PRIu64 "\n",
duration_hour, duration_minutes, egress_stats.high_kernel_latency, duration_hour, duration_minutes, egress_stats.high_kernel_latency,
egress_stats.invalid_parameter, egress_stats.missed_deadline); egress_stats.invalid_parameter, egress_stats.missed_deadline);
} }
static void sighand(int sig_num) { 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