RT-Bench
An Extensible Benchmark Framework for Real-Time Applications
Loading...
Searching...
No Matches
periodic_benchmark.c File Reference

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>
+ Include dependency graph for periodic_benchmark.c:

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.
 

Detailed Description

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.

Author
Mattia Nicolella

Dependencies:

  • POSIX.4 real-time signals.

Macro Definition Documentation

◆ DEADLINE_TIMER_IN_USE

#define DEADLINE_TIMER_IN_USE   1

This value in deadline_timer_status determines that the deadline timer must be used

Function Documentation

◆ deadline_handler()

static void deadline_handler ( int  signo,
siginfo_t *  info,
void *  context 
)
static

The signal handler that is executed when the deadline timer expires.

Parameters
signoIgnored.
infoIgnored.
contextIgnored.

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.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ period_handler()

static void period_handler ( int  signo,
siginfo_t *  info,
void *  context 
)
static

The signal handler that is executed when the period timer expires.

Parameters
signoIgnored.
infoIgnored.
contextIgnored.

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().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ periodic_benchmark()

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.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ quit_handler()

static void quit_handler ( int  signo,
siginfo_t *  info,
void *  context 
)
static

SIGINT handler, causes the program to terminate in a clean way.

Parameters
signoIgnored.
infoIgnored.
contextIgnored.

Will call the exit function, it's invoked when a SIGINT is received.

+ Here is the caller graph for this function:

◆ setup_signal()

static int setup_signal ( int  handled_signal,
void(*)(int, siginfo_t *, void *)  handler,
int *  masked_signals,
int  masked_signals_num 
)
static

A simple function that is used to install a signal handler.

Parameters
[in]handled_signalThe signal that is to be associated to the handler.
[in]handlerThe handler that is to be associated to the signal.
[in]masked_signalsAn array, containing the signals that must be masked during the handler execution.
[in]masked_signals_numThe number of element of masked_signals.
+ Here is the caller graph for this function:

◆ setup_timer()

static int setup_timer ( timer_t *  timer,
int  signal_generated,
long  interval_sec,
long  interval_nsec 
)
static

A function that creates and arms a real-time timer.

Parameters
[out]timerThe pointer that will contain the created timer.
[in]signal_generatedThe signal that the timer must generated when it expires.
[in]interval_secThe seconds after which the timer will expire.
[in]interval_nsecThe 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.

+ Here is the caller graph for this function:

◆ stop_benchmark()

static void stop_benchmark ( int  status,
void *  arg 
)
static

Teardown function registered to be called when exit is called.

Parameters
[in]statusThe exit status.
[in]argIgnored.

Will ensure that all the requested resourced are freed, the memory watcher is stopped, and the output file is flushed and closed.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ deadline_timer_status

int deadline_timer_status
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.

◆ job_end_timestamp

long double job_end_timestamp = 0
static

Timestamp in seconds of when the last job ended, it can be 0 if the job has not finished yet.

◆ job_end_timestamp_clocks

unsigned long long job_end_timestamp_clocks = 0
static

Timestamp in clock cycles of when the last job ended, it can be 0 if the job has not finished yet.