summaryrefslogblamecommitdiffstats
path: root/src/include/ipxe/profile.h
blob: 2c69e120840243b099ca766b97f0bf3fb201a992 (plain) (tree)
1
2
3
4
5
6
7
8
9

                       






            
                                       
 


                         
                 




                   
      



                                                     



                              


                              












                                                                    
          

                                                                       
           
                                

  









                                                          

                                      



                                                                               

   



















































                                                                
                  
  
                                






                                                                       
















                                                                               





                                
   

                                                    
 

                                                                
                                                                   


   
                 
  
                                
   
                                                    
                                            

                                                                               

                                                                  

 
   
                                                    



                                                    
                                               
 
                                                                          
                        
                                                                 

 













                                                                    
                            
#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 */