diff -ur linux-2.6.14.2-rt12/drivers/serial/8250.c linux-2.6.14.2-rt12-latency/drivers/serial/8250.c
--- linux-2.6.14.2-rt12/drivers/serial/8250.c 2005-11-11 00:33:12.000000000 -0500
+++ linux-2.6.14.2-rt12-latency/drivers/serial/8250.c 2005-11-15 18:04:59.000000000 -0500
@@ -251,8 +251,91 @@
},
};
-static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
+#ifdef CONFIG_SERIAL_LATENCY_TIMING
+
+// loadavg stuff borrowed from kernel/timer.c and fs/proc/proc_misc.c
+#include <linux/sched.h>
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+extern unsigned long avenrun[3];
+
+extern unsigned int cpu_khz;
+static u64 startTimer_G;
+
+#ifdef CONFIG_RCU_STATS
+struct rcu_ctrlblk {
+ raw_spinlock_t fliplock;
+ long completed;
+};
+extern struct rcu_ctrlblk rcu_ctrlblk;
+#endif
+
+static void
+latency_serial_out (struct uart_8250_port *up, int offset, int value)
{
+ size_t i, len;
+ char timerBuf[100];
+ int a;
+ u64 endTimer;
+ struct timespec uptime;
+ struct timespec idle;
+ cputime_t idletime;
+
+ rdtscll (endTimer);
+#ifdef CONFIG_PREEMPT_RT
+ user_trace_stop ();
+#endif
+ a = avenrun[0] + (FIXED_1/200);
+ do_posix_clock_monotonic_gettime (&uptime);
+ idletime = cputime_add (init_task.utime, init_task.stime);
+ cputime_to_timespec (idletime, &idle);
+#ifdef CONFIG_RCU_STATS
+ sprintf (timerBuf, "**%llu %u %d.%02d %lu.%02lu %lu.%02lu %ld**\n",
+ endTimer - startTimer_G, cpu_khz,
+ LOAD_INT(a), LOAD_FRAC(a),
+ (unsigned long) uptime.tv_sec,
+ (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
+ (unsigned long) idle.tv_sec,
+ (idle.tv_nsec / (NSEC_PER_SEC / 100)),
+ rcu_ctrlblk.completed);
+#else
+ sprintf (timerBuf, "**%llu %u %d.%02d %lu.%02lu %lu.%02lu**\n",
+ endTimer - startTimer_G, cpu_khz,
+ LOAD_INT(a), LOAD_FRAC(a),
+ (unsigned long) uptime.tv_sec,
+ (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
+ (unsigned long) idle.tv_sec,
+ (idle.tv_nsec / (NSEC_PER_SEC / 100)));
+#endif
+ len = strlen (timerBuf);
+ for (i=0; i<len; ++i) {
+ switch (up->port.iotype) {
+ case UPIO_MEM:
+ writeb (timerBuf[i], up->port.membase + offset);
+ break;
+ case UPIO_MEM32:
+ writel (timerBuf[i], up->port.membase + offset);
+ break;
+ default:
+ outb (timerBuf[i], up->port.iobase + offset);
+ break;
+ }
+ /*
+ * give the port enough time to cope. Note
+ * that the timer has been stopped already,
+ * so this does not increase the latency:
+ */
+ udelay(100);
+ }
+}
+#endif
+
+static unsigned int
+serial_in(struct uart_8250_port *up, int offset)
+{
+ u8 ch8;
+ u32 ch32;
+
offset <<= up->port.regshift;
switch (up->port.iotype) {
@@ -261,19 +344,53 @@
return inb(up->port.iobase + 1);
case UPIO_MEM:
- return readb(up->port.membase + offset);
+ ch8 = readb (up->port.membase + offset);
+#ifdef CONFIG_SERIAL_LATENCY_TIMING
+ if ((offset == UART_RX) && (ch8 == '\n')) {
+#ifdef CONFIG_PREEMPT_RT
+ user_trace_start ();
+#endif
+ rdtscll (startTimer_G);
+ }
+#endif
+ return ch8;
case UPIO_MEM32:
- return readl(up->port.membase + offset);
+ ch32 = readl (up->port.membase + offset);
+#ifdef CONFIG_SERIAL_LATENCY_TIMING
+ if ((offset == UART_RX) && (ch32 == '\n')) {
+#ifdef CONFIG_PREEMPT_RT
+ user_trace_start ();
+#endif
+ rdtscll (startTimer_G);
+ }
+#endif
+ return ch32;
default:
- return inb(up->port.iobase + offset);
+ ch8 = inb (up->port.iobase + offset);
+#ifdef CONFIG_SERIAL_LATENCY_TIMING
+ if ((offset == UART_RX) && (ch8 == '\n')) {
+#ifdef CONFIG_PREEMPT_RT
+ user_trace_start ();
+#endif
+ rdtscll (startTimer_G);
+ }
+#endif
+ return ch8;
}
}
-static _INLINE_ void
+
+static void
serial_out(struct uart_8250_port *up, int offset, int value)
{
+#ifdef CONFIG_SERIAL_LATENCY_TIMING
+ if ((offset == UART_TX) && (value == '{')) {
+ latency_serial_out (up, offset, value);
+ }
+#endif
+
offset <<= up->port.regshift;
switch (up->port.iotype) {
diff -ur linux-2.6.14.2-rt12/drivers/serial/Kconfig linux-2.6.14.2-rt12-latency/drivers/serial/Kconfig
--- linux-2.6.14.2-rt12/drivers/serial/Kconfig 2005-11-11 00:33:12.000000000 -0500
+++ linux-2.6.14.2-rt12-latency/drivers/serial/Kconfig 2005-11-15 18:04:59.000000000 -0500
@@ -39,9 +39,16 @@
Most people will say Y or M here, so that they can use serial mice,
modems and similar devices connecting to the standard serial ports.
+config SERIAL_LATENCY_TIMING
+ tristate "serial latency timing"
+ depends on SERIAL_8250
+ ---help---
+ This modifies the 8250 serial driver for serial <-> user-space
+ latency testing.
+
config SERIAL_8250_CONSOLE
bool "Console on 8250/16550 and compatible serial port"
- depends on SERIAL_8250=y
+ depends on SERIAL_8250=y && !SERIAL_LATENCY_TIMING
select SERIAL_CORE_CONSOLE
---help---
If you say Y here, it will be possible to use a serial port as the
Only in linux-2.6.14.2-rt12/fs: exec.c.orig
diff -ur linux-2.6.14.2-rt12/kernel/rcupdate.c linux-2.6.14.2-rt12-latency/kernel/rcupdate.c
--- linux-2.6.14.2-rt12/kernel/rcupdate.c 2005-11-15 19:04:47.000000000 -0500
+++ linux-2.6.14.2-rt12-latency/kernel/rcupdate.c 2005-11-15 18:54:25.000000000 -0500
@@ -566,10 +566,11 @@
long completed; /* Number of last completed batch. */
};
static struct rcu_data rcu_data;
-static struct rcu_ctrlblk rcu_ctrlblk = {
+struct rcu_ctrlblk rcu_ctrlblk = {
.fliplock = RAW_SPIN_LOCK_UNLOCKED,
.completed = 0,
};
+EXPORT_SYMBOL(rcu_ctrlblk);
static DEFINE_PER_CPU(atomic_t [2], rcu_flipctr) =
{ ATOMIC_INIT(0), ATOMIC_INIT(0) };
|