Index: oskittcp/oskittcp/interface.c
===================================================================
--- oskittcp/oskittcp/interface.c	(revision 20264)
+++ oskittcp/oskittcp/interface.c	(working copy)
@@ -66,9 +66,13 @@
 void DeinitOskitTCP() {
 }
 
-void TimerOskitTCP() {
-    tcp_slowtimo();
-    tcp_fasttimo();
+void TimerOskitTCP( int FastTimer, int SlowTimer ) {
+    if ( SlowTimer ) {
+        tcp_slowtimo();
+    }
+    if ( FastTimer ) {
+        tcp_fasttimo();
+    }
 }
 
 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
Index: oskittcp/oskittcp/tcp_output.c
===================================================================
--- oskittcp/oskittcp/tcp_output.c	(revision 20264)
+++ oskittcp/oskittcp/tcp_output.c	(working copy)
@@ -66,7 +66,10 @@
 extern struct mbuf *m_copypack();
 #endif
 
+#define IS_LOOPBACK_ADDR(addr) \
+  ((ntohl(addr) & IN_CLASSA_NET) == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
 
+
 /*
  * Tcp output routine: figure out what should be sent and send it.
  */
@@ -215,8 +218,8 @@
 	win = sbspace(&so->so_rcv);
 
 	/*
-	 * Sender silly window avoidance.  If connection is idle
-	 * and can send all data, a maximum segment,
+	 * Sender silly window avoidance.  If connection is idle or using
+	 * the loopback interface and can send all data, a maximum segment,
 	 * at least a maximum default-size segment do it,
 	 * or are forced, do it; otherwise don't bother.
 	 * If peer's buffer is tiny, then send
@@ -227,7 +230,8 @@
 	if (len) {
 		if (len == tp->t_maxseg)
 			goto send;
-		if ((idle || tp->t_flags & TF_NODELAY) &&
+		if ((idle || tp->t_flags & TF_NODELAY ||
+                     IS_LOOPBACK_ADDR(tp->t_inpcb->inp_laddr.s_addr)) &&
 		    (tp->t_flags & TF_NOPUSH) == 0 &&
 		    len + off >= so->so_snd.sb_cc)
 			goto send;
Index: oskittcp/include/oskittcp.h
===================================================================
--- oskittcp/include/oskittcp.h	(revision 20264)
+++ oskittcp/include/oskittcp.h	(working copy)
@@ -105,7 +105,7 @@
 
 extern void InitOskitTCP();
 extern void DeinitOskitTCP();
-extern void TimerOskitTCP();
+extern void TimerOskitTCP( int FastTimer, int SlowTimer );
 extern void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len );
 extern int  OskitTCPShutdown( void *socket, int disconn_type );
 extern int  OskitTCPSocket( void *Connection, void **ConnectionContext,
Index: ip/transport/tcp/tcp.c
===================================================================
--- ip/transport/tcp/tcp.c	(revision 20264)
+++ ip/transport/tcp/tcp.c	(working copy)
@@ -307,6 +307,68 @@
     TCPWakeup         /* Wakeup */
 };
 
+static KEVENT TimerLoopEvent;
+static HANDLE TimerThreadHandle;
+
+/*
+ * We are running 2 timers here, one with a 200ms interval (fast) and the other
+ * with a 500ms interval (slow). So we need to time out at 200, 400, 500, 600,
+ * 800, 1000 and process the "fast" events at 200, 400, 600, 800, 1000 and the
+ * "slow" events at 500 and 1000.
+ */
+static VOID DDKAPI
+TimerThread(PVOID Context)
+{
+    LARGE_INTEGER Timeout;
+    NTSTATUS Status;
+    unsigned Current, NextFast, NextSlow, Next;
+
+    Current = 0;
+    Next = 0;
+    NextFast = 0;
+    NextSlow = 0;
+    while ( 1 ) {
+        if (Next == NextFast) {
+            NextFast += 2;
+        }
+        if (Next == NextSlow) {
+            NextSlow += 5;
+        }
+        Next = min(NextFast, NextSlow);
+        Timeout.QuadPart = (LONGLONG) (Next - Current) * -1000000; /* 100 ms */
+        Status = KeWaitForSingleObject(&TimerLoopEvent, Executive, KernelMode,
+                                       FALSE, &Timeout);
+        if (STATUS_SUCCESS == Status) {
+            PsTerminateSystemThread(STATUS_SUCCESS);
+        }
+        ASSERT(STATUS_TIMEOUT == Status);
+
+        TcpipRecursiveMutexEnter( &TCPLock, TRUE );
+        TimerOskitTCP( Next == NextFast, Next == NextSlow );
+        if (Next == NextSlow) {
+            DrainSignals();
+        }
+        TcpipRecursiveMutexLeave( &TCPLock );
+
+        Current = Next;
+        if (10 <= Current) {
+            Current = 0;
+            Next = 0;
+            NextFast = 0;
+            NextSlow = 0;
+        }
+    }
+}
+
+static VOID
+StartTimer(VOID)
+{
+    KeInitializeEvent(&TimerLoopEvent, NotificationEvent, FALSE);
+    PsCreateSystemThread(&TimerThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0,
+                         TimerThread, NULL);
+}
+
+
 NTSTATUS TCPStartup(VOID)
 /*
  * FUNCTION: Initializes the TCP subsystem
@@ -336,6 +398,8 @@
 	TAG('T','C','P','S'),           /* Tag */
 	0);                             /* Depth */
 
+    StartTimer();
+
     TCPInitialized = TRUE;
 
     return STATUS_SUCCESS;
@@ -349,9 +413,16 @@
  *     Status of operation
  */
 {
+    LARGE_INTEGER WaitForThread;
+
     if (!TCPInitialized)
 	return STATUS_SUCCESS;
 
+    WaitForThread.QuadPart = -2500000; /* 250 ms */
+    KeSetEvent(&TimerLoopEvent, IO_NO_INCREMENT, TRUE);
+    KeWaitForSingleObject(&TimerThreadHandle, Executive, KernelMode,
+                          FALSE, &WaitForThread);
+
     /* Deregister this protocol with IP layer */
     IPRegisterProtocol(IPPROTO_TCP, NULL);
 
@@ -598,13 +669,7 @@
 }
 
 VOID TCPTimeout(VOID) {
-    static int Times = 0;
-    TcpipRecursiveMutexEnter( &TCPLock, TRUE );
-    if( (Times++ % 5) == 0 ) {
-	TimerOskitTCP();
-    }
-    DrainSignals();
-    TcpipRecursiveMutexLeave( &TCPLock );
+    /* Now handled by TimerThread */
 }
 
 UINT TCPAllocatePort( UINT HintPort ) {
