RT-Bench
An Extensible Benchmark Framework for Real-Time Applications
|
Implementation of a general periodic benchmark using real time timers. More...
#include "periodic_benchmark.h"
#include "performance_counters.h"
#include "performance_sampler.h"
#include "get_cpu_timestamp.h"
#include "logging.h"
#include "memory_watcher.h"
#include <bits/types/siginfo_t.h>
#include <bits/types/struct_itimerspec.h>
#include <errno.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
Macros | |
#define | DEADLINE_TIMER_IN_USE 1 |
#define | DEFAULT_OUTPUT_PATH "./timing.csv" |
Default output path and filename for timing information. | |
#define | DEFAULT_PERFORMANCE_COUNTER_SAMPLING_OUTPUT_PATH "./perf.csv" |
Default output path and filename for performance counter runtime monitoring. | |
#define | PRINT_SKIPPED_DEADLINE 0 |
Indicates whether to print skipped deadelines with 0s. | |
#define | SIGNAL_DEADLINE SIGRTMIN |
The real-time signal that identifies the deadline occurrence. | |
#define | SIGNAL_END_PERIOD SIGRTMIN + 1 |
The real-time signal that identifies the end of the period. | |
Functions | |
static void | deadline_handler (int signo, siginfo_t *info, void *context) |
The signal handler that is executed when the deadline timer expires. More... | |
static void | period_handler (int signo, siginfo_t *info, void *context) |
The signal handler that is executed when the period timer expires. More... | |
int | periodic_benchmark (struct execution_options *exec_opts) |
Handles the timer creation, setup and the periodic execution of a generic benchmark. More... | |
static void | quit_handler (int signo, siginfo_t *info, void *context) |
SIGINT handler, causes the program to terminate in a clean way. More... | |
static int | setup_signal (int handled_signal, void(*handler)(int, siginfo_t *, void *), int *masked_signals, int masked_signals_num) |
A simple function that is used to install a signal handler. More... | |
static int | setup_timer (timer_t *timer, int signal_generated, long interval_sec, long interval_nsec) |
A function that creates and arms a real-time timer. More... | |
static void | stop_benchmark (int status, void *arg) |
Teardown function registered to be called when exit is called. More... | |
Variables | |
static int | benchmark_param_num = 0 |
Number of parameters passed to the benchmark. | |
static void ** | benchmark_params = NULL |
Benchmark parameters array. | |
static timer_t | deadline_timer = NULL |
Real time timer, used to notify when the deadline is reached. | |
static int | deadline_timer_status |
If the deadline timer must be used. More... | |
static struct itimerspec | deadline_timing |
The timing interval of a deadline, used to rearm the deadline timer. | |
static float | extra_measurement = 0.0f |
Extra benchmark dependant measured data. | |
static FILE * | filep = NULL |
The file pointer to the timing output file. | |
static long double | job_deadline_timestamp = 0 |
Timestamp in seconds clock cycles of when the first deadline since the job start has occurred. | |
static unsigned long long | job_deadline_timestamp_clocks = 0 |
Timestamp in clock cycles of when the first deadline since the job start has occurred. | |
static long double | job_end_timestamp = 0 |
static unsigned long long | job_end_timestamp_clocks = 0 |
static struct perf_counters | job_perf_counters_end |
Performance counters at the end of the period. | |
static struct perf_counters | job_perf_counters_start |
Performance counters at the start of the period. | |
static long double | job_period_end_timestamp = 0 |
Timestamp in seconds of the period end. | |
static unsigned long long | job_period_end_timestamp_clocks = 0 |
Timestamp in clock cycles of the period end. | |
static long double | job_period_start_timestamp = 0 |
Timestamp in seconds of the period start. | |
static unsigned long long | job_period_start_timestamp_clocks = 0 |
Timestamp in clock cycles of the period start. | |
static long double | last_deadline_timestamp = 0 |
Timestamp in seconds of when the last deadline since the job start has occurred. | |
static unsigned long long | last_deadline_timestamp_clocks = 0 |
Timestamp in clock cycles of when the last deadline since the job start has occurred. | |
static sem_t | period_sem |
Semaphore used to determine if a new job can be started. | |
static timer_t | period_timer |
Real time timer, used to notify when the period end is reached. | |
static unsigned long long | tasks_launched = 0 |
Number of tasks launched. | |
Implementation of a general periodic benchmark using real time timers.
Timer expiration triggers a real time POSIX signal and SIGINT
is used to stop the benchmark and terminate the program.
Dependencies:
#define DEADLINE_TIMER_IN_USE 1 |
This value in deadline_timer_status
determines that the deadline timer must be used
|
static |
The signal handler that is executed when the deadline timer expires.
signo | Ignored. |
info | Ignored. |
context | Ignored. |
When the deadline timer expires, the current timestamp is saved in last_deadline_timestamp
, If this if the first deadline expiration since the period start, then the timestamp values is also copied in job_deadline_timestamp
. Both get_rdtsc()
and get_timestamp()
are used, to be safe in case only one of these methods is working.
|
static |
The signal handler that is executed when the period timer expires.
signo | Ignored. |
info | Ignored. |
context | Ignored. |
When the period expires and the job has terminated its execution, the deadline timer is rearmed, the job's stats are reported, the semaphore is unlocked and the reporting variables are reset. The start of the next period matches with the end of the previous period. The next job starts as soon as the semaphore is unlocked, and this creates a slight overhead, since before unlocking the semaphore the previous job stats must be reported. When the period ends but no start timestamp was recorded (job_period_start_timestamp
is 0
), no reporting will be done.
If the job has not terminated when the period ends, a deadline skip is reported if the deadline that has been missed is not the first since the job start.
Finally, if the deadline matches the period, the period handler will also perform the same operations as deadline_handler()
, but will use the timestamp of the period end.
Both get_rdtsc()
and get_timestamp()
are used, to be safe in case only one of these methods is working.
Reporting is done using print_statistics()
.
int periodic_benchmark | ( | struct execution_options * | exec_opts | ) |
Handles the timer creation, setup and the periodic execution of a generic benchmark.
This function will prepare the environment for executing the job, initialize the timers and signal handlers. If bytes_to_preallocate
in execution_options
is not 0
(which is set in the command line via the -m
option) the memory watcher is also initialized. When the environment for the periodic benchmark is initialized, the benchmark will be periodically executed.
To execute the benchmark periodically we use two timers that fire different real time signals:
SIGNAL_DEADLINE
which will be fired when the deadline occurs, if the deadline is less than the period.SIGNAL_END_PERIOD
which will be fired when the period ends.After the setup, the periodic benchmark will start after a SIGNAL_END_PERIOD
is received, to allow a start with reduced delay.
When a SIGINT
is received, the timer will be destroyed and the environment for the job execution will be cleaned.
The environment for the job execution is handled by calling the benchmark_init()
and benchmark_teardown()
functions.
Both get_rdtsc()
and get_timestamp()
are used, to be safe in case only one of these methods is working.
|
static |
SIGINT handler, causes the program to terminate in a clean way.
signo | Ignored. |
info | Ignored. |
context | Ignored. |
Will call the exit function, it's invoked when a SIGINT
is received.
|
static |
A simple function that is used to install a signal handler.
[in] | handled_signal | The signal that is to be associated to the handler. |
[in] | handler | The handler that is to be associated to the signal. |
[in] | masked_signals | An array, containing the signals that must be masked during the handler execution. |
[in] | masked_signals_num | The number of element of masked_signals . |
|
static |
A function that creates and arms a real-time timer.
[out] | timer | The pointer that will contain the created timer. |
[in] | signal_generated | The signal that the timer must generated when it expires. |
[in] | interval_sec | The seconds after which the timer will expire. |
[in] | interval_nsec | The nanoseconds after which the timer will expire. |
The function will create and arm the timer for a periodic execution, with the specified timing. The timer will be armed immediately after creation.
interval_sec
and interval_nsec
can be used in conjunction to specify when the timer must expire and if they are both set to 0
the timer will not be armed.
|
static |
Teardown function registered to be called when exit is called.
[in] | status | The exit status. |
[in] | arg | Ignored. |
Will ensure that all the requested resourced are freed, the memory watcher is stopped, and the output file is flushed and closed.
|
static |
If the deadline timer must be used.
Possible values should be only DEADLINE_TIMER_IN_USE
when a separate deadline timer is used or !DEADLINE_TIMER_IN_USE
when only the period timer is used.
|
static |
Timestamp in seconds of when the last job ended, it can be 0 if the job has not finished yet.
|
static |
Timestamp in clock cycles of when the last job ended, it can be 0 if the job has not finished yet.