blob: 32d42f58eb436560fba0b93eca0b2a7bb3149f1b [file] [log] [blame]
#pragma once
#include <ros/common.h>
#include <ros/time.h>
#include <arch/time.h>
#include <ros/procinfo.h>
/* Conversion factors */
#define NSEC_PER_SEC 1000000000L
#define NSEC_PER_MSEC 1000000L
#define NSEC_PER_USEC 1000L
void time_init(void);
void udelay(uint64_t usec); /* done in arch-specific files */
uint64_t read_persistent_clock(void); /* arch-specific */
uint64_t tsc2nsec(uint64_t tsc_time);
static inline uint64_t tsc2usec(uint64_t tsc_time)
{
return tsc2nsec(tsc_time) / NSEC_PER_USEC;
}
static inline uint64_t tsc2msec(uint64_t tsc_time)
{
return tsc2nsec(tsc_time) / NSEC_PER_MSEC;
}
static inline uint64_t tsc2sec(uint64_t tsc_time)
{
return tsc2nsec(tsc_time) / NSEC_PER_SEC;
}
uint64_t nsec2tsc(uint64_t nsec);
static inline uint64_t usec2tsc(uint64_t usec)
{
return nsec2tsc(usec * NSEC_PER_USEC);
}
static inline uint64_t msec2tsc(uint64_t msec)
{
return nsec2tsc(msec * NSEC_PER_MSEC);
}
static inline uint64_t sec2tsc(uint64_t sec)
{
return nsec2tsc(sec * NSEC_PER_SEC);
}
uint64_t epoch_nsec(void);
static inline struct timespec nsec2timespec(uint64_t ns)
{
return (struct timespec) {
.tv_sec = ns / NSEC_PER_SEC,
.tv_nsec = ns % NSEC_PER_SEC
};
}
static inline struct timeval nsec2timeval(uint64_t ns)
{
return (struct timeval) {
.tv_sec = ns / NSEC_PER_SEC,
.tv_usec = (ns % NSEC_PER_SEC) / NSEC_PER_USEC
};
}
static inline struct timespec tsc2timespec(uint64_t tsc_time)
{
return nsec2timespec(tsc2nsec(tsc_time));
}
/* Just takes a time measurement. Meant to be paired with stop_timing. Use
* this if you don't want to muck with overheads or subtraction. */
static inline __attribute__((always_inline))
uint64_t start_timing(void)
{
return read_tsc_serialized();
}
/* Takes a time measurement and subtracts the start time and timing overhead,
* to return the detected elapsed time. Use this if you don't want to muck
* with overheads or subtraction. */
static inline __attribute__((always_inline))
uint64_t stop_timing(uint64_t start_time)
{
uint64_t diff = read_tsc_serialized();
diff -= start_time;
diff -= __proc_global_info.tsc_overhead;
if ((int64_t) diff < 0) {
return 1;
}
return diff;
}
static inline __attribute__((always_inline))
uint64_t nsec(void)
{
return tsc2nsec(read_tsc());
}
/* Ancient measurement crap below. TODO: use or lose it */
#if 0
#include <pool.h>
#include <string.h>
#define TIMER_TAG_SIZE 20
#define MAX_TIMERS 20
/* timer_t
* This struct is used to keep track of counter values as they are spread
* throughput code and timing measurements are made calling TAGGED_TIMING_BEGIN
* and TAGGED_TIMING_END
*/
typedef struct Timer{
uint64_t curr_run;
uint64_t aggr_run;
char label[TIMER_TAG_SIZE];
} timer_t;
#define TAGGED_TIMING_BEGIN(tag) \
static timer_t* _timer_##tag = NULL; \
if (_timer_##tag == NULL) { \
_timer_##tag = POOL_GET(&timer_pool); \
strcpy((_timer_##tag->label), #tag); \
_timer_##tag->aggr_run = 0; \
} \
_timer_##tag->curr_run = start_timing();
#define TAGGED_TIMING_END(tag) \
({ \
_timer_##tag->curr_run = stop_timing(_timer_##tag->curr_run); \
_timer_##tag->aggr_run += _timer_##tag->curr_run; \
})
#endif