mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
206 lines
7.1 KiB
C
206 lines
7.1 KiB
C
/*
|
|
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
|
*/
|
|
|
|
#ifndef __TIME_MEAS_DEFS__H__
|
|
#define __TIME_MEAS_DEFS__H__
|
|
|
|
#include <unistd.h>
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <pthread.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/types.h>
|
|
// global var to enable openair performance profiler
|
|
extern int cpu_meas_enabled;
|
|
extern double cpu_freq_GHz __attribute__ ((aligned(32)));
|
|
// structure to store data to compute cpu measurment
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
|
|
typedef long long oai_cputime_t;
|
|
#else
|
|
#error "building on unsupported CPU architecture"
|
|
#endif
|
|
|
|
#define TIMESTAT_MSGID_START 0 /*!< \brief send time at measure starting point */
|
|
#define TIMESTAT_MSGID_STOP 1 /*!< \brief send time at measure end point */
|
|
#define TIMESTAT_MSGID_ENABLE 2 /*!< \brief enable measure point */
|
|
#define TIMESTAT_MSGID_DISABLE 3 /*!< \brief disable measure point */
|
|
#define TIMESTAT_MSGID_DISPLAY 10 /*!< \brief display measure */
|
|
#define TIMESTAT_MSGID_END 11 /*!< \brief stops the measure threads and free assocated resources */
|
|
typedef void(*meas_printfunc_t)(const char* format, ...);
|
|
typedef struct {
|
|
int msgid; /*!< \brief message id, as defined by TIMESTAT_MSGID_X macros */
|
|
int timestat_id; /*!< \brief points to the time_stats_t entry in cpumeas table */
|
|
oai_cputime_t ts; /*!< \brief time stamp */
|
|
meas_printfunc_t displayFunc; /*!< \brief function to call when DISPLAY message is received*/
|
|
} time_stats_msg_t;
|
|
|
|
struct notifiedFIFO_elt_s;
|
|
typedef struct time_stats {
|
|
oai_cputime_t in; /*!< \brief time at measure starting point */
|
|
oai_cputime_t diff; /*!< \brief average difference between time at starting point and time at endpoint*/
|
|
oai_cputime_t p_time; /*!< \brief absolute process duration */
|
|
double diff_square; /*!< \brief process duration square */
|
|
oai_cputime_t max; /*!< \brief maximum difference between time at starting point and time at endpoint*/
|
|
int trials; /*!< \brief number of start point - end point iterations */
|
|
int meas_flag; /*!< \brief 1: stop_meas not called (consecutive calls of start_meas) */
|
|
char *meas_name; /*!< \brief name to use when printing the measure (not used for PHY simulators)*/
|
|
int meas_index; /*!< \brief index of this measure in the measure array (not used for PHY simulators)*/
|
|
int meas_enabled; /*!< \brief per measure enablement flag. send_meas tests this flag, unused today in start_meas and stop_meas*/
|
|
struct notifiedFIFO_elt_s *tpoolmsg; /*!< \brief message pushed to the cpu measurment queue to report a measure START or STOP */
|
|
time_stats_msg_t *tstatptr; /*!< \brief pointer to the time_stats_msg_t data in the tpoolmsg, stored here for perf considerations*/
|
|
} time_stats_t;
|
|
#define MEASURE_ENABLED(X) (X->meas_enabled)
|
|
|
|
static inline void start_meas(time_stats_t *ts) __attribute__((always_inline));
|
|
static inline void stop_meas(time_stats_t *ts) __attribute__((always_inline));
|
|
|
|
void print_meas_now(time_stats_t *ts, const char *name, FILE *file_name);
|
|
void print_meas(time_stats_t *ts, const char *name, time_stats_t *total_exec_time, time_stats_t *sf_exec_time);
|
|
size_t print_meas_log(time_stats_t *ts,
|
|
const char *name,
|
|
time_stats_t *total_exec_time,
|
|
time_stats_t *sf_exec_time,
|
|
char *output,
|
|
size_t outputlen);
|
|
double get_time_meas_us(time_stats_t *ts);
|
|
double get_cpu_freq_GHz(void);
|
|
|
|
#if defined(__i386__)
|
|
static inline unsigned long long rdtsc_oai(void) __attribute__((always_inline));
|
|
static inline unsigned long long rdtsc_oai(void) {
|
|
unsigned long long int x;
|
|
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
|
|
return x;
|
|
}
|
|
#elif defined(__x86_64__)
|
|
static inline unsigned long long rdtsc_oai(void) __attribute__((always_inline));
|
|
static inline unsigned long long rdtsc_oai(void) {
|
|
unsigned long long a, d;
|
|
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
|
|
return (d<<32) | a;
|
|
}
|
|
#elif defined(__aarch64__)
|
|
static inline uint64_t rdtsc_oai(void) __attribute__((always_inline));
|
|
static inline uint64_t rdtsc_oai(void)
|
|
{
|
|
uint64_t r = 0;
|
|
asm volatile("mrs %0, cntvct_el0" : "=r"(r));
|
|
return r;
|
|
}
|
|
|
|
#elif defined(__arm__)
|
|
static inline uint32_t rdtsc_oai(void) __attribute__((always_inline));
|
|
static inline uint32_t rdtsc_oai(void) {
|
|
uint32_t r = 0;
|
|
asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(r) );
|
|
return r;
|
|
}
|
|
#endif
|
|
|
|
#define CPUMEAS_DISABLE 0
|
|
#define CPUMEAS_ENABLE 1
|
|
#define CPUMEAS_GETSTATE 2
|
|
static inline int cpumeas(int action) {
|
|
switch (action) {
|
|
case CPUMEAS_ENABLE:
|
|
cpu_meas_enabled = 1;
|
|
break;
|
|
|
|
case CPUMEAS_DISABLE:
|
|
cpu_meas_enabled = 0;
|
|
break;
|
|
|
|
case CPUMEAS_GETSTATE:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return cpu_meas_enabled;
|
|
}
|
|
|
|
static inline void start_meas(time_stats_t *ts) {
|
|
if (cpu_meas_enabled) {
|
|
if (ts->meas_flag==0) {
|
|
ts->trials++;
|
|
ts->in = rdtsc_oai();
|
|
ts->meas_flag=1;
|
|
} else {
|
|
ts->in = rdtsc_oai();
|
|
}
|
|
if ((ts->trials&16383)<10) ts->max=0;
|
|
}
|
|
}
|
|
|
|
static inline void stop_meas(time_stats_t *ts) {
|
|
if (cpu_meas_enabled) {
|
|
long long out = rdtsc_oai();
|
|
if (ts->in) {
|
|
ts->diff += (out - ts->in);
|
|
/// process duration is the difference between two clock points
|
|
ts->p_time = (out - ts->in);
|
|
ts->diff_square += ((double)out - ts->in) * ((double)out - ts->in);
|
|
|
|
if ((out - ts->in) > ts->max)
|
|
ts->max = out - ts->in;
|
|
|
|
ts->meas_flag = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void reset_meas(time_stats_t *ts) {
|
|
ts->in=0;
|
|
ts->diff=0;
|
|
ts->p_time=0;
|
|
ts->diff_square=0;
|
|
ts->max=0;
|
|
ts->trials=0;
|
|
ts->meas_flag=0;
|
|
}
|
|
|
|
static inline void copy_meas(time_stats_t *dst_ts,time_stats_t *src_ts) {
|
|
if (cpu_meas_enabled) {
|
|
dst_ts->trials=src_ts->trials;
|
|
dst_ts->diff=src_ts->diff;
|
|
dst_ts->max=src_ts->max;
|
|
}
|
|
}
|
|
|
|
static inline void merge_meas(time_stats_t *dst_ts, const time_stats_t *src_ts)
|
|
{
|
|
if (!cpu_meas_enabled)
|
|
return;
|
|
dst_ts->trials += src_ts->trials;
|
|
dst_ts->diff += src_ts->diff;
|
|
dst_ts->diff_square += src_ts->diff_square;
|
|
if (src_ts->max > dst_ts->max)
|
|
dst_ts->max = src_ts->max;
|
|
}
|
|
|
|
#define CPUMEASUR_SECTION "cpumeasur"
|
|
|
|
// clang-format off
|
|
#define CPUMEASUR_PARAMS_DESC { \
|
|
{"max_cpumeasur", "Max number of cpu measur entries", 0, .uptr=&max_cpumeasur, .defintval=100, TYPE_UINT, 0}, \
|
|
}
|
|
// clang-format on
|
|
|
|
void init_meas(void);
|
|
time_stats_t *register_meas(char *name);
|
|
#define START_MEAS(X) send_meas(X, TIMESTAT_MSGID_START)
|
|
#define STOP_MEAS(X) send_meas(X, TIMESTAT_MSGID_STOP)
|
|
void send_meas(time_stats_t *ts, int msgid);
|
|
void end_meas(void);
|
|
|
|
#define timeIt(a) \
|
|
{ \
|
|
uint64_t deb = rdtsc_oai(); \
|
|
a; \
|
|
LOG_W(UTIL, #a ": %llu\n", (rdtsc_oai() - deb) / 3000); \
|
|
}
|
|
#endif
|