[profile] Standardise return type of profile_timestamp()

All consumers of profile_timestamp() currently treat the value as an
unsigned long.  Only the elapsed number of ticks is ever relevant: the
absolute value of the timestamp is not used.  Profiling is used to
measure short durations that are generally fewer than a million CPU
cycles, for which an unsigned long is easily large enough.

Standardise the return type of profile_timestamp() as unsigned long
across all CPU architectures.  This allows 32-bit architectures such
as i386 and riscv32 to omit all logic associated with retrieving the
upper 32 bits of the 64-bit hardware counter, which simplifies the
code and allows riscv32 and riscv64 to share the same implementation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2024-09-24 14:49:32 +01:00
parent 3def13265d
commit 5f7c6bd95b
8 changed files with 11 additions and 45 deletions

View File

@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* *
* @ret timestamp Timestamp * @ret timestamp Timestamp
*/ */
static inline __attribute__ (( always_inline )) uint64_t static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) { profile_timestamp ( void ) {
uint32_t cycles; uint32_t cycles;

View File

@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* *
* @ret timestamp Timestamp * @ret timestamp Timestamp
*/ */
static inline __attribute__ (( always_inline )) uint64_t static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) { profile_timestamp ( void ) {
uint64_t cycles; uint64_t cycles;

View File

@ -16,12 +16,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* *
* @ret timestamp Timestamp * @ret timestamp Timestamp
*/ */
static inline __attribute__ (( always_inline )) uint64_t static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) { profile_timestamp ( void ) {
uint64_t tsc; uint32_t tsc;
/* Read timestamp counter */ /* Read timestamp counter */
__asm__ __volatile__ ( "rdtsc" : "=A" ( tsc ) ); __asm__ __volatile__ ( "rdtsc" : "=a" ( tsc ) : : "edx" );
return tsc; return tsc;
} }

View File

@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* *
* @ret timestamp Timestamp * @ret timestamp Timestamp
*/ */
static inline __attribute__ (( always_inline )) uint64_t static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) { profile_timestamp ( void ) {
uint64_t cycles; uint64_t cycles;

View File

@ -16,9 +16,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* *
* @ret timestamp Timestamp * @ret timestamp Timestamp
*/ */
static inline __attribute__ (( always_inline )) uint64_t static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) { profile_timestamp ( void ) {
uint64_t cycles; unsigned long cycles;
/* Read timestamp counter */ /* Read timestamp counter */
__asm__ __volatile__ ( "rdcycle %0" : "=r" ( cycles ) ); __asm__ __volatile__ ( "rdcycle %0" : "=r" ( cycles ) );

View File

@ -1,36 +0,0 @@
#ifndef _BITS_PROFILE_H
#define _BITS_PROFILE_H
/** @file
*
* Profiling
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
/**
* Get profiling timestamp
*
* @ret timestamp Timestamp
*/
static inline __attribute__ (( always_inline )) uint64_t
profile_timestamp ( void ) {
uint32_t cycles_lo;
uint32_t cycles_hi;
uint32_t tmp;
/* Read timestamp counter */
__asm__ __volatile__ ( "\n1:\n\t"
"rdcycleh %1\n\t"
"rdcycle %0\n\t"
"rdcycleh %2\n\t"
"bne %1, %2, 1b\n\t"
: "=r" ( cycles_lo ), "=r" ( cycles_hi ),
"=r" ( tmp ) );
return ( ( ( ( uint64_t ) cycles_hi ) << 32 ) | cycles_lo );
}
#endif /* _BITS_PROFILE_H */

View File

@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* *
* @ret timestamp Timestamp * @ret timestamp Timestamp
*/ */
static inline __attribute__ (( always_inline )) uint64_t static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) { profile_timestamp ( void ) {
uint32_t eax; uint32_t eax;
uint32_t edx; uint32_t edx;

View File

@ -60,6 +60,8 @@ struct profiler {
#define __profiler #define __profiler
#endif #endif
unsigned long profile_timestamp ( void );
extern unsigned long profile_excluded; extern unsigned long profile_excluded;
extern void profile_update ( struct profiler *profiler, unsigned long sample ); extern void profile_update ( struct profiler *profiler, unsigned long sample );