Index: ev_win32.c
===================================================================
RCS file: /schmorpforge/libev/ev_win32.c,v
retrieving revision 1.12
diff -u -r1.12 ev_win32.c
--- ev_win32.c	29 Jun 2009 07:27:54 -0000	1.12
+++ ev_win32.c	2 Jul 2009 01:28:01 -0000
@@ -39,15 +39,60 @@
 
 #ifdef _WIN32
 
-/* timeb.h is actually xsi legacy functionality */
-#include <sys/timeb.h>
-
 /* note: the comment below could not be substantiated, but what would I care */
 /* MSDN says this is required to handle SIGFPE */
 /* my wild guess would be that using something floating-pointy is required */
 /* for the crt to do something about it */
 volatile double SIGFPE_REQ = 0.0f; 
 
+typedef union {
+  unsigned __int64 ft_i64;
+  FILETIME ft_val;
+} FT_t;
+
+struct timedata {
+  unsigned __int64 base_ticks;
+  unsigned __int64 tick_frequency;
+  FT_t base_systime_as_filetime;
+  unsigned __int64 reset_time;
+};
+
+static struct timedata t;
+
+/* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
+#ifdef __GNUC__
+# define Const64(x) x##LL
+#else
+# define Const64(x) x##i64
+#endif
+#define EPOCH_BIAS  Const64(116444736000000000)
+
+#ifdef Const64
+# ifdef __GNUC__
+#  define IV_1E6LL  1000000LL /* Needed because of Const64() ##-appends LL (or i64). */
+#  define IV_1E7LL  10000000LL
+#  define IV_1E9LL  1000000000LL
+# else
+#  define IV_1E6i64 1000000i64
+#  define IV_1E7i64 10000000i64
+#  define IV_1E9i64 1000000000i64
+# endif
+#endif
+
+#define IV_1E6 1000000
+#define IV_1E7 10000000
+
+#define NV_1E6 1000000.0
+
+/* If the performance counter delta drifts more than 0.5 seconds from the
+ * system time then we recalibrate to the system time.  This means we may
+ * move *backwards* in time! */
+#define MAX_PERF_COUNTER_SKEW Const64(5000000) /* 0.5 seconds */
+
+/* Reset reading from the performance counter every five minutes.
+ * Many PC clocks just seem to be so bad. */
+#define MAX_PERF_COUNTER_TICKS Const64(300000000) /* 300 seconds */
+
 /* oh, the humanity! */
 static int
 ev_pipe (int filedes [2])
@@ -138,15 +183,35 @@
 ev_tstamp
 ev_time (void)
 {
-  FILETIME ft;
-  ULARGE_INTEGER ui;
-
-  GetSystemTimeAsFileTime (&ft);
-  ui.u.LowPart  = ft.dwLowDateTime;
-  ui.u.HighPart = ft.dwHighDateTime;
-
-  /* msvc cannot convert ulonglong to double... yes, it is that sucky */
-  return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7;
+  unsigned __int64 ticks;
+  FT_t ft;
+  
+  if (t.reset_time == 0 || t.base_systime_as_filetime.ft_i64 > t.reset_time) {
+    QueryPerformanceFrequency((LARGE_INTEGER*)&t.tick_frequency);
+    QueryPerformanceCounter((LARGE_INTEGER*)&t.base_ticks);
+    GetSystemTimeAsFileTime(&t.base_systime_as_filetime.ft_val);
+    ft.ft_i64 = t.base_systime_as_filetime.ft_i64;
+    t.reset_time = ft.ft_i64 + MAX_PERF_COUNTER_TICKS;
+  }
+  else {
+    __int64 diff;
+    QueryPerformanceCounter((LARGE_INTEGER*)&ticks);
+    ticks -= t.base_ticks;
+    ft.ft_i64 = t.base_systime_as_filetime.ft_i64
+                + Const64(IV_1E7) * (ticks / t.tick_frequency)
+                +(Const64(IV_1E7) * (ticks % t.tick_frequency)) / t.tick_frequency;
+    diff = ft.ft_i64 - t.base_systime_as_filetime.ft_i64;
+    if (diff < -MAX_PERF_COUNTER_SKEW || diff > MAX_PERF_COUNTER_SKEW) {
+	    t.base_ticks += ticks;
+      GetSystemTimeAsFileTime(&t.base_systime_as_filetime.ft_val);
+      ft.ft_i64 = t.base_systime_as_filetime.ft_i64;
+    }
+  }
+  
+  return 
+    ((ft.ft_i64 - EPOCH_BIAS) / Const64(IV_1E7)) /* seconds since epoch */
+    +
+    (((ft.ft_i64 / Const64(10)) % Const64(IV_1E6)) / NV_1E6); /* microseconds remaining */
 }
 
 #endif
