From: Luis C. R. G. <lcl...@uu...> - 2008-05-25 16:14:32
|
[ Please, keep me on Cc: if you have any comments ] The busy_work_ms() function was not honoring the requested busy interval. In my test box busy_work_ms(1) would create a 42us busy interval. To solve this issue I added a function calibrate_busy_work(), called by rt_init(). This funtion runs CALIBRATION_LOOPS and uses the average value as the calibration magic constant. Two notes: * I avoided touching busy_work_us() so that we have a better resolution for busy_work_ms(). The only user for busy_work_us() as of now is JVMSIM. * After adding this fix, I understand the tests are working as supposed to, with the right amount of busy work. And the fail rate increased. Sign-off-by: Luis Claudio R. Goncalves <lcl...@uu...> diff --git a/testcases/realtime/lib/librttest.c b/testcases/realtime/lib/librttest.c index 6981376..49f101f 100644 --- a/testcases/realtime/lib/librttest.c +++ b/testcases/realtime/lib/librttest.c @@ -60,6 +60,8 @@ #include <fcntl.h> #include <math.h> +#define CALIBRATION_LOOPS 20 + static LIST_HEAD(_threads); static atomic_t _thread_count = {-1}; @@ -68,6 +70,8 @@ pthread_mutex_t _buffer_mutex; int _print_buffer_offset = 0; int _dbg_lvl = 0; double pass_criteria; +/* multiplier to calibrate busy_work loop */ +static int busy_work_mult = 1; static int _use_pi = 1; @@ -82,6 +86,23 @@ void rt_help(void) printf(" -c Set pass criteria\n"); } + +static void calibrate_busy_work( void) +{ + int i; + int delta = 0; + nsec_t start, end; + + for(i = 0; i < CALIBRATION_LOOPS; i++) { + start = rt_gettime(); + busy_work_ms(1); + end = rt_gettime(); + delta = delta + (end - start); + } + busy_work_mult = (i * NS_PER_MS) / delta; +} + + int rt_init(const char *options, int (*parse_arg)(int option, char *value), int argc, char *argv[]) { int use_buffer = 1; @@ -140,6 +164,8 @@ int rt_init(const char *options, int (*parse_arg)(int option, char *value), int if (use_buffer) buffer_init(); + calibrate_busy_work(); + /* * atexit() order matters here - buffer_print() will be called before * buffer_fini(). @@ -428,7 +446,7 @@ nsec_t rt_gettime(void) { void *busy_work_ms(int ms) { - busy_work_us(ms*US_PER_MS); + busy_work_us(ms * busy_work_mult); return NULL; } @@ -438,22 +462,17 @@ void *busy_work_us(int us) int scale; double pi_scaled; double pi_value; - nsec_t start, now; - int delta; /* time in us */ volatile double a=16, b=1.0, c=5.0, d=4, e=1.0, f=239.0; - scale = us * ITERS_PER_US; + /* Calc may take more than 1us on some boxes. Lower this time and + guarantee that busy_work_ms is accurate. Tests call busy_work_ms */ + scale = us; pi_scaled = 0; - start = rt_gettime(); for (i = 0; i < scale; i++) { double pi = a*atan(b/c) - d*atan(e/f); pi_scaled += pi; } pi_value = pi_scaled / scale; - now = rt_gettime(); - delta = (now - start)/NS_PER_US; - /* uncomment to tune to your machine */ - /* printf("busy_work_us requested: %dus actual: %dus\n", us, delta); */ return NULL; } -- [ Luis Claudio R. Goncalves Red Hat - Realtime Team ] [ Fingerprint: 4FDD B8C4 3C59 34BD 8BE9 2696 7203 D980 A448 C8F8 ] |