Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 Oct 2001 20:14:00 -0700
From:      Luigi Rizzo <rizzo@aciri.org>
To:        arch@freebsd.org
Subject:   where to put support for timestamping kernel events ?
Message-ID:  <20011014201400.A49458@iguana.aciri.org>
In-Reply-To: <20011014134502.B47525@iguana.aciri.org>
References:  <20011014134502.B47525@iguana.aciri.org>

next in thread | previous in thread | raw e-mail | index | archive | help
[Apparently this kind of question is better asked on -arch,
so sorry for the repost, here it goes again... and in the meantime
i have had some time to elaborate on names and locations.]

for some work i am doing these days, i needed to do some relatively
precise (sub-microsecond resolution, and possibly not very intrusive)
measurements of some kernel events.

What i come up with seems to be relatively simple yet flexible:
I record pairs of 32-bit values <timestamp,tag> into an array which
is then exported via sysctl.  Timestamps are recorded using the
TSTMP macro below, which in turn calls the (machine-specific)
_TSTMP() function which does the job.  On a 750MHz machine the
whole thing takes about 30-40 cycles, which gives pretty good
resolution (I guess it can be further optimized by writing the
whole thing in assembler).

The whole thing is extremely simple -- the full code is below, basically
(modulo disabling it for architectures where the TSC is not present,
or adapting it to other architectures such as the Alpha).

My question(s) are:
* do you think this is a useful feature to be incorporated in the system ?

* if so, where would you put the two pieces of code below ?
   I am thinking of sys/param.h for the header files,
   and i386/isa/clock.c for the actual function definition
   (and other machine-specific implementation as they get
   implemented. Initially, i would put the option in options.i386)

* any suggestion about variables and macro/function names etc ?

Feedback is greatly appreciated -- i would really like to see
this stuff in the system.

Diffs below (not mp-ready, the static variable in _TSTMP
should be read and incremented in a critical section, but
you get the idea).

	cheers
	luigi

-----------------------------------------------------------------
RCS file: /home/xorpc/u2/freebsd/src/sys/conf/options.i386,v
retrieving revision 1.132.2.7
diff -u -r1.132.2.7 options.i386
--- conf/options.i386   2001/08/15 01:23:48     1.132.2.7
+++ conf/options.i386   2001/10/15 02:44:30
@@ -205,5 +205,6 @@
 SMBFS
 
 # -------------------------------
+KERN_TIMESTAMP         opt_global.h
 # EOF
 # -------------------------------
===================================================================
RCS file: /home/xorpc/u2/freebsd/src/sys/i386/isa/clock.c,v
retrieving revision 1.149.2.3
diff -u -r1.149.2.3 clock.c
--- i386/isa/clock.c    2001/04/18 23:17:41     1.149.2.3
+++ i386/isa/clock.c    2001/10/15 02:49:37
@@ -199,6 +199,25 @@
 SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, 
        &i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", "");
 
+#ifdef KERN_TIMESTAMP
+#define L_TSC_SIZE 16384
+static u_long tsc[L_TSC_SIZE] ;
+SYSCTL_OPAQUE(_debug, OID_AUTO, timestamp, CTLFLAG_RD, tsc,
+       sizeof(tsc), "LU", "Kernel timestamps");
+void
+_TSTMP(u_int32_t x)
+{
+       static int i ;
+
+       tsc[i] = (u_int32_t)rdtsc();
+       tsc[i+1] = x ;
+       i = i + 2 ;
+       if (i >= L_TSC_SIZE)
+               i = 0 ;
+       tsc[i] = 0 ; /* mark last entry */
+}
+#endif KERN_TIMESTAMP
+
 static void
 clkintr(struct clockframe frame)
 {
===================================================================
RCS file: /home/xorpc/u2/freebsd/src/sys/sys/param.h,v
retrieving revision 1.61.2.18
diff -u -r1.61.2.18 param.h
--- sys/param.h 2001/09/17 06:54:26     1.61.2.18
+++ sys/param.h 2001/10/15 02:41:24
@@ -263,4 +263,17 @@
 void   panic __P((const char *, ...)) __dead2 __printflike(1, 2);
 #endif
 
+#ifdef _KERNEL /* timestamping support */
+#ifdef KERN_TIMESTAMP
+#define TSTMP(class, unit, event, par)           \
+        _TSTMP( (((class) &     15) << 28 ) |    \
+                (((unit)  &     15) << 24 ) |    \
+                (((event) &    255) << 16 ) |    \
+                (((par)   & 0xffff)       )    )
+extern void _TSTMP(u_long);
+#else /* !KERN_TIMESTAMP */
+#define TSTMP(class, unit, event, par)  _TSTMP(0)
+#define _TSTMP(x)                      do {} while (0)
+#endif /* !KERN_TIMESTAMP */
+#endif
 #endif /* _SYS_PARAM_H_ */


----------------------------------+-----------------------------------------
 Luigi RIZZO, luigi@iet.unipi.it  . ACIRI/ICSI (on leave from Univ. di Pisa)
 http://www.iet.unipi.it/~luigi/  . 1947 Center St, Berkeley CA 94704
 Phone: (510) 666 2927
----------------------------------+-----------------------------------------

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011014201400.A49458>