david/ipxe
david
/
ipxe
Archived
1
0
Fork 0
This repository has been archived on 2020-12-06. You can view files and clone it, but cannot push or open issues or pull requests.
ipxe/src/include/ipxe/profile.h

206 lines
4.6 KiB
C

#ifndef _IPXE_PROFILE_H
#define _IPXE_PROFILE_H
/** @file
*
* Profiling
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <bits/profile.h>
#include <ipxe/tables.h>
#ifndef PROFILING
#ifdef NDEBUG
#define PROFILING 0
#else
#define PROFILING 1
#endif
#endif
/**
* A data structure for storing profiling information
*/
struct profiler {
/** Name */
const char *name;
/** Start timestamp */
unsigned long started;
/** Stop timestamp */
unsigned long stopped;
/** Number of samples */
unsigned int count;
/** Mean sample value (scaled) */
unsigned long mean;
/** Mean sample value MSB
*
* This is the highest bit set in the raw (unscaled) value
* (i.e. one less than would be returned by flsl(raw_mean)).
*/
unsigned int mean_msb;
/** Accumulated variance (scaled) */
unsigned long long accvar;
/** Accumulated variance MSB
*
* This is the highest bit set in the raw (unscaled) value
* (i.e. one less than would be returned by flsll(raw_accvar)).
*/
unsigned int accvar_msb;
};
/** Profiler table */
#define PROFILERS __table ( struct profiler, "profilers" )
/** Declare a profiler */
#if PROFILING
#define __profiler __table_entry ( PROFILERS, 01 )
#else
#define __profiler
#endif
extern unsigned long profile_excluded;
extern void profile_update ( struct profiler *profiler, unsigned long sample );
extern unsigned long profile_mean ( struct profiler *profiler );
extern unsigned long profile_variance ( struct profiler *profiler );
extern unsigned long profile_stddev ( struct profiler *profiler );
/**
* Get start time
*
* @v profiler Profiler
* @ret started Start time
*/
static inline __attribute__ (( always_inline )) unsigned long
profile_started ( struct profiler *profiler ) {
/* If profiling is active then return start time */
if ( PROFILING ) {
return ( profiler->started + profile_excluded );
} else {
return 0;
}
}
/**
* Get stop time
*
* @v profiler Profiler
* @ret stopped Stop time
*/
static inline __attribute__ (( always_inline )) unsigned long
profile_stopped ( struct profiler *profiler ) {
/* If profiling is active then return start time */
if ( PROFILING ) {
return ( profiler->stopped + profile_excluded );
} else {
return 0;
}
}
/**
* Get elapsed time
*
* @v profiler Profiler
* @ret elapsed Elapsed time
*/
static inline __attribute__ (( always_inline )) unsigned long
profile_elapsed ( struct profiler *profiler ) {
/* If profiling is active then return elapsed time */
if ( PROFILING ) {
return ( profile_stopped ( profiler ) -
profile_started ( profiler ) );
} else {
return 0;
}
}
/**
* Start profiling
*
* @v profiler Profiler
* @v started Start timestamp
*/
static inline __attribute__ (( always_inline )) void
profile_start_at ( struct profiler *profiler, unsigned long started ) {
/* If profiling is active then record start timestamp */
if ( PROFILING )
profiler->started = ( started - profile_excluded );
}
/**
* Stop profiling
*
* @v profiler Profiler
* @v stopped Stop timestamp
*/
static inline __attribute__ (( always_inline )) void
profile_stop_at ( struct profiler *profiler, unsigned long stopped ) {
/* If profiling is active then record end timestamp and update stats */
if ( PROFILING ) {
profiler->stopped = ( stopped - profile_excluded );
profile_update ( profiler, profile_elapsed ( profiler ) );
}
}
/**
* Start profiling
*
* @v profiler Profiler
*/
static inline __attribute__ (( always_inline )) void
profile_start ( struct profiler *profiler ) {
/* If profiling is active then record start timestamp */
if ( PROFILING )
profile_start_at ( profiler, profile_timestamp() );
}
/**
* Stop profiling
*
* @v profiler Profiler
*/
static inline __attribute__ (( always_inline )) void
profile_stop ( struct profiler *profiler ) {
/* If profiling is active then record end timestamp and update stats */
if ( PROFILING )
profile_stop_at ( profiler, profile_timestamp() );
}
/**
* Exclude time from other ongoing profiling results
*
* @v profiler Profiler
*/
static inline __attribute__ (( always_inline )) void
profile_exclude ( struct profiler *profiler ) {
/* If profiling is active then update accumulated excluded time */
if ( PROFILING )
profile_excluded += profile_elapsed ( profiler );
}
/**
* Record profiling sample in custom units
*
* @v profiler Profiler
* @v sample Profiling sample
*/
static inline __attribute__ (( always_inline )) void
profile_custom ( struct profiler *profiler, unsigned long sample ) {
/* If profiling is active then update stats */
if ( PROFILING )
profile_update ( profiler, sample );
}
#endif /* _IPXE_PROFILE_H */