timing measurement code out of kernel and into library
(so other components can use it too)
This commit is contained in:
		
							parent
							
								
									54b3f50b05
								
							
						
					
					
						commit
						128a0508c0
					
				@ -61,5 +61,21 @@ _PROTOTYPE( void ser_putc, (char c));
 | 
			
		||||
 | 
			
		||||
#define ASSERT(c) if(!(c)) { panic(__FILE__, "assert " #c " failed at line", __LINE__); }
 | 
			
		||||
 | 
			
		||||
/* timing library */
 | 
			
		||||
#define TIMING_CATEGORIES       20
 | 
			
		||||
 | 
			
		||||
#define TIMING_POINTS           20      /* timing resolution */
 | 
			
		||||
#define TIMING_CATEGORIES       20
 | 
			
		||||
#define TIMING_NAME             10
 | 
			
		||||
 | 
			
		||||
struct util_timingdata {
 | 
			
		||||
        char names[TIMING_NAME];
 | 
			
		||||
        unsigned long lock_timings[TIMING_POINTS]; 
 | 
			
		||||
        unsigned long lock_timings_range[2];
 | 
			
		||||
        unsigned long binsize, resets, misses, measurements;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct util_timingdata util_timingdata_t[TIMING_CATEGORIES];
 | 
			
		||||
 | 
			
		||||
#endif /* _MINIX_SYSUTIL_H */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,96 +11,6 @@
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Data structures to store lock() timing data. */
 | 
			
		||||
static unsigned long starttimes[TIMING_CATEGORIES][2];
 | 
			
		||||
 | 
			
		||||
#define HIGHCOUNT	0
 | 
			
		||||
#define LOWCOUNT	1
 | 
			
		||||
 | 
			
		||||
void timer_start(int cat, char *name)
 | 
			
		||||
{
 | 
			
		||||
	static int init = 0;
 | 
			
		||||
	unsigned long h, l;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if (cat < 0 || cat >= TIMING_CATEGORIES) return;
 | 
			
		||||
 | 
			
		||||
	for(i = 0; i < sizeof(timingdata[0].names) && *name; i++)
 | 
			
		||||
		timingdata[cat].names[i] = *name++;
 | 
			
		||||
	timingdata[cat].names[sizeof(timingdata[0].names)-1] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (starttimes[cat][HIGHCOUNT]) {  return; }
 | 
			
		||||
 | 
			
		||||
	if (!init) {
 | 
			
		||||
		int t, f;
 | 
			
		||||
		init = 1;
 | 
			
		||||
		for(t = 0; t < TIMING_CATEGORIES; t++) {
 | 
			
		||||
			timingdata[t].lock_timings_range[0] = 0;
 | 
			
		||||
			timingdata[t].resets = timingdata[t].misses = 
 | 
			
		||||
				timingdata[t].measurements = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void timer_end(int cat)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long h, l, d = 0, binsize;
 | 
			
		||||
	int bin;
 | 
			
		||||
 | 
			
		||||
	read_tsc(&h, &l);
 | 
			
		||||
	if (cat < 0 || cat >= TIMING_CATEGORIES) return;
 | 
			
		||||
	if (!starttimes[cat][HIGHCOUNT]) {
 | 
			
		||||
		timingdata[cat].misses++;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (starttimes[cat][HIGHCOUNT] == h) {
 | 
			
		||||
		d = (l - starttimes[cat][1]);
 | 
			
		||||
	} else if (starttimes[cat][HIGHCOUNT] == h-1 &&
 | 
			
		||||
		starttimes[cat][LOWCOUNT] > l) {
 | 
			
		||||
		d = ((ULONG_MAX - starttimes[cat][LOWCOUNT]) + l);
 | 
			
		||||
	} else {
 | 
			
		||||
		timingdata[cat].misses++;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	starttimes[cat][HIGHCOUNT] = 0;
 | 
			
		||||
	if (!timingdata[cat].lock_timings_range[0] ||
 | 
			
		||||
		d < timingdata[cat].lock_timings_range[0] ||
 | 
			
		||||
		d > timingdata[cat].lock_timings_range[1]) {
 | 
			
		||||
		int t;
 | 
			
		||||
		if (!timingdata[cat].lock_timings_range[0] ||
 | 
			
		||||
			d < timingdata[cat].lock_timings_range[0])
 | 
			
		||||
			timingdata[cat].lock_timings_range[0] = d;
 | 
			
		||||
		if (!timingdata[cat].lock_timings_range[1] ||
 | 
			
		||||
			d > timingdata[cat].lock_timings_range[1])
 | 
			
		||||
			timingdata[cat].lock_timings_range[1] = d;
 | 
			
		||||
		for(t = 0; t < TIMING_POINTS; t++)
 | 
			
		||||
			timingdata[cat].lock_timings[t] = 0;
 | 
			
		||||
		timingdata[cat].binsize =
 | 
			
		||||
			(timingdata[cat].lock_timings_range[1] -
 | 
			
		||||
			timingdata[cat].lock_timings_range[0])/(TIMING_POINTS+1);
 | 
			
		||||
		if (timingdata[cat].binsize < 1)
 | 
			
		||||
		  timingdata[cat].binsize = 1;
 | 
			
		||||
		timingdata[cat].resets++;
 | 
			
		||||
	}
 | 
			
		||||
	bin = (d-timingdata[cat].lock_timings_range[0]) /
 | 
			
		||||
		timingdata[cat].binsize;
 | 
			
		||||
	if (bin < 0 || bin >= TIMING_POINTS) {
 | 
			
		||||
		int t;
 | 
			
		||||
		/* this indicates a bug, but isn't really serious */
 | 
			
		||||
		for(t = 0; t < TIMING_POINTS; t++)
 | 
			
		||||
			timingdata[cat].lock_timings[t] = 0;
 | 
			
		||||
		timingdata[cat].misses++;
 | 
			
		||||
	} else {
 | 
			
		||||
		timingdata[cat].lock_timings[bin]++;
 | 
			
		||||
		timingdata[cat].measurements++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if DEBUG_SCHED_CHECK		/* only include code if enabled */
 | 
			
		||||
 | 
			
		||||
#define MAX_LOOP (NR_PROCS + NR_TASKS)
 | 
			
		||||
 | 
			
		||||
@ -25,12 +25,4 @@
 | 
			
		||||
#define DEBUG_SCHED_CHECK		1
 | 
			
		||||
#define DEBUG_TIME_LOCKS		1
 | 
			
		||||
 | 
			
		||||
/* It's interesting to measure the time spent withing locked regions, because
 | 
			
		||||
 * this is the time that the system is deaf to interrupts.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define TIMING_POINTS		20	/* timing resolution */
 | 
			
		||||
#define TIMING_CATEGORIES	20
 | 
			
		||||
#define TIMING_NAME		10
 | 
			
		||||
 | 
			
		||||
#endif /* DEBUG_H */
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
#ifndef GLO_H
 | 
			
		||||
#define GLO_H
 | 
			
		||||
 | 
			
		||||
#include <minix/sysutil.h>
 | 
			
		||||
 | 
			
		||||
/* Global variables used in the kernel. This file contains the declarations;
 | 
			
		||||
 * storage space for the variables is allocated in table.c, because EXTERN is
 | 
			
		||||
 * defined as extern unless the _TABLE definition is seen. We rely on the 
 | 
			
		||||
@ -96,8 +98,8 @@ EXTERN int must_notify_vm;
 | 
			
		||||
/* Verbose flags (debugging). */
 | 
			
		||||
EXTERN int verbose_vm;
 | 
			
		||||
 | 
			
		||||
/* Timing measurements. */
 | 
			
		||||
EXTERN struct lock_timingdata timingdata[TIMING_CATEGORIES];
 | 
			
		||||
/* Timing */
 | 
			
		||||
EXTERN util_timingdata_t timingdata;
 | 
			
		||||
 | 
			
		||||
/* Variables that are initialized elsewhere are just extern here. */
 | 
			
		||||
extern struct boot_image image[]; 	/* system image processes */
 | 
			
		||||
 | 
			
		||||
@ -50,14 +50,4 @@ typedef struct irq_hook {
 | 
			
		||||
 | 
			
		||||
typedef int (*irq_handler_t)(struct irq_hook *);
 | 
			
		||||
 | 
			
		||||
/* Timing measurements. */
 | 
			
		||||
struct lock_timingdata {
 | 
			
		||||
        char names[TIMING_NAME];
 | 
			
		||||
        unsigned long lock_timings[TIMING_POINTS];
 | 
			
		||||
        unsigned long lock_timings_range[2];
 | 
			
		||||
        unsigned long binsize, resets, misses, measurements;
 | 
			
		||||
};
 | 
			
		||||
EXTERN struct lock_timingdata timingdata[TIMING_CATEGORIES];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* TYPE_H */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user